diff --git a/resources/wx_gui/gui_build.py b/resources/wx_gui/gui_build.py index e0e912590..e0cdc3541 100644 --- a/resources/wx_gui/gui_build.py +++ b/resources/wx_gui/gui_build.py @@ -1,11 +1,16 @@ +# Generate UI for Building OpenCore import wx import logging import threading import traceback -from resources.wx_gui import gui_main_menu, gui_install_oc, gui_support -from resources.build import build from resources import constants +from resources.build import build +from resources.wx_gui import ( + gui_main_menu, + gui_install_oc, + gui_support +) class BuildFrame(wx.Frame): @@ -13,8 +18,8 @@ class BuildFrame(wx.Frame): Create a frame for building OpenCore Uses a Modal Dialog for smoother transition from other frames """ - def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None): - super(BuildFrame, self).__init__(parent, title=title, size=(350, 200), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None) -> None: + super(BuildFrame, self).__init__(parent, title=title, size=(350, 200), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.install_button: wx.Button = None self.text_box: wx.TextCtrl = None @@ -78,7 +83,10 @@ class BuildFrame(wx.Frame): frame.SetSize((-1, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40)) - def _invoke_build(self): + def _invoke_build(self) -> None: + """ + Invokes build function and waits for it to finish + """ while gui_support.PayloadMount(self.constants, self).is_unpack_finished() is False: wx.Yield() @@ -100,7 +108,7 @@ class BuildFrame(wx.Frame): self.on_install() if dialog.ShowModal() == wx.ID_YES else self.install_button.Enable() - def _build(self): + def _build(self) -> None: """ Calls build function and redirects stdout to the text box """ @@ -114,9 +122,12 @@ class BuildFrame(wx.Frame): logger.removeHandler(logger.handlers[2]) - def on_return_to_main_menu(self, event: wx.Event = None): + def on_return_to_main_menu(self, event: wx.Event = None) -> None: + """ + Return to main menu + """ self.frame_modal.Hide() - main_menu_frame = gui_main_menu.MainMenu( + main_menu_frame = gui_main_menu.MainFrame( None, title=self.title, global_constants=self.constants, @@ -127,7 +138,10 @@ class BuildFrame(wx.Frame): self.Destroy() - def on_install(self, event: wx.Event = None): + def on_install(self, event: wx.Event = None) -> None: + """ + Launch install frame + """ self.frame_modal.Destroy() self.Destroy() install_oc_frame = gui_install_oc.InstallOCFrame( diff --git a/resources/wx_gui/gui_download.py b/resources/wx_gui/gui_download.py index 7ba4da5ed..81d56ac4b 100644 --- a/resources/wx_gui/gui_download.py +++ b/resources/wx_gui/gui_download.py @@ -1,14 +1,18 @@ - +# Generate UI for downloading files import wx -from resources import constants, network_handler, utilities +from resources import ( + constants, + network_handler, + utilities +) class DownloadFrame(wx.Frame): """ Update provided frame with download stats """ - def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, download_obj: network_handler.DownloadObject, item_name: str): + def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, download_obj: network_handler.DownloadObject, item_name: str) -> None: self.constants: constants.Constants = global_constants self.title: str = title @@ -23,7 +27,10 @@ class DownloadFrame(wx.Frame): self._generate_elements(self.frame_modal) - def _generate_elements(self, frame: wx.Frame = None) -> None: + def _generate_elements(self, frame: wx.Dialog = None) -> None: + """ + Generate elements for download frame + """ frame = self if not frame else frame @@ -81,6 +88,9 @@ class DownloadFrame(wx.Frame): def terminate_download(self) -> None: + """ + Terminate download + """ if wx.MessageBox("Are you sure you want to cancel the download?", "Cancel Download", wx.YES_NO | wx.ICON_QUESTION | wx.NO_DEFAULT) == wx.YES: self.user_cancelled = True self.download_obj.stop() diff --git a/resources/wx_gui/gui_entry.py b/resources/wx_gui/gui_entry.py index 575876738..3100067e0 100644 --- a/resources/wx_gui/gui_entry.py +++ b/resources/wx_gui/gui_entry.py @@ -1,7 +1,8 @@ +# Entry point for the wxPython GUI import wx import sys -import logging import atexit +import logging from resources import constants from resources.wx_gui import ( @@ -14,21 +15,23 @@ from resources.wx_gui import ( ) from resources.sys_patch import sys_patch_detect + class SupportedEntryPoints: """ Enum for supported entry points """ - MAIN_MENU = gui_main_menu.MainMenu + MAIN_MENU = gui_main_menu.MainFrame BUILD_OC = gui_build.BuildFrame INSTALL_OC = gui_install_oc.InstallOCFrame - SYS_PATCH = gui_sys_patch.SysPatchMenu + SYS_PATCH = gui_sys_patch.SysPatchFrame UPDATE_APP = gui_update.UpdateFrame + class EntryPoint: def __init__(self, global_constants: constants.Constants) -> None: self.app: wx.App = None - self.main_menu_frame: gui_main_menu.MainMenu = None + self.main_menu_frame: gui_main_menu.MainFrame = None self.constants: constants.Constants = global_constants self.constants.gui_mode = True @@ -38,16 +41,17 @@ class EntryPoint: self.app = wx.App() - def start(self, entry: SupportedEntryPoints = gui_main_menu.MainMenu) -> None: + def start(self, entry: SupportedEntryPoints = gui_main_menu.MainFrame) -> None: """ Launches entry point for the wxPython GUI """ self._generate_base_data() if "--gui_patch" in sys.argv or "--gui_unpatch" in sys.argv: - entry = gui_sys_patch.SysPatchMenu + entry = gui_sys_patch.SysPatchFrame patches = sys_patch_detect.DetectRootPatch(self.constants.computer.real_model, self.constants).detect_patch_set() + logging.info(f"- Loading wxPython GUI: {entry.__name__}") self.frame: wx.Frame = entry( None, title=f"{self.constants.patcher_name} ({self.constants.patcher_version})", @@ -57,6 +61,7 @@ class EntryPoint: ) if self.frame: self.frame.SetMenuBar(gui_support.GenerateMenubar().generate()) + atexit.register(self.OnCloseFrame) if "--gui_patch" in sys.argv: @@ -67,7 +72,7 @@ class EntryPoint: self.app.MainLoop() - def OnCloseFrame(self, event: wx.Event = None): + def OnCloseFrame(self, event: wx.Event = None) -> None: """ Closes the wxPython GUI """ diff --git a/resources/wx_gui/gui_help.py b/resources/wx_gui/gui_help.py index 14fb1d819..090472f06 100644 --- a/resources/wx_gui/gui_help.py +++ b/resources/wx_gui/gui_help.py @@ -1,3 +1,4 @@ +# Generate UI for help menu import wx import webbrowser @@ -8,7 +9,7 @@ class HelpFrame(wx.Frame): """ Append to main menu through a modal dialog """ - def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None): + def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None) -> None: self.dialog = wx.Dialog(parent, title=title, size=(300, 200)) @@ -21,7 +22,6 @@ class HelpFrame(wx.Frame): def _generate_elements(self, frame: wx.Frame = None) -> None: """ - Format: - Title: Patcher Resources - Text: Following resources are available: diff --git a/resources/wx_gui/gui_install_oc.py b/resources/wx_gui/gui_install_oc.py index a17e4a110..83f017af8 100644 --- a/resources/wx_gui/gui_install_oc.py +++ b/resources/wx_gui/gui_install_oc.py @@ -12,7 +12,7 @@ class InstallOCFrame(wx.Frame): Create a frame for installing OpenCore to disk """ def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None): - super(InstallOCFrame, self).__init__(parent, title=title, size=(300, 120), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + super(InstallOCFrame, self).__init__(parent, title=title, size=(300, 120), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.constants: constants.Constants = global_constants self.title: str = title @@ -252,6 +252,9 @@ class InstallOCFrame(wx.Frame): def _invoke_install_oc(self, partition: dict) -> None: + """ + Invoke OpenCore installation + """ thread = threading.Thread(target=self._install_oc, args=(partition,)) thread.start() @@ -304,7 +307,7 @@ class InstallOCFrame(wx.Frame): """ Return to main menu """ - main_menu_frame = gui_main_menu.MainMenu( + main_menu_frame = gui_main_menu.MainFrame( None, title=self.title, global_constants=self.constants, diff --git a/resources/wx_gui/gui_macos_installer_download.py b/resources/wx_gui/gui_macos_installer_download.py index f9627f780..430a12f79 100644 --- a/resources/wx_gui/gui_macos_installer_download.py +++ b/resources/wx_gui/gui_macos_installer_download.py @@ -4,7 +4,12 @@ import threading from pathlib import Path -from resources.wx_gui import gui_main_menu, gui_support, gui_download, gui_macos_installer_flash +from resources.wx_gui import ( + gui_main_menu, + gui_support, + gui_download, + gui_macos_installer_flash +) from resources import ( constants, macos_installer_handler, @@ -14,7 +19,7 @@ from resources import ( ) -class macOSInstallerFrame(wx.Frame): +class macOSInstallerDownloadFrame(wx.Frame): """ Create a frame for downloading and creating macOS installers Uses a Modal Dialog for smoother transition from other frames @@ -69,8 +74,11 @@ class macOSInstallerFrame(wx.Frame): frame.SetSize((-1, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40)) - def _generate_catalog_frame(self) -> wx.Frame: - super(macOSInstallerFrame, self).__init__(None, title=self.title, size=(300, 200), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + def _generate_catalog_frame(self) -> None: + """ + Generate frame to display available installers + """ + super(macOSInstallerDownloadFrame, self).__init__(None, title=self.title, size=(300, 200), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.SetPosition((self.parent.GetPosition()[0], self.parent.GetPosition()[1])) # Title: Pulling installer catalog @@ -107,6 +115,9 @@ class macOSInstallerFrame(wx.Frame): def _display_available_installers(self, event: wx.Event = None, show_full: bool = False) -> None: + """ + Display available installers in frame + """ self.frame_modal.Destroy() dialog = wx.Dialog(self, title="Select macOS Installer", size=(300, 200)) @@ -155,6 +166,9 @@ class macOSInstallerFrame(wx.Frame): def on_download_installer(self, app: dict) -> None: + """ + Download macOS installer + """ host_space = utilities.get_free_space() needed_space = app['Size'] * 2 if host_space < needed_space: @@ -182,7 +196,9 @@ class macOSInstallerFrame(wx.Frame): def _validate_installer(self, chunklist_link: str) -> None: - + """ + Validate macOS installer + """ self.SetSize((300, 200)) for child in self.GetChildren(): child.Destroy() @@ -284,14 +300,20 @@ class macOSInstallerFrame(wx.Frame): self.on_existing() - def on_download(self, event: wx.Event) -> None: + """ + Display available macOS versions to download + """ self.frame_modal.Close() self.parent.Hide() self._generate_catalog_frame() self.parent.Close() + def on_existing(self, event: wx.Event = None) -> None: + """ + Display local macOS installers + """ frames = [self, self.frame_modal, self.parent] for frame in frames: if frame: @@ -308,12 +330,19 @@ class macOSInstallerFrame(wx.Frame): def on_return(self, event: wx.Event) -> None: + """ + Return to main menu (dismiss frame) + """ self.frame_modal.Close() - def on_return_to_main_menu(self, event: wx.Event = None): + + def on_return_to_main_menu(self, event: wx.Event = None) -> None: + """ + Return to main menu + """ if self.frame_modal: self.frame_modal.Hide() - main_menu_frame = gui_main_menu.MainMenu( + main_menu_frame = gui_main_menu.MainFrame( None, title=self.title, global_constants=self.constants, diff --git a/resources/wx_gui/gui_macos_installer_flash.py b/resources/wx_gui/gui_macos_installer_flash.py index 5a9e5b812..2d9a6c739 100644 --- a/resources/wx_gui/gui_macos_installer_flash.py +++ b/resources/wx_gui/gui_macos_installer_flash.py @@ -1,10 +1,10 @@ import wx -import logging -import threading import time -import subprocess +import logging import plistlib import tempfile +import threading +import subprocess from pathlib import Path @@ -22,7 +22,7 @@ from data import os_data class macOSInstallerFlashFrame(wx.Frame): def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None): - super(macOSInstallerFlashFrame, self).__init__(parent, title=title, size=(350, 200), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + super(macOSInstallerFlashFrame, self).__init__(parent, title=title, size=(350, 200), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.constants: constants.Constants = global_constants self.title: str = title @@ -546,7 +546,7 @@ class macOSInstallerFlashFrame(wx.Frame): def on_return_to_main_menu(self, event: wx.Event = None): if self.frame_modal: self.frame_modal.Hide() - main_menu_frame = gui_main_menu.MainMenu( + main_menu_frame = gui_main_menu.MainFrame( None, title=self.title, global_constants=self.constants, diff --git a/resources/wx_gui/gui_main_menu.py b/resources/wx_gui/gui_main_menu.py index 4445087d8..5c2bd6568 100644 --- a/resources/wx_gui/gui_main_menu.py +++ b/resources/wx_gui/gui_main_menu.py @@ -1,8 +1,6 @@ import wx import logging -import webbrowser import threading -import sys from resources.wx_gui import ( gui_build, @@ -13,13 +11,17 @@ from resources.wx_gui import ( gui_settings, gui_update, ) - -from resources import constants, global_settings, updates +from resources import ( + constants, + global_settings, + updates +) from data import os_data -class MainMenu(wx.Frame): + +class MainFrame(wx.Frame): def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None): - super(MainMenu, self).__init__(parent, title=title, size=(350, 300), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + super(MainFrame, self).__init__(parent, title=title, size=(350, 300), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.constants: constants.Constants = global_constants self.title: str = title @@ -105,7 +107,7 @@ class MainMenu(wx.Frame): self, f"We found you are currently booting OpenCore built for a different unit: {self.constants.computer.build_model}\n\nWe builds configs to match individual units and cannot be mixed or reused with different Macs.\n\nPlease Build and Install a new OpenCore config, and reboot your Mac.", "Unsupported Configuration Detected!", - style = wx.OK | wx.ICON_EXCLAMATION + style=wx.OK | wx.ICON_EXCLAMATION ) pop_up.ShowModal() self.on_build_and_install() @@ -162,7 +164,7 @@ class MainMenu(wx.Frame): def on_post_install_root_patch(self, event: wx.Event = None): self.Hide() - gui_sys_patch.SysPatchMenu( + gui_sys_patch.SysPatchFrame( parent=None, title=self.title, global_constants=self.constants, @@ -172,7 +174,7 @@ class MainMenu(wx.Frame): def on_create_macos_installer(self, event: wx.Event = None): - gui_macos_installer_download.macOSInstallerFrame( + gui_macos_installer_download.macOSInstallerDownloadFrame( parent=self, title=self.title, global_constants=self.constants, diff --git a/resources/wx_gui/gui_settings.py b/resources/wx_gui/gui_settings.py index 0772eea1c..09f81ecd7 100644 --- a/resources/wx_gui/gui_settings.py +++ b/resources/wx_gui/gui_settings.py @@ -1,15 +1,29 @@ import wx import wx.adv +import pprint import logging import py_sip_xnu -import pprint import subprocess + from pathlib import Path -from resources.wx_gui import gui_support, gui_update +from resources.wx_gui import ( + gui_support, + gui_update +) +from resources import ( + constants, + global_settings, + defaults, + generate_smbios +) +from data import ( + model_array, + sip_data, + smbios_data, + os_data +) -from resources import constants, global_settings, defaults, generate_smbios -from data import model_array, sip_data, smbios_data, os_data class SettingsFrame(wx.Frame): """ @@ -898,16 +912,6 @@ class SettingsFrame(wx.Frame): generate_serial_number_button.Bind(wx.EVT_BUTTON, self.on_generate_serial_number) - def _populate_non_metal_settings(self, panel: wx.Frame) -> None: - title: wx.StaticText = None - for child in panel.GetChildren(): - if child.GetLabel() == "SkyLight Configuration": - title = child - break - - # Label: To apply, a logout is required - - def _populate_app_stats(self, panel: wx.Frame) -> None: title: wx.StaticText = None for child in panel.GetChildren(): @@ -918,6 +922,8 @@ class SettingsFrame(wx.Frame): lines = f"""Application Information: Application Version: {self.constants.patcher_version} PatcherSupportPkg Version: {self.constants.patcher_support_pkg_version} + Application Path: {self.constants.launcher_binary} + Application Mount: {self.constants.payload_path} Commit Information: Branch: {self.constants.commit_info[0]} diff --git a/resources/wx_gui/gui_support.py b/resources/wx_gui/gui_support.py index 192635867..1aea7db61 100644 --- a/resources/wx_gui/gui_support.py +++ b/resources/wx_gui/gui_support.py @@ -1,10 +1,9 @@ import wx -import time import sys import time import logging -import subprocess import threading +import subprocess from pathlib import Path @@ -23,7 +22,6 @@ class GenerateMenubar: return self.menubar - class GaugePulseCallback: """ Uses an alternative Pulse() method for wx.Gauge() on macOS Monterey+ @@ -113,7 +111,6 @@ class CheckProperties: return True - class PayloadMount: def __init__(self, global_constants: constants.Constants, frame: wx.Frame) -> None: @@ -133,7 +130,7 @@ class PayloadMount: self.frame, f"During unpacking of our internal files, we seemed to have encountered an error.\n\nIf you keep seeing this error, please try rebooting and redownloading the application.", "Internal Error occurred!", - style = wx.OK | wx.ICON_EXCLAMATION + style=wx.OK | wx.ICON_EXCLAMATION ) popup.ShowModal() self.frame.Freeze() @@ -189,6 +186,7 @@ class RelaunchApplicationAsRoot: self.constants = global_constants self.frame: wx.Frame = frame + def relaunch(self, event: wx.Event): self.dialog = wx.MessageDialog( diff --git a/resources/wx_gui/gui_sys_patch.py b/resources/wx_gui/gui_sys_patch.py index fa1414897..5620ababa 100644 --- a/resources/wx_gui/gui_sys_patch.py +++ b/resources/wx_gui/gui_sys_patch.py @@ -1,35 +1,39 @@ import wx import os +import sys +import time import logging import plistlib +import traceback import threading import subprocess -import time -import sys -import traceback + from pathlib import Path -from resources import constants, kdk_handler, utilities, network_handler -from data import os_data +from resources import ( + constants, + kdk_handler, +) from resources.sys_patch import ( sys_patch, sys_patch_detect ) - from resources.wx_gui import ( gui_main_menu, gui_support, gui_download, ) +from data import os_data -class SysPatchMenu(wx.Frame): + +class SysPatchFrame(wx.Frame): """ Create a frame for root patching Uses a Modal Dialog for smoother transition from other frames """ def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None, patches: dict = {}): - super(SysPatchMenu, self).__init__(parent, title=title, size=(350, 260), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + super(SysPatchFrame, self).__init__(parent, title=title, size=(350, 260), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.title = title self.constants: constants.Constants = global_constants @@ -158,7 +162,6 @@ class SysPatchMenu(wx.Frame): # Check if OCLP has already applied the same patches no_new_patches = not self._check_if_new_patches_needed(patches) if patches else False - if not patches: # Prompt user with no patches found patch_label = wx.StaticText(frame, label="No patches required", pos=(-1, available_label.GetPosition()[1] + 20)) @@ -373,7 +376,7 @@ class SysPatchMenu(wx.Frame): def on_return_to_main_menu(self, event: wx.Event = None): self.frame_modal.Hide() - main_menu_frame = gui_main_menu.MainMenu( + main_menu_frame = gui_main_menu.MainFrame( None, title=self.title, global_constants=self.constants, diff --git a/resources/wx_gui/gui_update.py b/resources/wx_gui/gui_update.py index 043de879c..5b6ecf29b 100644 --- a/resources/wx_gui/gui_update.py +++ b/resources/wx_gui/gui_update.py @@ -1,19 +1,26 @@ +# Generate UI for updating the patcher import wx import sys -import subprocess -import threading -import logging import time +import logging import datetime +import threading +import subprocess + from pathlib import Path from resources.wx_gui import gui_download +from resources import ( + constants, + network_handler, + updates +) -from resources import constants, network_handler, updates - class UpdateFrame(wx.Frame): - + """ + Create a frame for updating the patcher + """ def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: wx.Point, url: str = "", version_label: str = "") -> None: if parent: self.parent: wx.Frame = parent @@ -22,7 +29,7 @@ class UpdateFrame(wx.Frame): child.Hide() parent.Hide() else: - super(UpdateFrame, self).__init__(parent, title=title, size=(350, 300), style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + super(UpdateFrame, self).__init__(parent, title=title, size=(350, 300), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) self.title: str = title self.constants: constants.Constants = global_constants @@ -150,13 +157,14 @@ class UpdateFrame(wx.Frame): - def _extract_update(self): - # Extract update + def _extract_update(self) -> None: + """ + Extracts the update + """ logging.info("Extracting update") if Path(self.application_path).exists(): subprocess.run(["rm", "-rf", str(self.application_path)]) - # Some hell spawn at Github decided to double zip our Github Actions artifacts # So we need to unzip it twice loop = 0 @@ -177,8 +185,10 @@ class UpdateFrame(wx.Frame): wx.CallAfter(sys.exit, 1) - def _install_update(self): - # Install update + def _install_update(self) -> None: + """ + Installs update to '/Library/Application Support/Dortania/OpenCore-Patcher.app' + """ logging.info(f"Installing update: {self.application_path}") # Create bash script to run as root @@ -234,7 +244,9 @@ EOF wx.CallAfter(sys.exit, 1) - def _launch_update(self): - # Launch update + def _launch_update(self) -> None: + """ + Launches newly installed update + """ logging.info("Launching update: '/Library/Application Support/Dortania/OpenCore-Patcher.app'") subprocess.Popen(["/Library/Application Support/Dortania/OpenCore-Patcher.app/Contents/MacOS/OpenCore-Patcher"])