diff --git a/Build-Binary.command b/Build-Binary.command index 83721de0d..9251b27d2 100755 --- a/Build-Binary.command +++ b/Build-Binary.command @@ -148,6 +148,14 @@ class CreateBinary: print(build_result.stderr.decode('utf-8')) raise Exception("Build failed") + # Next embed support icns into ./Resources + print("- Embedding icns...") + for file in Path("payloads/Icon/AppIcons").glob("*.icns"): + subprocess.run( + ["cp", str(file), "./dist/OpenCore-Patcher.app/Contents/Resources/"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) + diff --git a/payloads/Icon/AppIcons/OC-Build.icns b/payloads/Icon/AppIcons/OC-Build.icns new file mode 100644 index 000000000..97acf17cc Binary files /dev/null and b/payloads/Icon/AppIcons/OC-Build.icns differ diff --git a/payloads/Icon/AppIcons/OC-Installer.icns b/payloads/Icon/AppIcons/OC-Installer.icns new file mode 100644 index 000000000..1bbaac873 Binary files /dev/null and b/payloads/Icon/AppIcons/OC-Installer.icns differ diff --git a/payloads/Icon/AppIcons/OC-Patch.icns b/payloads/Icon/AppIcons/OC-Patch.icns new file mode 100644 index 000000000..24a44266b Binary files /dev/null and b/payloads/Icon/AppIcons/OC-Patch.icns differ diff --git a/payloads/Icon/AppIcons/OC-Support.icns b/payloads/Icon/AppIcons/OC-Support.icns new file mode 100644 index 000000000..b3c2019e5 Binary files /dev/null and b/payloads/Icon/AppIcons/OC-Support.icns differ diff --git a/resources/constants.py b/resources/constants.py index c5946e969..02bde4eaa 100644 --- a/resources/constants.py +++ b/resources/constants.py @@ -500,7 +500,7 @@ class Constants: @property def apple_isight_path(self): return self.payload_kexts_path / Path(f"Misc/LegacyUSBVideoSupport-v{self.apple_isight_version}.zip") - + @property def legacy_keyboard_path(self): return self.payload_kexts_path / Path(f"Misc/LegacyKeyboardInjector-v{self.legacy_keyboard}.zip") @@ -673,6 +673,12 @@ class Constants: def kdk_download_path(self): return self.payload_path / Path("KDK.dmg") + @property + def icns_resource_path(self): + if self.launcher_script: + return self.payload_path / Path("Icon/AppIcons") + return Path(self.launcher_binary).parent.parent / Path("Resources") + sbm_values = [ "j137ap", # iMacPro1,1 diff --git a/resources/wx_gui/gui_build.py b/resources/wx_gui/gui_build.py index 2edf7a19b..a9a6487b0 100644 --- a/resources/wx_gui/gui_build.py +++ b/resources/wx_gui/gui_build.py @@ -20,6 +20,7 @@ class BuildFrame(wx.Frame): """ 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)) + gui_support.GenerateMenubar(self, global_constants).generate() self.install_button: wx.Button = None self.text_box: wx.TextCtrl = None @@ -36,7 +37,7 @@ class BuildFrame(wx.Frame): if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: self.constants.update_stage = gui_support.AutoUpdateStages.BUILDING - self.SetPosition(screen_location) if screen_location else self.Centre() + self.Centre() self.frame_modal.ShowWindowModal() self._invoke_build() diff --git a/resources/wx_gui/gui_download.py b/resources/wx_gui/gui_download.py index 96b139129..1f15cecec 100644 --- a/resources/wx_gui/gui_download.py +++ b/resources/wx_gui/gui_download.py @@ -13,7 +13,6 @@ 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) -> None: - self.constants: constants.Constants = global_constants self.title: str = title self.parent: wx.Frame = parent diff --git a/resources/wx_gui/gui_entry.py b/resources/wx_gui/gui_entry.py index c8ef7e0f1..49a92605e 100644 --- a/resources/wx_gui/gui_entry.py +++ b/resources/wx_gui/gui_entry.py @@ -60,8 +60,6 @@ class EntryPoint: screen_location=None, **({"patches": patches} if "--gui_patch" in sys.argv or "--gui_unpatch" in sys.argv else {}) ) - if self.frame: - gui_support.GenerateMenubar(self.frame, self.constants).generate() atexit.register(self.OnCloseFrame) diff --git a/resources/wx_gui/gui_install_oc.py b/resources/wx_gui/gui_install_oc.py index 6d0b38669..e503a5b74 100644 --- a/resources/wx_gui/gui_install_oc.py +++ b/resources/wx_gui/gui_install_oc.py @@ -13,6 +13,7 @@ class InstallOCFrame(wx.Frame): """ 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)) + gui_support.GenerateMenubar(self, global_constants).generate() self.constants: constants.Constants = global_constants self.title: str = title @@ -30,7 +31,7 @@ class InstallOCFrame(wx.Frame): if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: self.constants.update_stage = gui_support.AutoUpdateStages.INSTALLING - self.SetPosition(screen_location) if screen_location else self.Centre() + self.Centre() self.Show() self._display_disks() diff --git a/resources/wx_gui/gui_macos_installer_download.py b/resources/wx_gui/gui_macos_installer_download.py index 35bd4e819..c0fd6d876 100644 --- a/resources/wx_gui/gui_macos_installer_download.py +++ b/resources/wx_gui/gui_macos_installer_download.py @@ -81,7 +81,8 @@ class macOSInstallerDownloadFrame(wx.Frame): 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])) + gui_support.GenerateMenubar(self, self.constants).generate() + self.Centre() # Title: Pulling installer catalog title_label = wx.StaticText(self, label="Pulling installer catalog", pos=(-1,5)) diff --git a/resources/wx_gui/gui_macos_installer_flash.py b/resources/wx_gui/gui_macos_installer_flash.py index 8e79f95e8..5cc2d1d9c 100644 --- a/resources/wx_gui/gui_macos_installer_flash.py +++ b/resources/wx_gui/gui_macos_installer_flash.py @@ -23,6 +23,7 @@ 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)) + gui_support.GenerateMenubar(self, global_constants).generate() self.constants: constants.Constants = global_constants self.title: str = title @@ -37,7 +38,7 @@ class macOSInstallerFlashFrame(wx.Frame): self._generate_elements() - self.SetPosition(screen_location) if screen_location else self.Centre() + self.Centre() self.Show() self._populate_installers() diff --git a/resources/wx_gui/gui_main_menu.py b/resources/wx_gui/gui_main_menu.py index 856742a6b..4316e0062 100644 --- a/resources/wx_gui/gui_main_menu.py +++ b/resources/wx_gui/gui_main_menu.py @@ -23,7 +23,8 @@ from data import os_data class MainFrame(wx.Frame): def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None): - super(MainFrame, 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=(600, 400), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + gui_support.GenerateMenubar(self, global_constants).generate() self.constants: constants.Constants = global_constants self.title: str = title @@ -35,7 +36,7 @@ class MainFrame(wx.Frame): self._generate_elements() - self.SetPosition(screen_location) if screen_location else self.Centre() + self.Centre() self.Show() self._preflight_checks() @@ -58,31 +59,102 @@ class MainFrame(wx.Frame): """ # Title label: OpenCore Legacy Patcher v{X.Y.Z} - title_label = wx.StaticText(self, label=f"OpenCore Legacy Patcher v{self.constants.patcher_version}", pos=(-1,1)) + title_label = wx.StaticText(self, label=f"OpenCore Legacy Patcher v{self.constants.patcher_version}", pos=(-1,10)) title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont")) title_label.Centre(wx.HORIZONTAL) # Text: Model: {Build or Host Model} - model_label = wx.StaticText(self, label=f"Model: {self.constants.custom_model or self.constants.computer.real_model}", pos=(-1,30)) + model_label = wx.StaticText(self, label=f"Model: {self.constants.custom_model or self.constants.computer.real_model}", pos=(-1, title_label.GetPosition()[1] + 25 + )) model_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont")) model_label.Centre(wx.HORIZONTAL) self.model_label = model_label # Buttons: menu_buttons = { - "Build and Install OpenCore": self.on_build_and_install, - "Post-Install Root Patch": self.on_post_install_root_patch, - "Create macOS Installer": self.on_create_macos_installer, - "Settings": self.on_settings, - "Help": self.on_help + "Build and Install OpenCore": { + "function": self.on_build_and_install, + "description": [ + "Prepares provided drive to be able", + "to boot unsupported OSes.", + "Use on installers or internal drives." + ], + "icon": str(self.constants.icns_resource_path / "OC-Build.icns"), + }, + "Create macOS Installer": { + "function": self.on_create_macos_installer, + "description": [ + "Download and flash a macOS", + "Installer for your system.", + ], + "icon": str(self.constants.icns_resource_path / "OC-Installer.icns"), + }, + "Settings ⚙️": { + "function": self.on_settings, + "description": [ + ], + }, + "Post-Install Root Patch": { + "function": self.on_post_install_root_patch, + "description": [ + "Installs hardware drivers and", + "patches for your system after", + "installing a new version of macOS.", + ], + "icon": str(self.constants.icns_resource_path / "OC-Patch.icns"), + }, + + "Support": { + "function": self.on_help, + "description": [ + "Resources for OpenCore Legacy", + "Patcher.", + ], + "icon": str(self.constants.icns_resource_path / "OC-Support.icns"), + }, } - button_y = model_label.GetPosition()[1] + 20 + button_x = 30 + button_y = model_label.GetPosition()[1] + 30 + rollover = len(menu_buttons) / 2 + if rollover % 1 != 0: + rollover = int(rollover) + 1 + index = 0 + max_height = 0 for button_name, button_function in menu_buttons.items(): - button = wx.Button(self, label=button_name, pos=(-1, button_y), size=(200, 30)) - button.Bind(wx.EVT_BUTTON, button_function) - button.Centre(wx.HORIZONTAL) + # place icon + if "icon" in button_function: + icon_mac = wx.StaticBitmap(self, bitmap=wx.Bitmap(button_function["icon"], wx.BITMAP_TYPE_ICON), pos=(button_x - 10, button_y), size=(64, 64)) + if button_name == "Post-Install Root Patch": + icon_mac.SetPosition((-1, button_y + 7)) + if button_name == "Create macOS Installer": + icon_mac.SetPosition((button_x - 5, button_y + 3)) + if button_name == "Support": + # icon_mac.SetSize((80, 80)) + icon_mac.SetPosition((button_x - 7, button_y + 3)) + if button_name == "Build and Install OpenCore": + icon_mac.SetSize((70, 70)) + if button_name == "Settings ⚙️": + button_y += 5 + + button = wx.Button(self, label=button_name, pos=(button_x + 70, button_y), size=(180, 30)) + button.Bind(wx.EVT_BUTTON, lambda event, function=button_function["function"]: function(event)) button_y += 30 + # # Text: Description + description_label = wx.StaticText(self, label='\n'.join(button_function["description"]), pos=(button_x + 75, button.GetPosition()[1] + button.GetSize()[1] + 3)) + description_label.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont")) + # button_y += 15 + + for i, line in enumerate(button_function["description"]): + if line == "": + continue + if i == 0: + button_y += 11 + else: + button_y += 13 + + button_y += 25 + if button_name == "Build and Install OpenCore": self.build_button = button if gui_support.CheckProperties(self.constants).host_can_build() is False: @@ -90,14 +162,25 @@ class MainFrame(wx.Frame): elif button_name == "Post-Install Root Patch": if self.constants.detected_os < os_data.os_data.big_sur: button.Disable() + elif button_name == "Settings ⚙️": + button.SetSize((100, -1)) + button.Centre(wx.HORIZONTAL) + description_label.Centre(wx.HORIZONTAL) + + index += 1 + if index == rollover: + max_height = button_y + button_x = 320 + button_y = model_label.GetPosition()[1] + 30 + # Text: Copyright - copy_label = wx.StaticText(self, label=self.constants.copyright_date, pos=(-1, button_y + 10)) + copy_label = wx.StaticText(self, label=self.constants.copyright_date, pos=(-1, max_height - 15)) copy_label.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont")) copy_label.Centre(wx.HORIZONTAL) # Set window size - self.SetSize((350, copy_label.GetPosition()[1] + 50)) + self.SetSize((-1, copy_label.GetPosition()[1] + 50)) def _preflight_checks(self): @@ -195,14 +278,12 @@ class MainFrame(wx.Frame): def on_post_install_root_patch(self, event: wx.Event = None): - self.Hide() gui_sys_patch.SysPatchFrame( - parent=None, + parent=self, title=self.title, global_constants=self.constants, screen_location=self.GetPosition() ) - self.Destroy() def on_create_macos_installer(self, event: wx.Event = None): diff --git a/resources/wx_gui/gui_settings.py b/resources/wx_gui/gui_settings.py index 8b608eda1..d857a99a8 100644 --- a/resources/wx_gui/gui_settings.py +++ b/resources/wx_gui/gui_settings.py @@ -357,6 +357,8 @@ class SettingsFrame(wx.Frame): "Disabled by default due to", "performance degradation", "on some systems from wake.", + "Only applies to BCM943224, 331,", + "360 and 3602 chipsets.", ], }, "Disable Thunderbolt": { diff --git a/resources/wx_gui/gui_sys_patch.py b/resources/wx_gui/gui_sys_patch.py index 8942101f8..aba259521 100644 --- a/resources/wx_gui/gui_sys_patch.py +++ b/resources/wx_gui/gui_sys_patch.py @@ -33,7 +33,7 @@ class SysPatchFrame(wx.Frame): 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(SysPatchFrame, self).__init__(parent, title=title, size=(350, 260), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + self.frame = parent self.title = title self.constants: constants.Constants = global_constants @@ -41,8 +41,7 @@ class SysPatchFrame(wx.Frame): self.return_button: wx.Button = None self.available_patches: bool = False - self.frame_modal = wx.Dialog(self, title=title, size=(360, 200)) - self.SetPosition(screen_location) if screen_location else self.Centre() + self.frame_modal = wx.Dialog(self.frame, title=title, size=(360, 200)) if patches: return @@ -52,7 +51,7 @@ class SysPatchFrame(wx.Frame): if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE: if self.available_patches is False: - gui_support.RestartHost(self).restart(message="No root patch updates needed!\n\nWould you like to reboot to apply the new OpenCore build?") + gui_support.RestartHost(self.frame).restart(message="No root patch updates needed!\n\nWould you like to reboot to apply the new OpenCore build?") def _kdk_download(self, frame: wx.Frame = None) -> bool: @@ -249,7 +248,7 @@ class SysPatchFrame(wx.Frame): # Button: Return to Main Menu return_button = wx.Button(frame, label="Return to Main Menu", pos=(10, revert_button.GetPosition().y + revert_button.GetSize().height), size=(150, 30)) - return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu) + return_button.Bind(wx.EVT_BUTTON, self.on_return_dismiss) return_button.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont")) return_button.Centre(wx.HORIZONTAL) self.return_button = return_button @@ -356,6 +355,12 @@ class SysPatchFrame(wx.Frame): def start_root_patching(self, patches: dict): + self.frame.Close() if self.frame else None + super(SysPatchFrame, self).__init__(None, title=self.title, size=(350, 260), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + gui_support.GenerateMenubar(self, self.constants).generate() + self.Centre() + self.return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu) if self.return_button else None + logging.info("Starting root patching") while gui_support.PayloadMount(self.constants, self).is_unpack_finished() is False: @@ -391,6 +396,12 @@ class SysPatchFrame(wx.Frame): def revert_root_patching(self, patches: dict): + self.frame.Close() if self.frame else None + super(SysPatchFrame, self).__init__(None, title=self.title, size=(350, 260), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + gui_support.GenerateMenubar(self, self.constants).generate() + self.Centre() + self.return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu) if self.return_button else None + logging.info("Reverting root patches") self._generate_modal(patches, "Revert Root Patches") self.return_button.Disable() @@ -422,11 +433,16 @@ class SysPatchFrame(wx.Frame): None, title=self.title, global_constants=self.constants, - screen_location=self.GetScreenPosition() + screen_location=self.GetScreenPosition() if not self.frame else self.frame.GetScreenPosition(), ) main_menu_frame.Show() self.frame_modal.Destroy() - self.Destroy() + self.Destroy() if not self.frame else self.frame.Destroy() + + + def on_return_dismiss(self, event: wx.Event = None): + self.frame_modal.Hide() + self.frame_modal.Destroy() def _post_patch(self): diff --git a/resources/wx_gui/gui_update.py b/resources/wx_gui/gui_update.py index 844ae5ef4..5814d362a 100644 --- a/resources/wx_gui/gui_update.py +++ b/resources/wx_gui/gui_update.py @@ -9,7 +9,7 @@ import subprocess from pathlib import Path -from resources.wx_gui import gui_download +from resources.wx_gui import gui_download, gui_support from resources import ( constants, network_handler, @@ -30,6 +30,7 @@ class UpdateFrame(wx.Frame): parent.Hide() else: super(UpdateFrame, self).__init__(parent, title=title, size=(350, 300), style=wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX)) + gui_support.GenerateMenubar(self, global_constants).generate() self.title: str = title self.constants: constants.Constants = global_constants