mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-23 11:30:15 +10:00
Push experimental build
This commit is contained in:
@@ -15,6 +15,7 @@ class Constants:
|
|||||||
self.patcher_version: str = "0.6.6" # OpenCore-Legacy-Patcher
|
self.patcher_version: str = "0.6.6" # OpenCore-Legacy-Patcher
|
||||||
self.patcher_support_pkg_version: str = "1.0.0" # PatcherSupportPkg
|
self.patcher_support_pkg_version: str = "1.0.0" # PatcherSupportPkg
|
||||||
self.copyright_date: str = "Copyright © 2020-2023 Dortania"
|
self.copyright_date: str = "Copyright © 2020-2023 Dortania"
|
||||||
|
self.patcher_name: str = "OpenCore Legacy Patcher"
|
||||||
|
|
||||||
# URLs
|
# URLs
|
||||||
self.url_patcher_support_pkg: str = "https://github.com/dortania/PatcherSupportPkg/releases/download/"
|
self.url_patcher_support_pkg: str = "https://github.com/dortania/PatcherSupportPkg/releases/download/"
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import threading
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from resources.gui import gui_main
|
from resources.gui import gui_main
|
||||||
|
from resources.wx_gui import gui_entry
|
||||||
from resources import (
|
from resources import (
|
||||||
constants,
|
constants,
|
||||||
utilities,
|
utilities,
|
||||||
@@ -38,7 +39,8 @@ class OpenCoreLegacyPatcher:
|
|||||||
self._generate_base_data()
|
self._generate_base_data()
|
||||||
|
|
||||||
if utilities.check_cli_args() is None:
|
if utilities.check_cli_args() is None:
|
||||||
gui_main.wx_python_gui(self.constants).main_menu(None)
|
# gui_main.wx_python_gui(self.constants).main_menu(None)
|
||||||
|
gui_entry.EntryPoint(self.constants).start()
|
||||||
|
|
||||||
|
|
||||||
def _generate_base_data(self) -> None:
|
def _generate_base_data(self) -> None:
|
||||||
|
|||||||
112
resources/wx_gui/gui_build.py
Normal file
112
resources/wx_gui/gui_build.py
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
import wx
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from resources.wx_gui import gui_main_menu, gui_install_oc, gui_support
|
||||||
|
from resources.build import build
|
||||||
|
from resources import constants
|
||||||
|
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
self.install_button: wx.Button = None
|
||||||
|
self.text_box: wx.TextCtrl = None
|
||||||
|
self.frame_modal: wx.Dialog = None
|
||||||
|
|
||||||
|
self.constants: constants.Constants = global_constants
|
||||||
|
self.title: str = title
|
||||||
|
self.stock_output = logging.getLogger().handlers[0].stream
|
||||||
|
|
||||||
|
self.frame_modal = wx.Dialog(self, title=title, size=(400, 200))
|
||||||
|
|
||||||
|
self._generate_elements(self.frame_modal)
|
||||||
|
|
||||||
|
self.SetPosition(screen_location) if screen_location else self.Centre()
|
||||||
|
self.frame_modal.ShowWindowModal()
|
||||||
|
|
||||||
|
self._invoke_build()
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_elements(self, frame=None) -> None:
|
||||||
|
"""
|
||||||
|
Generate UI elements for build frame
|
||||||
|
|
||||||
|
Format:
|
||||||
|
- Title label: Build and Install OpenCore
|
||||||
|
- Text: Model: {Build or Host Model}
|
||||||
|
- Button: Install OpenCore
|
||||||
|
- Read-only text box: {empty}
|
||||||
|
- Button: Return to Main Menu
|
||||||
|
"""
|
||||||
|
frame = self if not frame else frame
|
||||||
|
|
||||||
|
title_label = wx.StaticText(frame, label="Build and Install OpenCore", pos=(-1,5))
|
||||||
|
title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
title_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
model_label = wx.StaticText(frame, label=f"Model: {self.constants.custom_model or self.constants.computer.real_model}", pos=(-1,30))
|
||||||
|
model_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
model_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Button: Install OpenCore
|
||||||
|
install_button = wx.Button(frame, label="🔩 Install OpenCore", pos=(-1, model_label.GetPosition()[1] + model_label.GetSize()[1]), size=(150, 30))
|
||||||
|
install_button.Bind(wx.EVT_BUTTON, self.on_install)
|
||||||
|
install_button.Center(wx.HORIZONTAL)
|
||||||
|
install_button.Disable()
|
||||||
|
self.install_button = install_button
|
||||||
|
|
||||||
|
# Read-only text box: {empty}
|
||||||
|
text_box = wx.TextCtrl(frame, value="", pos=(-1, install_button.GetPosition()[1] + install_button.GetSize()[1] + 10), size=(400, 350), style=wx.TE_READONLY | wx.TE_MULTILINE | wx.TE_RICH2)
|
||||||
|
text_box.Center(wx.HORIZONTAL)
|
||||||
|
self.text_box = text_box
|
||||||
|
|
||||||
|
# Button: Return to Main Menu
|
||||||
|
return_button = wx.Button(frame, label="Return to Main Menu", pos=(-1, text_box.GetPosition()[1] + text_box.GetSize()[1] + 5), size=(200, 30))
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu)
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Adjust window size to fit all elements
|
||||||
|
frame.SetSize((-1, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
|
||||||
|
|
||||||
|
|
||||||
|
def _invoke_build(self):
|
||||||
|
"""
|
||||||
|
Calls build function and redirects stdout to the text box
|
||||||
|
"""
|
||||||
|
logging.getLogger().handlers[0].stream = gui_support.RedirectText(self.text_box, False)
|
||||||
|
build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants)
|
||||||
|
logging.getLogger().handlers[0].stream = self.stock_output
|
||||||
|
self.install_button.Enable()
|
||||||
|
|
||||||
|
|
||||||
|
def on_return_to_main_menu(self, event):
|
||||||
|
self.frame_modal.Hide()
|
||||||
|
main_menu_frame = gui_main_menu.MainMenu(
|
||||||
|
None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition()
|
||||||
|
)
|
||||||
|
main_menu_frame.Show()
|
||||||
|
self.frame_modal.Destroy()
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def on_install(self, event):
|
||||||
|
self.frame_modal.Destroy()
|
||||||
|
self.Destroy()
|
||||||
|
install_oc_frame = gui_install_oc.InstallOCFrame(
|
||||||
|
None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition()
|
||||||
|
)
|
||||||
|
install_oc_frame.Show()
|
||||||
|
|
||||||
|
|
||||||
70
resources/wx_gui/gui_entry.py
Normal file
70
resources/wx_gui/gui_entry.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
import wx
|
||||||
|
import sys
|
||||||
|
import logging
|
||||||
|
import atexit
|
||||||
|
|
||||||
|
from resources import constants
|
||||||
|
from resources.wx_gui import (
|
||||||
|
gui_main_menu,
|
||||||
|
gui_build,
|
||||||
|
gui_menubar,
|
||||||
|
gui_install_oc
|
||||||
|
)
|
||||||
|
|
||||||
|
class SupportedEntryPoints:
|
||||||
|
"""
|
||||||
|
Enum for supported entry points
|
||||||
|
"""
|
||||||
|
MAIN_MENU = gui_main_menu.MainMenu
|
||||||
|
BUILD_OC = gui_build.BuildFrame
|
||||||
|
INSTALL_OC = gui_install_oc.InstallOCFrame
|
||||||
|
|
||||||
|
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.constants: constants.Constants = global_constants
|
||||||
|
|
||||||
|
self.constants.gui_mode = True
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_base_data(self) -> None:
|
||||||
|
self.app = wx.App()
|
||||||
|
|
||||||
|
|
||||||
|
def start(self, entry: SupportedEntryPoints = gui_main_menu.MainMenu) -> None:
|
||||||
|
"""
|
||||||
|
Launches entry point for the wxPython GUI
|
||||||
|
"""
|
||||||
|
self._generate_base_data()
|
||||||
|
self.frame: wx.Frame = entry(
|
||||||
|
None,
|
||||||
|
title=f"{self.constants.patcher_name} ({self.constants.patcher_version})",
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=None
|
||||||
|
)
|
||||||
|
self.frame.SetMenuBar(gui_menubar.GenerateMenubar().generate())
|
||||||
|
atexit.register(self.OnCloseFrame)
|
||||||
|
|
||||||
|
self.app.MainLoop()
|
||||||
|
|
||||||
|
|
||||||
|
def OnCloseFrame(self, event=None):
|
||||||
|
"""
|
||||||
|
Closes the wxPython GUI
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not self.frame:
|
||||||
|
return
|
||||||
|
|
||||||
|
logging.info("- Cleaning up wxPython GUI")
|
||||||
|
|
||||||
|
self.frame.SetTransparent(0)
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
|
||||||
|
self.frame.DestroyChildren()
|
||||||
|
self.frame.Destroy()
|
||||||
|
self.app.ExitMainLoop()
|
||||||
|
|
||||||
|
sys.exit()
|
||||||
277
resources/wx_gui/gui_install_oc.py
Normal file
277
resources/wx_gui/gui_install_oc.py
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
import wx
|
||||||
|
import threading
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from resources.wx_gui import gui_main_menu, gui_support
|
||||||
|
from resources import constants, install
|
||||||
|
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
self.constants: constants.Constants = global_constants
|
||||||
|
self.title: str = title
|
||||||
|
|
||||||
|
self.available_disks: dict = None
|
||||||
|
self.stock_output = logging.getLogger().handlers[0].stream
|
||||||
|
|
||||||
|
self._generate_elements()
|
||||||
|
|
||||||
|
self.SetPosition(screen_location) if screen_location else self.Centre()
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
self._display_disks()
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_elements(self) -> None:
|
||||||
|
"""
|
||||||
|
Display indeterminate progress bar while collecting disk information
|
||||||
|
|
||||||
|
Format:
|
||||||
|
- Title label: Install OpenCore
|
||||||
|
- Text: Fetching information on local disks...
|
||||||
|
- Progress bar: {indeterminate}
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Title label: Install OpenCore
|
||||||
|
title_label = wx.StaticText(self, label="Install OpenCore", pos=(-1,5))
|
||||||
|
title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
title_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Text: Parsing local disks...
|
||||||
|
text_label = wx.StaticText(self, label="Fetching information on local disks...", pos=(-1,30))
|
||||||
|
text_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
text_label.Center(wx.HORIZONTAL)
|
||||||
|
self.text_label = text_label
|
||||||
|
|
||||||
|
# Progress bar: {indeterminate}
|
||||||
|
progress_bar = wx.Gauge(self, range=100, pos=(-1, text_label.GetPosition()[1] + text_label.GetSize()[1]), size=(150, 30), style=wx.GA_HORIZONTAL | wx.GA_SMOOTH)
|
||||||
|
progress_bar.Center(wx.HORIZONTAL)
|
||||||
|
progress_bar.Pulse()
|
||||||
|
self.progress_bar = progress_bar
|
||||||
|
|
||||||
|
|
||||||
|
def _fetch_disks(self) -> None:
|
||||||
|
"""
|
||||||
|
Fetch information on local disks
|
||||||
|
"""
|
||||||
|
self.available_disks = install.tui_disk_installation(self.constants).list_disks()
|
||||||
|
|
||||||
|
|
||||||
|
def _display_disks(self) -> None:
|
||||||
|
"""
|
||||||
|
Display disk selection dialog
|
||||||
|
"""
|
||||||
|
thread = threading.Thread(target=self._fetch_disks)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
while thread.is_alive():
|
||||||
|
wx.Yield()
|
||||||
|
continue
|
||||||
|
|
||||||
|
self.progress_bar.Hide()
|
||||||
|
|
||||||
|
# Create wxDialog for disk selection
|
||||||
|
dialog = wx.Dialog(self, title=self.title, size=(370, -1))
|
||||||
|
|
||||||
|
# Title label: Install OpenCore
|
||||||
|
title_label = wx.StaticText(dialog, label="Install OpenCore", pos=(-1,5))
|
||||||
|
title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
title_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Text: select disk to install OpenCore onto
|
||||||
|
text_label = wx.StaticText(dialog, label="Select disk to install OpenCore onto:", pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 5))
|
||||||
|
text_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
text_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Add note: "Missing disks? Ensure they're FAT32 or formatted as GUID/GPT"
|
||||||
|
gpt_note = wx.StaticText(dialog, label="Missing disks? Ensure they're FAT32 or formatted as GUID/GPT", pos=(-1, text_label.GetPosition()[1] + text_label.GetSize()[1] + 5))
|
||||||
|
gpt_note.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
gpt_note.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Add buttons for each disk
|
||||||
|
if self.available_disks is None:
|
||||||
|
# Text: Failed to find any applicable disks
|
||||||
|
disk_label = wx.StaticText(dialog, label="Failed to find any applicable disks", pos=(-1, gpt_note.GetPosition()[1] + gpt_note.GetSize()[1] + 5))
|
||||||
|
disk_label.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
disk_label.Center(wx.HORIZONTAL)
|
||||||
|
else:
|
||||||
|
disk_root = self.constants.booted_oc_disk
|
||||||
|
if disk_root:
|
||||||
|
# disk6s1 -> disk6
|
||||||
|
disk_root = self.constants.booted_oc_disk.strip("disk")
|
||||||
|
disk_root = "disk" + disk_root.split("s")[0]
|
||||||
|
|
||||||
|
# Add buttons for each disk
|
||||||
|
for disk in self.available_disks:
|
||||||
|
# Create a button for each disk
|
||||||
|
logging.info(f"- {self.available_disks[disk]['disk']} - {self.available_disks[disk]['name']} - {self.available_disks[disk]['size']}")
|
||||||
|
disk_button = wx.Button(dialog, label=f"{self.available_disks[disk]['disk']} - {self.available_disks[disk]['name']} - {self.available_disks[disk]['size']}", size=(300,30), pos=(-1, gpt_note.GetPosition()[1] + gpt_note.GetSize()[1] + 5))
|
||||||
|
disk_button.Center(wx.HORIZONTAL)
|
||||||
|
disk_button.Bind(wx.EVT_BUTTON, lambda event, disk=disk: self._display_volumes(disk, self.available_disks))
|
||||||
|
if disk_root == self.available_disks[disk]['disk']:
|
||||||
|
disk_button.SetForegroundColour((25, 179, 231))
|
||||||
|
|
||||||
|
|
||||||
|
if disk_root:
|
||||||
|
# Add note: "Note: Blue represent the disk OpenCore is currently booted from"
|
||||||
|
disk_label = wx.StaticText(dialog, label="Note: Blue represent the disk OpenCore is currently booted from", pos=(-1, disk_button.GetPosition()[1] + disk_button.GetSize()[1] + 5))
|
||||||
|
disk_label.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
disk_label.Center(wx.HORIZONTAL)
|
||||||
|
else:
|
||||||
|
disk_label = wx.StaticText(dialog, label="", pos=(-1, disk_button.GetPosition()[1] + 15))
|
||||||
|
disk_label.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
|
||||||
|
# Add button: Search for disks again
|
||||||
|
search_button = wx.Button(dialog, label="Search for disks again", size=(200,30), pos=(-1, disk_label.GetPosition()[1] + disk_label.GetSize()[1] + 5))
|
||||||
|
search_button.Center(wx.HORIZONTAL)
|
||||||
|
search_button.Bind(wx.EVT_BUTTON, self._reload_frame)
|
||||||
|
|
||||||
|
# Add button: Return to main menu
|
||||||
|
return_button = wx.Button(dialog, label="Return to main menu", size=(200,30), pos=(-1, search_button.GetPosition()[1] + 25))
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self._return_to_main_menu)
|
||||||
|
|
||||||
|
# Set size
|
||||||
|
dialog.SetSize((370, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
|
||||||
|
dialog.ShowWindowModal()
|
||||||
|
self.dialog = dialog
|
||||||
|
|
||||||
|
|
||||||
|
def _display_volumes(self, disk: str, dataset: dict) -> None:
|
||||||
|
"""
|
||||||
|
List volumes on disk
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.dialog.Close()
|
||||||
|
|
||||||
|
# Create dialog
|
||||||
|
dialog = wx.Dialog(
|
||||||
|
self,
|
||||||
|
title=f"Volumes on {disk}",
|
||||||
|
style=wx.CAPTION | wx.CLOSE_BOX,
|
||||||
|
size=(370, 300)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add text: "Volumes on {disk}"
|
||||||
|
text_label = wx.StaticText(dialog, label=f"Volumes on {disk}", pos=(-1, 10))
|
||||||
|
text_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
text_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
partitions = install.tui_disk_installation(self.constants).list_partitions(disk, dataset)
|
||||||
|
for partition in partitions:
|
||||||
|
logging.info(f"- {partitions[partition]['partition']} - {partitions[partition]['name']} - {partitions[partition]['size']}")
|
||||||
|
disk_button = wx.Button(dialog, label=f"{partitions[partition]['partition']} - {partitions[partition]['name']} - {partitions[partition]['size']}", size=(300,30), pos=(-1, text_label.GetPosition()[1] + text_label.GetSize()[1] + 5))
|
||||||
|
disk_button.Center(wx.HORIZONTAL)
|
||||||
|
disk_button.Bind(wx.EVT_BUTTON, lambda event, partition=partition: self._install_oc_process(partition))
|
||||||
|
|
||||||
|
# Add button: Return to main menu
|
||||||
|
return_button = wx.Button(dialog, label="Return to main menu", size=(200,30), pos=(-1, disk_button.GetPosition()[1] + disk_button.GetSize()[1]))
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self._return_to_main_menu)
|
||||||
|
|
||||||
|
# Set size
|
||||||
|
dialog.SetSize((370, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
|
||||||
|
|
||||||
|
# Show dialog
|
||||||
|
dialog.ShowWindowModal()
|
||||||
|
self.dialog = dialog
|
||||||
|
|
||||||
|
|
||||||
|
def _install_oc_process(self, partition: dict) -> None:
|
||||||
|
"""
|
||||||
|
Install OpenCore to disk
|
||||||
|
"""
|
||||||
|
self.dialog.Close()
|
||||||
|
|
||||||
|
# Create dialog
|
||||||
|
dialog = wx.Dialog(
|
||||||
|
self,
|
||||||
|
title=f"Installing OpenCore to {partition}",
|
||||||
|
style=wx.CAPTION | wx.CLOSE_BOX,
|
||||||
|
size=(370, 200)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add text: "Installing OpenCore to {partition}"
|
||||||
|
text_label = wx.StaticText(dialog, label=f"Installing OpenCore to {partition}", pos=(-1, 10))
|
||||||
|
text_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
text_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Read-only text box: {empty}
|
||||||
|
text_box = wx.TextCtrl(dialog, value="", pos=(-1, text_label.GetPosition()[1] + text_label.GetSize()[1] + 10), size=(370, 200), style=wx.TE_READONLY | wx.TE_MULTILINE | wx.TE_RICH2)
|
||||||
|
text_box.Center(wx.HORIZONTAL)
|
||||||
|
self.text_box = text_box
|
||||||
|
|
||||||
|
# Add button: Return to main menu
|
||||||
|
return_button = wx.Button(dialog, label="Return to main menu", size=(200,30), pos=(-1, text_box.GetPosition()[1] + text_box.GetSize()[1] + 10))
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self._return_to_main_menu)
|
||||||
|
return_button.Disable()
|
||||||
|
|
||||||
|
# Set size
|
||||||
|
dialog.SetSize((370, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
|
||||||
|
|
||||||
|
# Show dialog
|
||||||
|
dialog.ShowWindowModal()
|
||||||
|
self.dialog = dialog
|
||||||
|
|
||||||
|
# Install OpenCore
|
||||||
|
self._install_oc(partition)
|
||||||
|
return_button.Enable()
|
||||||
|
|
||||||
|
|
||||||
|
def _install_oc(self, partition: dict) -> None:
|
||||||
|
"""
|
||||||
|
Install OpenCore to disk
|
||||||
|
"""
|
||||||
|
logging.info(f"- Installing OpenCore to {partition}")
|
||||||
|
logging.getLogger().handlers[0].stream = gui_support.RedirectText(self.text_box, False)
|
||||||
|
result = install.tui_disk_installation(self.constants).install_opencore(partition)
|
||||||
|
logging.getLogger().handlers[0].stream = self.stock_output
|
||||||
|
|
||||||
|
if result is True:
|
||||||
|
if not self.constants.custom_model:
|
||||||
|
gui_support.RestartHost(self).restart(message="OpenCore has finished installing to disk.\n\nYou will need to reboot and hold the Option key and select OpenCore/Boot EFI's option.\n\nWould you like to reboot?")
|
||||||
|
else:
|
||||||
|
popup_message = wx.MessageDialog(
|
||||||
|
self,
|
||||||
|
f"OpenCore has finished installing to disk.\n\nYou can eject the drive, insert it into the {self.constants.custom_model}, reboot, hold the Option key and select OpenCore/Boot EFI's option.", "Success",
|
||||||
|
wx.OK
|
||||||
|
)
|
||||||
|
popup_message.ShowModal()
|
||||||
|
|
||||||
|
|
||||||
|
def _reload_frame(self, event) -> None:
|
||||||
|
"""
|
||||||
|
Reload frame
|
||||||
|
"""
|
||||||
|
self.Destroy()
|
||||||
|
frame = InstallOCFrame(
|
||||||
|
None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition()
|
||||||
|
)
|
||||||
|
frame.Show()
|
||||||
|
|
||||||
|
|
||||||
|
def _return_to_main_menu(self, event: wx.Event) -> None:
|
||||||
|
"""
|
||||||
|
Return to main menu
|
||||||
|
"""
|
||||||
|
main_menu_frame = gui_main_menu.MainMenu(
|
||||||
|
None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition()
|
||||||
|
)
|
||||||
|
main_menu_frame.Show()
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
99
resources/wx_gui/gui_main_menu.py
Normal file
99
resources/wx_gui/gui_main_menu.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import wx
|
||||||
|
from resources.wx_gui import (
|
||||||
|
gui_build,
|
||||||
|
gui_sys_patch,
|
||||||
|
gui_support,
|
||||||
|
)
|
||||||
|
from resources import constants
|
||||||
|
|
||||||
|
class MainMenu(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))
|
||||||
|
|
||||||
|
self.constants: constants.Constants = global_constants
|
||||||
|
self.title: str = title
|
||||||
|
|
||||||
|
self._generate_elements()
|
||||||
|
|
||||||
|
self.SetPosition(screen_location) if screen_location else self.Centre()
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_elements(self) -> None:
|
||||||
|
"""
|
||||||
|
Generate UI elements for the main menu
|
||||||
|
|
||||||
|
Format:
|
||||||
|
- Title label: OpenCore Legacy Patcher v{X.Y.Z}
|
||||||
|
- Text: Model: {Build or Host Model}
|
||||||
|
- Buttons:
|
||||||
|
- Build and Install OpenCore
|
||||||
|
- Post-Install Root Patch
|
||||||
|
- Create macOS Installer
|
||||||
|
- Settings
|
||||||
|
- Help
|
||||||
|
- Text: Copyright
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 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.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
title_label.Center(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.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
model_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
button_y = model_label.GetPosition()[1] + 20
|
||||||
|
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.Center(wx.HORIZONTAL)
|
||||||
|
button_y += 30
|
||||||
|
|
||||||
|
# Text: Copyright
|
||||||
|
copy_label = wx.StaticText(self, label=self.constants.copyright_date, pos=(-1, button_y + 10))
|
||||||
|
copy_label.SetFont(wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
copy_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set window size
|
||||||
|
self.SetSize((350, copy_label.GetPosition()[1] + 50))
|
||||||
|
|
||||||
|
|
||||||
|
def on_build_and_install(self, event):
|
||||||
|
gui_build.BuildFrame(
|
||||||
|
parent=None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetPosition()
|
||||||
|
)
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def on_post_install_root_patch(self, event):
|
||||||
|
gui_sys_patch.SysPatchMenu(
|
||||||
|
parent=None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetPosition()
|
||||||
|
)
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
|
||||||
|
def on_create_macos_installer(self, event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_settings(self, event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_help(self, event):
|
||||||
|
pass
|
||||||
14
resources/wx_gui/gui_menubar.py
Normal file
14
resources/wx_gui/gui_menubar.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# Generates menubar for wxPython to use
|
||||||
|
|
||||||
|
import wx
|
||||||
|
|
||||||
|
class GenerateMenubar:
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self.menubar: wx.MenuBar = None
|
||||||
|
|
||||||
|
|
||||||
|
def generate(self) -> wx.MenuBar:
|
||||||
|
self.menubar = wx.MenuBar()
|
||||||
|
|
||||||
|
return self.menubar
|
||||||
139
resources/wx_gui/gui_support.py
Normal file
139
resources/wx_gui/gui_support.py
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import wx
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from resources import constants
|
||||||
|
|
||||||
|
class RedirectText(object):
|
||||||
|
"""
|
||||||
|
Redirects stdout to a wxPython TextCtrl
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, aWxTextCtrl: wx.TextCtrl, sleep: bool):
|
||||||
|
self.out = aWxTextCtrl
|
||||||
|
self.sleep = sleep
|
||||||
|
|
||||||
|
def write(self,string):
|
||||||
|
self.out.WriteText(string)
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
if self.sleep:
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
|
def fileno(self):
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def flush(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RestartHost:
|
||||||
|
"""
|
||||||
|
Restarts the host machine
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, frame) -> None:
|
||||||
|
self.frame: wx.Frame = frame
|
||||||
|
|
||||||
|
|
||||||
|
def restart(self, event: wx.Event = None, message: str = ""):
|
||||||
|
self.popup = wx.MessageDialog(
|
||||||
|
self.frame,
|
||||||
|
message,
|
||||||
|
"Reboot to apply?",
|
||||||
|
wx.YES_NO | wx.ICON_INFORMATION
|
||||||
|
)
|
||||||
|
self.popup.SetYesNoLabels("Reboot", "Ignore")
|
||||||
|
answer = self.popup.ShowModal()
|
||||||
|
if answer == wx.ID_YES:
|
||||||
|
# Reboots with Count Down prompt (user can still dismiss if needed)
|
||||||
|
self.frame.Hide()
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
subprocess.call(['osascript', '-e', 'tell app "loginwindow" to «event aevtrrst»'])
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
|
||||||
|
class RelaunchApplicationAsRoot:
|
||||||
|
"""
|
||||||
|
Relaunches the application as root
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, frame: wx.Frame, global_constants: constants.Constants) -> None:
|
||||||
|
self.constants = global_constants
|
||||||
|
self.frame: wx.Frame = frame
|
||||||
|
|
||||||
|
def relaunch(self, event: wx.Event):
|
||||||
|
|
||||||
|
self.dialog = wx.MessageDialog(
|
||||||
|
self.frame,
|
||||||
|
"OpenCore Legacy Patcher needs to relaunch as admin to continue. You will be prompted to enter your password.",
|
||||||
|
"Relaunch as root?",
|
||||||
|
wx.YES_NO | wx.ICON_QUESTION
|
||||||
|
)
|
||||||
|
|
||||||
|
# Show Dialog Box
|
||||||
|
if self.dialog.ShowModal() != wx.ID_YES:
|
||||||
|
logging.info("User cancelled relaunch")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
timer: int = 5
|
||||||
|
program_arguments: str = ""
|
||||||
|
|
||||||
|
if event:
|
||||||
|
if event.GetEventObject() != wx.Menu:
|
||||||
|
try:
|
||||||
|
if event.GetEventObject().GetLabel() in ["Start Root Patching", "Reinstall Root Patches"]:
|
||||||
|
program_arguments = " --gui_patch"
|
||||||
|
elif event.GetEventObject().GetLabel() == "Revert Root Patches":
|
||||||
|
program_arguments = " --gui_unpatch"
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self.constants.launcher_script is None:
|
||||||
|
program_arguments = f"'{self.constants.launcher_binary}'{program_arguments}"
|
||||||
|
else:
|
||||||
|
program_arguments = f"{self.constants.launcher_binary} {self.constants.launcher_script}{program_arguments}"
|
||||||
|
|
||||||
|
# Relaunch as root
|
||||||
|
args = [
|
||||||
|
"osascript",
|
||||||
|
"-e",
|
||||||
|
f'''do shell script "{program_arguments}"'''
|
||||||
|
' with prompt "OpenCore Legacy Patcher needs administrator privileges to relaunch as admin."'
|
||||||
|
" with administrator privileges"
|
||||||
|
" without altering line endings",
|
||||||
|
]
|
||||||
|
|
||||||
|
self.frame.DestroyChildren()
|
||||||
|
self.frame.SetSize(400, 300)
|
||||||
|
|
||||||
|
# Header
|
||||||
|
header = wx.StaticText(self.frame, label="Relaunching as root")
|
||||||
|
header.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
header.Centre(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Add count down label
|
||||||
|
countdown_label = wx.StaticText(self.frame, label=f"Closing old process in {timer} seconds", pos=(0, header.GetPosition().y + header.GetSize().height + 3))
|
||||||
|
countdown_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
countdown_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set size of frame
|
||||||
|
self.frame.SetSize((-1, countdown_label.GetPosition().y + countdown_label.GetSize().height + 40))
|
||||||
|
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
|
||||||
|
logging.info(f"- Relaunching as root with command: {program_arguments}")
|
||||||
|
subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
countdown_label.SetLabel(f"Closing old process in {timer} seconds")
|
||||||
|
time.sleep(1)
|
||||||
|
timer -= 1
|
||||||
|
if timer == 0:
|
||||||
|
break
|
||||||
|
sys.exit(0)
|
||||||
202
resources/wx_gui/gui_sys_patch.py
Normal file
202
resources/wx_gui/gui_sys_patch.py
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
import wx
|
||||||
|
import logging
|
||||||
|
import plistlib
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from resources import constants
|
||||||
|
from resources.sys_patch import (
|
||||||
|
sys_patch,
|
||||||
|
sys_patch_detect
|
||||||
|
)
|
||||||
|
|
||||||
|
from resources.wx_gui import (
|
||||||
|
gui_main_menu
|
||||||
|
)
|
||||||
|
|
||||||
|
class SysPatchMenu(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(SysPatchMenu, self).__init__(parent, title=title, size=(350, 250))
|
||||||
|
|
||||||
|
self.title = title
|
||||||
|
self.constants: constants.Constants = global_constants
|
||||||
|
self.frame_modal: wx.Dialog = None
|
||||||
|
|
||||||
|
self.frame_modal = wx.Dialog(self, title=title, size=(370, 200))
|
||||||
|
|
||||||
|
self._generate_elements(self.frame_modal)
|
||||||
|
|
||||||
|
self.SetPosition(screen_location) if screen_location else self.Centre()
|
||||||
|
self.frame_modal.ShowWindowModal()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_elements(self, frame=None) -> None:
|
||||||
|
"""
|
||||||
|
Generate UI elements for root patching frame
|
||||||
|
|
||||||
|
Format:
|
||||||
|
- Title label: Post-Install Menu
|
||||||
|
- Label: Available patches:
|
||||||
|
- Labels: {patch name}
|
||||||
|
- Button: Start Root Patching
|
||||||
|
- Button: Revert Root Patches
|
||||||
|
- Button: Return to Main Menu
|
||||||
|
"""
|
||||||
|
frame = self if not frame else frame
|
||||||
|
|
||||||
|
title_label = wx.StaticText(frame, label="Post-Install Menu", pos=(-1, 10))
|
||||||
|
title_label.SetFont(wx.Font(19, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
title_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Label: Available patches:
|
||||||
|
available_label = wx.StaticText(frame, label="Available patches for your system:", pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 10))
|
||||||
|
available_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
available_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Labels: {patch name}
|
||||||
|
patches: dict = sys_patch_detect.DetectRootPatch(self.constants.computer.real_model, self.constants).detect_patch_set()
|
||||||
|
can_unpatch: bool = patches["Validation: Unpatching Possible"]
|
||||||
|
|
||||||
|
if not any(not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True for patch in patches):
|
||||||
|
logging.info("- No applicable patches available")
|
||||||
|
patches = []
|
||||||
|
|
||||||
|
# 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 needed", pos=(-1, available_label.GetPosition()[1] + 20))
|
||||||
|
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
patch_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Add Label for each patch
|
||||||
|
i = 0
|
||||||
|
if no_new_patches is True:
|
||||||
|
patch_label = wx.StaticText(frame, label="No new patches needed", pos=(-1, 50))
|
||||||
|
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
patch_label.Center(wx.HORIZONTAL)
|
||||||
|
i = i + 10
|
||||||
|
else:
|
||||||
|
for patch in patches:
|
||||||
|
if (not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True):
|
||||||
|
logging.info(f"- Adding patch: {patch} - {patches[patch]}")
|
||||||
|
patch_label = wx.StaticText(frame, label=f"- {patch}", pos=(available_label.GetPosition()[0]
|
||||||
|
, available_label.GetPosition()[1] + 20 + i))
|
||||||
|
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
i = i + 5
|
||||||
|
|
||||||
|
|
||||||
|
if patches["Validation: Patching Possible"] is False:
|
||||||
|
# Cannot patch due to the following reasons:
|
||||||
|
i = i + 10
|
||||||
|
patch_label = wx.StaticText(frame, label="Cannot patch due to the following reasons:", pos=(-1, patch_label.GetPosition().y + i + 10))
|
||||||
|
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD, False, ".AppleSystemUIFont"))
|
||||||
|
patch_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
|
||||||
|
for patch in patches:
|
||||||
|
if not patch.startswith("Validation"):
|
||||||
|
continue
|
||||||
|
if patches[patch] is False:
|
||||||
|
continue
|
||||||
|
if patch == "Validation: Unpatching Possible":
|
||||||
|
continue
|
||||||
|
|
||||||
|
patch_label = wx.StaticText(frame, label=f"- {patch.split('Validation: ')[1]}", pos=(available_label.GetPosition().x - 10, patch_label.GetPosition().y + 20))
|
||||||
|
patch_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
# patch_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
|
||||||
|
# Button: Start Root Patching
|
||||||
|
start_button = wx.Button(frame, label="Start Root Patching", pos=(10, patch_label.GetPosition().y + 40), size=(170, 30))
|
||||||
|
start_button.Bind(wx.EVT_BUTTON, lambda event: self._start_root_patching(frame, patches, no_new_patches))
|
||||||
|
start_button.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
start_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Button: Revert Root Patches
|
||||||
|
revert_button = wx.Button(frame, label="Revert Root Patches", pos=(10, start_button.GetPosition().y + start_button.GetSize().height - 5
|
||||||
|
), size=(170, 30))
|
||||||
|
revert_button.Bind(wx.EVT_BUTTON, lambda event: self._revert_root_patching(frame, patches, can_unpatch))
|
||||||
|
revert_button.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
revert_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# 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 + 10), size=(150, 30))
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu)
|
||||||
|
return_button.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set frame size
|
||||||
|
frame.SetSize((-1, return_button.GetPosition().y + return_button.GetSize().height + 40))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _start_root_patching(self, frame: wx.Frame, patches: dict, no_new_patches: bool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _revert_root_patching(self, frame: wx.Frame, patches: dict, can_unpatch: bool):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_return_to_main_menu(self, event):
|
||||||
|
self.frame_modal.Hide()
|
||||||
|
main_menu_frame = gui_main_menu.MainMenu(
|
||||||
|
None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition()
|
||||||
|
)
|
||||||
|
main_menu_frame.Show()
|
||||||
|
self.frame_modal.Destroy()
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _check_if_new_patches_needed(self, patches: dict) -> bool:
|
||||||
|
"""
|
||||||
|
Checks if any new patches are needed for the user to install
|
||||||
|
Newer users will assume the root patch menu will present missing patches.
|
||||||
|
Thus we'll need to see if the exact same OCLP build was used already
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.constants.commit_info[0] in ["Running from source", "Built from source"]:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if self.constants.computer.oclp_sys_url != self.constants.commit_info[2]:
|
||||||
|
# If commits are different, assume patches are as well
|
||||||
|
return True
|
||||||
|
|
||||||
|
oclp_plist = "/System/Library/CoreServices/OpenCore-Legacy-Patcher.plist"
|
||||||
|
if not Path(oclp_plist).exists():
|
||||||
|
# If it doesn't exist, no patches were ever installed
|
||||||
|
# ie. all patches applicable
|
||||||
|
return True
|
||||||
|
|
||||||
|
oclp_plist_data = plistlib.load(open(oclp_plist, "rb"))
|
||||||
|
for patch in patches:
|
||||||
|
if (not patch.startswith("Settings") and not patch.startswith("Validation") and patches[patch] is True):
|
||||||
|
# Patches should share the same name as the plist key
|
||||||
|
# See sys_patch_dict.py for more info
|
||||||
|
patch_installed = False
|
||||||
|
for key in oclp_plist_data:
|
||||||
|
if "Display Name" not in oclp_plist_data[key]:
|
||||||
|
continue
|
||||||
|
if oclp_plist_data[key]["Display Name"] == patch:
|
||||||
|
patch_installed = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if patch_installed is False:
|
||||||
|
logging.info(f"- Patch {patch} not installed")
|
||||||
|
return True
|
||||||
|
|
||||||
|
logging.info("- No new patches detected for system")
|
||||||
|
return False
|
||||||
Reference in New Issue
Block a user