Make Windows docker link clickable, and make Windows installer add a start menu shortcut

This commit is contained in:
Micah Lee 2020-10-28 16:48:16 -07:00
parent 10dfc1441b
commit 1116c9a029
No known key found for this signature in database
GPG key ID: 403C2657CD994F73
2 changed files with 263 additions and 224 deletions

View file

@ -74,6 +74,7 @@ class DockerInstaller(QtWidgets.QDialog):
self.task_label = QtWidgets.QLabel() self.task_label = QtWidgets.QLabel()
self.task_label.setAlignment(QtCore.Qt.AlignCenter) self.task_label.setAlignment(QtCore.Qt.AlignCenter)
self.task_label.setWordWrap(True) self.task_label.setWordWrap(True)
self.task_label.setOpenExternalLinks(True)
self.progress = QtWidgets.QProgressBar() self.progress = QtWidgets.QProgressBar()
self.progress.setMinimum(0) self.progress.setMinimum(0)

View file

@ -1,225 +1,263 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import uuid import uuid
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
def build_data(dirname, dir_prefix, id_, name): def build_data(dirname, dir_prefix, id_, name):
data = { data = {
"id": id_, "id": id_,
"name": name, "name": name,
"files": [], "files": [],
"dirs": [], "dirs": [],
} }
for basename in os.listdir(dirname): for basename in os.listdir(dirname):
filename = os.path.join(dirname, basename) filename = os.path.join(dirname, basename)
if os.path.isfile(filename): if os.path.isfile(filename):
data["files"].append(os.path.join(dir_prefix, basename)) data["files"].append(os.path.join(dir_prefix, basename))
elif os.path.isdir(filename): elif os.path.isdir(filename):
if id_ == "INSTALLDIR": if id_ == "INSTALLDIR":
id_prefix = "Folder" id_prefix = "Folder"
else: else:
id_prefix = id_ id_prefix = id_
data["dirs"].append( data["dirs"].append(
build_data( build_data(
os.path.join(dirname, basename), os.path.join(dirname, basename),
os.path.join(dir_prefix, basename), os.path.join(dir_prefix, basename),
f"{id_prefix}{basename.capitalize()}", f"{id_prefix}{basename.capitalize()}",
basename, basename,
) )
) )
if len(data["files"]) > 0: if len(data["files"]) > 0:
if id_ == "INSTALLDIR": if id_ == "INSTALLDIR":
data["component_id"] = "ApplicationFiles" data["component_id"] = "ApplicationFiles"
else: else:
data["component_id"] = "FolderComponent" + id_[len("Folder") :] data["component_id"] = "FolderComponent" + id_[len("Folder") :]
data["component_guid"] = str(uuid.uuid4()) data["component_guid"] = str(uuid.uuid4())
return data return data
def build_dir_xml(root, data): def build_dir_xml(root, data):
attrs = {} attrs = {}
if "id" in data: if "id" in data:
attrs["Id"] = data["id"] attrs["Id"] = data["id"]
if "name" in data: if "name" in data:
attrs["Name"] = data["name"] attrs["Name"] = data["name"]
el = ET.SubElement(root, "Directory", attrs) el = ET.SubElement(root, "Directory", attrs)
for subdata in data["dirs"]: for subdata in data["dirs"]:
build_dir_xml(el, subdata) build_dir_xml(el, subdata)
# If this is the ProgramMenuSubfolder, add the menu component
def build_components_xml(root, data): if "id" in data and data["id"] == "ProgramMenuSubfolder":
component_ids = [] component_el = ET.SubElement(
if "component_id" in data: el,
component_ids.append(data["component_id"]) "Component",
Id="ApplicationShortcuts",
for subdata in data["dirs"]: Guid="539e7de8-a124-4c09-aa55-0dd516aad7bc",
if "component_guid" in subdata: )
dir_ref_el = ET.SubElement(root, "DirectoryRef", Id=subdata["id"]) ET.SubElement(
component_el = ET.SubElement( component_el,
dir_ref_el, "Shortcut",
"Component", Id="ApplicationShortcut1",
Id=subdata["component_id"], Name="Dangerzone",
Guid=subdata["component_guid"], Description="Dangerzone",
) Target="[INSTALLDIR]dangerzone.exe",
for filename in subdata["files"]: WorkingDirectory="INSTALLDIR",
file_el = ET.SubElement( )
component_el, "File", Source=filename, Id="file_" + uuid.uuid4().hex ET.SubElement(
) component_el,
"RegistryValue",
component_ids += build_components_xml(root, subdata) Root="HKCU",
Key="Software\First Look Media\Dangerzone",
return component_ids Name="installed",
Type="integer",
Value="1",
def main(): KeyPath="yes",
version_filename = os.path.join( )
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), ET.SubElement(
"dangerzone", component_el, "RemoveFolder", Id="ProgramMenuSubfolder", On="uninstall"
"__init__.py", )
)
with open(version_filename) as f:
for line in f.readlines(): def build_components_xml(root, data):
if line.startswith("dangerzone_version ="): component_ids = []
version = line.split('"')[1] if "component_id" in data:
break component_ids.append(data["component_id"])
dist_dir = os.path.join( for subdata in data["dirs"]:
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), if "component_guid" in subdata:
"dist", dir_ref_el = ET.SubElement(root, "DirectoryRef", Id=subdata["id"])
"dangerzone", component_el = ET.SubElement(
) dir_ref_el,
if not os.path.exists(dist_dir): "Component",
print( Id=subdata["component_id"],
"You must run step1-build-exe.bat to build dangerzone binary before running this" Guid=subdata["component_guid"],
) )
return for filename in subdata["files"]:
file_el = ET.SubElement(
data = { component_el, "File", Source=filename, Id="file_" + uuid.uuid4().hex
"id": "TARGETDIR", )
"name": "SourceDir",
"dirs": [ component_ids += build_components_xml(root, subdata)
{
"id": "ProgramFilesFolder", return component_ids
"dirs": [],
}
], def main():
} version_filename = os.path.join(
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
data["dirs"][0]["dirs"].append( "dangerzone",
build_data( "__init__.py",
dist_dir, )
os.path.join("..", "..", "dist", "dangerzone"), with open(version_filename) as f:
"INSTALLDIR", for line in f.readlines():
"Dangerzone", if line.startswith("dangerzone_version ="):
) version = line.split('"')[1]
) break
root_el = ET.Element("Wix", xmlns="http://schemas.microsoft.com/wix/2006/wi") dist_dir = os.path.join(
product_el = ET.SubElement( os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
root_el, "dist",
"Product", "dangerzone",
Name="Dangerzone", )
Manufacturer="First Look Media", if not os.path.exists(dist_dir):
Id="f40ff0a9-ebf8-4e1e-9bce-6ab5c74fe119", print(
UpgradeCode="$(var.ProductUpgradeCode)", "You must run step1-build-exe.bat to build dangerzone binary before running this"
Language="1033", )
Codepage="1252", return
Version="$(var.ProductVersion)",
) data = {
ET.SubElement( "id": "TARGETDIR",
product_el, "name": "SourceDir",
"Package", "dirs": [
Id="*", {
Keywords="Installer", "id": "ProgramFilesFolder",
Description="Dangerzone $(var.ProductVersion) Installer", "dirs": [],
Manufacturer="First Look Media", },
InstallerVersion="100", {
Languages="1033", "id": "ProgramMenuFolder",
Compressed="yes", "dirs": [
SummaryCodepage="1252", {"id": "ProgramMenuSubfolder", "name": "Dangerzone", "dirs": []}
) ],
ET.SubElement(product_el, "Media", Id="1", Cabinet="product.cab", EmbedCab="yes") },
ET.SubElement( ],
product_el, "Icon", Id="ProductIcon", SourceFile="..\\..\\share\\dangerzone.ico" }
)
ET.SubElement(product_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon") data["dirs"][0]["dirs"].append(
ET.SubElement( build_data(
product_el, dist_dir,
"Property", os.path.join("..", "..", "dist", "dangerzone"),
Id="ARPHELPLINK", "INSTALLDIR",
Value="https://github.com/firstlookmedia/dangerzone", "Dangerzone",
) )
ET.SubElement( )
product_el,
"Property", root_el = ET.Element("Wix", xmlns="http://schemas.microsoft.com/wix/2006/wi")
Id="ARPURLINFOABOUT", product_el = ET.SubElement(
Value="https://tech.firstlook.media", root_el,
) "Product",
ET.SubElement(product_el, "UIRef", Id="WixUI_Minimal") Name="Dangerzone",
ET.SubElement(product_el, "UIRef", Id="WixUI_ErrorProgressText") Manufacturer="First Look Media",
ET.SubElement( Id="f40ff0a9-ebf8-4e1e-9bce-6ab5c74fe119",
product_el, UpgradeCode="$(var.ProductUpgradeCode)",
"WixVariable", Language="1033",
Id="WixUILicenseRtf", Codepage="1252",
Value="..\\..\\install\\windows\\license.rtf", Version="$(var.ProductVersion)",
) )
ET.SubElement( ET.SubElement(
product_el, product_el,
"WixVariable", "Package",
Id="WixUIDialogBmp", Id="*",
Value="..\\..\\install\\windows\\dialog.bmp", Keywords="Installer",
) Description="Dangerzone $(var.ProductVersion) Installer",
upgrade_el = ET.SubElement(product_el, "Upgrade", Id="$(var.ProductUpgradeCode)") Manufacturer="First Look Media",
ET.SubElement( InstallerVersion="100",
upgrade_el, Languages="1033",
"UpgradeVersion", Compressed="yes",
Minimum="$(var.ProductVersion)", SummaryCodepage="1252",
OnlyDetect="yes", )
Property="NEWERVERSIONDETECTED", ET.SubElement(product_el, "Media", Id="1", Cabinet="product.cab", EmbedCab="yes")
) ET.SubElement(
ET.SubElement( product_el, "Icon", Id="ProductIcon", SourceFile="..\\..\\share\\dangerzone.ico"
upgrade_el, )
"UpgradeVersion", ET.SubElement(product_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon")
Minimum="0.0.0", ET.SubElement(
Maximum="$(var.ProductVersion)", product_el,
IncludeMinimum="yes", "Property",
IncludeMaximum="no", Id="ARPHELPLINK",
Property="OLDERVERSIONBEINGUPGRADED", Value="https://github.com/firstlookmedia/dangerzone",
) )
condition_el = ET.SubElement( ET.SubElement(
product_el, product_el,
"Condition", "Property",
Message="A newer version of this software is already installed.", Id="ARPURLINFOABOUT",
) Value="https://tech.firstlook.media",
condition_el.text = "NOT NEWERVERSIONDETECTED" )
ET.SubElement(product_el, "UIRef", Id="WixUI_Minimal")
build_dir_xml(product_el, data) ET.SubElement(product_el, "UIRef", Id="WixUI_ErrorProgressText")
component_ids = build_components_xml(product_el, data) ET.SubElement(
product_el,
install_exec_seq_el = ET.SubElement( "WixVariable",
product_el, Id="WixUILicenseRtf",
"InstallExecuteSequence", Value="..\\..\\install\\windows\\license.rtf",
) )
ET.SubElement( ET.SubElement(
install_exec_seq_el, "RemoveExistingProducts", After="InstallValidate" product_el,
) "WixVariable",
Id="WixUIDialogBmp",
feature_el = ET.SubElement(product_el, "Feature", Id="DefaultFeature", Level="1") Value="..\\..\\install\\windows\\dialog.bmp",
for component_id in component_ids: )
ET.SubElement(feature_el, "ComponentRef", Id=component_id) upgrade_el = ET.SubElement(product_el, "Upgrade", Id="$(var.ProductUpgradeCode)")
ET.SubElement(
print('<?xml version="1.0" encoding="windows-1252"?>') upgrade_el,
print(f'<?define ProductVersion = "{version}"?>') "UpgradeVersion",
print('<?define ProductUpgradeCode = "12b9695c-965b-4be0-bc33-21274e809576"?>') Minimum="$(var.ProductVersion)",
OnlyDetect="yes",
ET.indent(root_el) Property="NEWERVERSIONDETECTED",
ET.dump(root_el) )
ET.SubElement(
upgrade_el,
if __name__ == "__main__": "UpgradeVersion",
Minimum="0.0.0",
Maximum="$(var.ProductVersion)",
IncludeMinimum="yes",
IncludeMaximum="no",
Property="OLDERVERSIONBEINGUPGRADED",
)
condition_el = ET.SubElement(
product_el,
"Condition",
Message="A newer version of this software is already installed.",
)
condition_el.text = "NOT NEWERVERSIONDETECTED"
build_dir_xml(product_el, data)
component_ids = build_components_xml(product_el, data)
install_exec_seq_el = ET.SubElement(
product_el,
"InstallExecuteSequence",
)
ET.SubElement(
install_exec_seq_el, "RemoveExistingProducts", After="InstallValidate"
)
feature_el = ET.SubElement(product_el, "Feature", Id="DefaultFeature", Level="1")
for component_id in component_ids:
ET.SubElement(feature_el, "ComponentRef", Id=component_id)
ET.SubElement(feature_el, "ComponentRef", Id="ApplicationShortcuts")
print('<?xml version="1.0" encoding="windows-1252"?>')
print(f'<?define ProductVersion = "{version}"?>')
print('<?define ProductUpgradeCode = "12b9695c-965b-4be0-bc33-21274e809576"?>')
ET.indent(root_el)
ET.dump(root_el)
if __name__ == "__main__":
main() main()