mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-04-14 04:38:20 +10:00
GUI: Implement Pulse() work-around for non-Metal
ASB I beg of you, please fix this. This hack is so painful…
This commit is contained in:
@@ -585,6 +585,7 @@ class LocalInstallerCatalog:
|
||||
"Build": app_sdk,
|
||||
"Path": application,
|
||||
"Minimum Host OS": min_required,
|
||||
"OS": kernel
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ class InstallOCFrame(wx.Frame):
|
||||
self.available_disks: dict = None
|
||||
self.stock_output = logging.getLogger().handlers[0].stream
|
||||
|
||||
self.progress_bar_animation: gui_support.GaugePulseCallback = None
|
||||
|
||||
self.hyperlink_colour = (25, 179, 231)
|
||||
|
||||
self._generate_elements()
|
||||
@@ -55,7 +57,11 @@ class InstallOCFrame(wx.Frame):
|
||||
# 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()
|
||||
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
self.progress_bar_animation = progress_bar_animation
|
||||
self.progress_bar = progress_bar
|
||||
|
||||
|
||||
@@ -77,6 +83,7 @@ class InstallOCFrame(wx.Frame):
|
||||
wx.Yield()
|
||||
continue
|
||||
|
||||
self.progress_bar_animation.stop_pulse()
|
||||
self.progress_bar.Hide()
|
||||
|
||||
# Create wxDialog for disk selection
|
||||
|
||||
@@ -81,7 +81,8 @@ class macOSInstallerFrame(wx.Frame):
|
||||
# Progress bar
|
||||
progress_bar = wx.Gauge(self, range=100, pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 5), size=(250, 30))
|
||||
progress_bar.Center(wx.HORIZONTAL)
|
||||
progress_bar.Pulse()
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
# Set size of frame
|
||||
self.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||
@@ -100,6 +101,7 @@ class macOSInstallerFrame(wx.Frame):
|
||||
while thread.is_alive():
|
||||
wx.Yield()
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.Hide()
|
||||
self._display_available_installers()
|
||||
|
||||
@@ -233,7 +235,8 @@ class macOSInstallerFrame(wx.Frame):
|
||||
chunk_label.SetLabel("May take a few minutes...")
|
||||
chunk_label.Center(wx.HORIZONTAL)
|
||||
|
||||
progress_bar.Pulse()
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
# Start thread to extract installer
|
||||
self.result = False
|
||||
@@ -250,6 +253,7 @@ class macOSInstallerFrame(wx.Frame):
|
||||
while thread.is_alive():
|
||||
wx.Yield()
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.Hide()
|
||||
chunk_label.SetLabel("Successfully extracted macOS installer" if self.result is True else "Failed to extract macOS installer")
|
||||
chunk_label.Center(wx.HORIZONTAL)
|
||||
|
||||
@@ -8,7 +8,7 @@ import tempfile
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from resources.wx_gui import gui_main_menu, gui_build
|
||||
from resources.wx_gui import gui_main_menu, gui_build, gui_support
|
||||
from resources import (
|
||||
constants,
|
||||
macos_installer_handler,
|
||||
@@ -31,6 +31,8 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
self.available_disks: dict = {}
|
||||
self.prepare_result: bool = False
|
||||
|
||||
self.progress_bar_animation: gui_support.GaugePulseCallback = None
|
||||
|
||||
self.frame_modal: wx.Dialog = None
|
||||
|
||||
self._generate_elements()
|
||||
@@ -54,7 +56,10 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
# Progress bar
|
||||
progress_bar = wx.Gauge(self, range=100, pos=(-1, 30), size=(200, 30))
|
||||
progress_bar.Center(wx.HORIZONTAL)
|
||||
progress_bar.Pulse()
|
||||
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
self.progress_bar_animation = progress_bar_animation
|
||||
|
||||
# Set size of frame
|
||||
self.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||
@@ -105,6 +110,8 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
# Set size of frame
|
||||
frame_modal.SetSize((-1, cancel_button.GetPosition()[1] + cancel_button.GetSize()[1] + 40))
|
||||
|
||||
self.progress_bar_animation.stop_pulse()
|
||||
|
||||
frame_modal.ShowWindowModal()
|
||||
self.frame_modal = frame_modal
|
||||
|
||||
@@ -123,7 +130,9 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
# Progress bar
|
||||
progress_bar = wx.Gauge(self, range=100, pos=(-1, 30), size=(200, 30))
|
||||
progress_bar.Center(wx.HORIZONTAL)
|
||||
progress_bar.Pulse()
|
||||
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
# Set size of frame
|
||||
self.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||
@@ -179,6 +188,9 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
|
||||
# Set size of frame
|
||||
self.frame_modal.SetSize((-1, cancel_button.GetPosition()[1] + cancel_button.GetSize()[1] + 40))
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
|
||||
self.frame_modal.ShowWindowModal()
|
||||
|
||||
|
||||
@@ -217,7 +229,9 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
# Progress bar
|
||||
progress_bar = wx.Gauge(self, range=100, pos=(-1, bytes_written_label.GetPosition()[1] + bytes_written_label.GetSize()[1] + 5), size=(300, 30))
|
||||
progress_bar.Center(wx.HORIZONTAL)
|
||||
progress_bar.Pulse()
|
||||
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
# Set size of frame
|
||||
self.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||
@@ -232,10 +246,11 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
# Base Size
|
||||
estimated_size = 16000
|
||||
# AutoPkg (700MB~)
|
||||
estimated_size += 700 if self.constants.detected_os >= os_data.os_data.big_sur else 0
|
||||
estimated_size += 700 if installer['OS'] >= os_data.os_data.big_sur else 0
|
||||
# KDK (700MB~, and overhead for copying to installer)
|
||||
estimated_size += 700 * 2 if self.constants.detected_os >= os_data.os_data.ventura else 0
|
||||
estimated_size += 700 * 2 if installer['OS'] >= os_data.os_data.ventura else 0
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.SetRange(estimated_size)
|
||||
|
||||
root_disk = disk['identifier'][5:]
|
||||
@@ -259,10 +274,14 @@ class macOSInstallerFlashFrame(wx.Frame):
|
||||
return
|
||||
|
||||
# Next verify the installer
|
||||
progress_bar.Pulse()
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
bytes_written_label.SetLabel("Validating Installer Integrity...")
|
||||
error_message = self._validate_installer_pkg(disk['identifier'])
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
|
||||
if error_message != "":
|
||||
progress_bar.SetValue(0)
|
||||
wx.MessageBox(f"Failed to validate installer, cannot continue.\n This can generally happen due to a faulty USB drive, as flashing is an intensive process that can trigger hardware faults not normally seen. \n\n{error_message}", "Corrupted Installer!", wx.OK | wx.ICON_ERROR)
|
||||
|
||||
@@ -8,6 +8,7 @@ from resources.wx_gui import (
|
||||
gui_settings,
|
||||
)
|
||||
from resources import constants
|
||||
from data import model_array, os_data
|
||||
|
||||
class MainMenu(wx.Frame):
|
||||
def __init__(self, parent: wx.Frame, title: str, global_constants: constants.Constants, screen_location: tuple = None):
|
||||
@@ -16,6 +17,9 @@ class MainMenu(wx.Frame):
|
||||
self.constants: constants.Constants = global_constants
|
||||
self.title: str = title
|
||||
|
||||
self.model_label: wx.StaticText = None
|
||||
self.build_button: wx.Button = None
|
||||
|
||||
self._generate_elements()
|
||||
|
||||
self.SetPosition(screen_location) if screen_location else self.Centre()
|
||||
@@ -64,6 +68,14 @@ class MainMenu(wx.Frame):
|
||||
button.Center(wx.HORIZONTAL)
|
||||
button_y += 30
|
||||
|
||||
if button_name == "Build and Install OpenCore":
|
||||
self.build_button = button
|
||||
if gui_support.CheckProperties(self.constants).host_can_build() is False:
|
||||
button.Disable()
|
||||
elif button_name == "Post-Install Root Patch":
|
||||
if self.constants.detected_os < os_data.os_data.big_sur:
|
||||
button.Disable()
|
||||
|
||||
# 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"))
|
||||
|
||||
@@ -4,10 +4,12 @@ import sys
|
||||
import time
|
||||
import logging
|
||||
import subprocess
|
||||
import threading
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from resources import constants
|
||||
from data import model_array, os_data
|
||||
|
||||
|
||||
class GenerateMenubar:
|
||||
@@ -21,6 +23,95 @@ class GenerateMenubar:
|
||||
return self.menubar
|
||||
|
||||
|
||||
|
||||
class GaugePulseCallback:
|
||||
"""
|
||||
Uses an alternative Pulse() method for wx.Gauge() on macOS Monterey+
|
||||
Dirty hack, however better to display some form of animation than none at all
|
||||
"""
|
||||
|
||||
def __init__(self, global_constants: constants.Constants, gauge: wx.Gauge) -> None:
|
||||
self.gauge: wx.Gauge = gauge
|
||||
|
||||
self.pulse_thread: threading.Thread = None
|
||||
self.pulse_thread_active: bool = False
|
||||
|
||||
self.gauge_value: int = 0
|
||||
self.pulse_forward: bool = True
|
||||
|
||||
self.non_metal_alternative: bool = CheckProperties(global_constants).host_is_non_metal()
|
||||
|
||||
|
||||
def start_pulse(self) -> None:
|
||||
if self.non_metal_alternative is False:
|
||||
self.gauge.Pulse()
|
||||
return
|
||||
self.pulse_thread_active = True
|
||||
self.pulse_thread = threading.Thread(target=self._pulse)
|
||||
self.pulse_thread.start()
|
||||
|
||||
|
||||
def stop_pulse(self) -> None:
|
||||
if self.non_metal_alternative is False:
|
||||
return
|
||||
self.pulse_thread_active = False
|
||||
self.pulse_thread.join()
|
||||
|
||||
|
||||
def _pulse(self) -> None:
|
||||
while self.pulse_thread_active:
|
||||
if self.gauge_value == 0:
|
||||
self.pulse_forward = True
|
||||
|
||||
elif self.gauge_value == 100:
|
||||
self.pulse_forward = False
|
||||
|
||||
if self.pulse_forward:
|
||||
self.gauge_value += 1
|
||||
else:
|
||||
self.gauge_value -= 1
|
||||
|
||||
wx.CallAfter(self.gauge.SetValue, self.gauge_value)
|
||||
time.sleep(0.005)
|
||||
|
||||
|
||||
class CheckProperties:
|
||||
|
||||
def __init__(self, global_constants: constants.Constants) -> None:
|
||||
self.constants: constants.Constants = global_constants
|
||||
|
||||
def host_can_build(self):
|
||||
"""
|
||||
Check if host supports building OpenCore configs
|
||||
"""
|
||||
if self.constants.host_is_hackintosh is True:
|
||||
return False
|
||||
if self.constants.allow_oc_everywhere is True:
|
||||
return True
|
||||
if self.constants.custom_model:
|
||||
return True
|
||||
if self.constants.computer.real_model in model_array.SupportedSMBIOS:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def host_is_non_metal(self):
|
||||
"""
|
||||
Check if host is non-metal
|
||||
Primarily for wx.Gauge().Pulse() workaround (where animation doesn't work on Monterey+)
|
||||
"""
|
||||
|
||||
if self.constants.detected_os < os_data.os_data.monterey:
|
||||
return False
|
||||
if not Path("/System/Library/PrivateFrameworks/SkyLight.framework/Versions/A/SkyLightOld.dylib").exists():
|
||||
# SkyLight stubs are only used on non-Metal
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
class PayloadMount:
|
||||
|
||||
def __init__(self, global_constants: constants.Constants, frame: wx.Frame) -> None:
|
||||
|
||||
@@ -61,7 +61,9 @@ class SysPatchMenu(wx.Frame):
|
||||
|
||||
progress_bar = wx.Gauge(frame, range=100, pos=(-1, subheader.GetPosition()[1] + subheader.GetSize()[1] + 5), size=(250, 20))
|
||||
progress_bar.Center(wx.HORIZONTAL)
|
||||
progress_bar.Pulse()
|
||||
|
||||
progress_bar_animation = gui_support.GaugePulseCallback(self.constants, progress_bar)
|
||||
progress_bar_animation.start_pulse()
|
||||
|
||||
# Set size of frame
|
||||
frame.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 35))
|
||||
@@ -76,10 +78,10 @@ class SysPatchMenu(wx.Frame):
|
||||
kdk_thread.start()
|
||||
|
||||
while kdk_thread.is_alive():
|
||||
progress_bar.Pulse()
|
||||
wx.GetApp().Yield()
|
||||
|
||||
if self.kdk_obj.success is False:
|
||||
progress_bar_animation.stop_pulse()
|
||||
progress_bar.SetValue(0)
|
||||
wx.MessageBox(f"KDK download failed: {self.kdk_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
||||
return False
|
||||
@@ -107,13 +109,18 @@ class SysPatchMenu(wx.Frame):
|
||||
subheader.Center(wx.HORIZONTAL)
|
||||
wx.GetApp().Yield()
|
||||
|
||||
progress_bar_animation.stop_pulse()
|
||||
|
||||
if self.kdk_obj.validate_kdk_checksum() is False:
|
||||
progress_bar.SetValue(0)
|
||||
logging.error("KDK checksum validation failed")
|
||||
logging.error(self.kdk_obj.error_msg)
|
||||
msg = wx.MessageDialog(frame, f"KDK checksum validation failed: {self.kdk_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
||||
msg.ShowModal()
|
||||
return False
|
||||
|
||||
progress_bar.SetValue(100)
|
||||
|
||||
logging.info("KDK download complete")
|
||||
return True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user