mirror of
https://github.com/dortania/OpenCore-Legacy-Patcher.git
synced 2026-06-19 22:00:00 +10:00
GUI: Implement download GUI class
Unifies all download UIs
This commit is contained in:
@@ -9,6 +9,7 @@ import threading
|
|||||||
import logging
|
import logging
|
||||||
import enum
|
import enum
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import atexit
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from resources import utilities
|
from resources import utilities
|
||||||
@@ -340,6 +341,7 @@ class DownloadObject:
|
|||||||
response = NetworkUtilities().get(self.url, stream=True, timeout=10)
|
response = NetworkUtilities().get(self.url, stream=True, timeout=10)
|
||||||
|
|
||||||
with open(self.filepath, 'wb') as file:
|
with open(self.filepath, 'wb') as file:
|
||||||
|
atexit.register(self.stop)
|
||||||
for i, chunk in enumerate(response.iter_content(1024 * 1024 * 4)):
|
for i, chunk in enumerate(response.iter_content(1024 * 1024 * 4)):
|
||||||
if self.should_stop:
|
if self.should_stop:
|
||||||
raise Exception("Download stopped")
|
raise Exception("Download stopped")
|
||||||
@@ -407,7 +409,10 @@ class DownloadObject:
|
|||||||
if self.total_file_size == 0.0:
|
if self.total_file_size == 0.0:
|
||||||
logging.error("- File size is 0, cannot calculate time remaining")
|
logging.error("- File size is 0, cannot calculate time remaining")
|
||||||
return -1
|
return -1
|
||||||
return (self.total_file_size - self.downloaded_file_size) / self.get_speed()
|
speed = self.get_speed()
|
||||||
|
if speed <= 0:
|
||||||
|
return -1
|
||||||
|
return (self.total_file_size - self.downloaded_file_size) / speed
|
||||||
|
|
||||||
|
|
||||||
def get_file_size(self) -> float:
|
def get_file_size(self) -> float:
|
||||||
|
|||||||
@@ -48,6 +48,44 @@ def human_fmt(num):
|
|||||||
return "%.1f %s" % (num, "EB")
|
return "%.1f %s" % (num, "EB")
|
||||||
|
|
||||||
|
|
||||||
|
def seconds_to_readable_time(seconds) -> str:
|
||||||
|
"""
|
||||||
|
Convert seconds to a readable time format
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
seconds (int | float | str): Seconds to convert
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Readable time format
|
||||||
|
"""
|
||||||
|
seconds = int(seconds)
|
||||||
|
time = ""
|
||||||
|
|
||||||
|
if seconds == 0:
|
||||||
|
return "Done"
|
||||||
|
if seconds < 0:
|
||||||
|
return "Indeterminate"
|
||||||
|
|
||||||
|
years, seconds = divmod(seconds, 31536000)
|
||||||
|
days, seconds = divmod(seconds, 86400)
|
||||||
|
hours, seconds = divmod(seconds, 3600)
|
||||||
|
minutes, seconds = divmod(seconds, 60)
|
||||||
|
|
||||||
|
if years > 0:
|
||||||
|
return "Over a year"
|
||||||
|
if days > 0:
|
||||||
|
if days > 31:
|
||||||
|
return "Over a month"
|
||||||
|
time += f"{days}d "
|
||||||
|
if hours > 0:
|
||||||
|
time += f"{hours}h "
|
||||||
|
if minutes > 0:
|
||||||
|
time += f"{minutes}m "
|
||||||
|
if seconds > 0:
|
||||||
|
time += f"{seconds}s"
|
||||||
|
return time
|
||||||
|
|
||||||
|
|
||||||
def header(lines):
|
def header(lines):
|
||||||
lines = [i for i in lines if i is not None]
|
lines = [i for i in lines if i is not None]
|
||||||
total_length = len(max(lines, key=len)) + 4
|
total_length = len(max(lines, key=len)) + 4
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
import wx
|
||||||
|
|
||||||
|
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, screen_location: tuple = None):
|
||||||
|
|
||||||
|
self.constants: constants.Constants = global_constants
|
||||||
|
self.title: str = title
|
||||||
|
self.parent: wx.Frame = parent
|
||||||
|
self.download_obj: network_handler.DownloadObject = download_obj
|
||||||
|
self.item_name: str = item_name
|
||||||
|
|
||||||
|
self.frame_modal = wx.Dialog(parent, title=title, size=(400, 200))
|
||||||
|
|
||||||
|
self._generate_elements(self.frame_modal)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_elements(self, frame: wx.Frame = None) -> None:
|
||||||
|
|
||||||
|
frame = self if not frame else frame
|
||||||
|
|
||||||
|
title_label = wx.StaticText(frame, label=f"Downloading: {self.item_name}", 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)
|
||||||
|
|
||||||
|
label_amount = wx.StaticText(frame, label="0.00 B downloaded of 0.00B (0.00%)", pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 5))
|
||||||
|
label_amount.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
label_amount.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
label_speed = wx.StaticText(frame, label="Average download speed: Unknown", pos=(-1, label_amount.GetPosition()[1] + label_amount.GetSize()[1] + 5))
|
||||||
|
label_speed.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
label_speed.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
label_est_time = wx.StaticText(frame, label="Estimated time remaining: Unknown", pos=(-1, label_speed.GetPosition()[1] + label_speed.GetSize()[1] + 5))
|
||||||
|
label_est_time.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
label_est_time.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
progress_bar = wx.Gauge(frame, range=100, pos=(-1, label_est_time.GetPosition()[1] + label_est_time.GetSize()[1] + 5), size=(300, 20))
|
||||||
|
progress_bar.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set size of frame
|
||||||
|
frame.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||||
|
frame.ShowWindowModal()
|
||||||
|
|
||||||
|
self.download_obj.download()
|
||||||
|
while self.download_obj.is_active():
|
||||||
|
if self.download_obj.total_file_size == -1:
|
||||||
|
amount_str = f"{utilities.human_fmt(self.download_obj.downloaded_file_size)} downloaded"
|
||||||
|
else:
|
||||||
|
amount_str = f"{utilities.human_fmt(self.download_obj.downloaded_file_size)} downloaded of {utilities.human_fmt(self.download_obj.total_file_size)} ({self.download_obj.get_percent():.2f}%)"
|
||||||
|
label_amount.SetLabel(amount_str)
|
||||||
|
label_amount.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
label_speed.SetLabel(
|
||||||
|
f"Average download speed: {utilities.human_fmt(self.download_obj.get_speed())}/s"
|
||||||
|
)
|
||||||
|
|
||||||
|
label_est_time.SetLabel(
|
||||||
|
f"Estimated time remaining: {utilities.seconds_to_readable_time(self.download_obj.get_time_remaining())}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
progress_bar.SetValue(int(self.download_obj.get_percent()))
|
||||||
|
wx.GetApp().Yield()
|
||||||
|
|
||||||
|
if self.download_obj.download_complete is False:
|
||||||
|
wx.MessageBox(f"Download failed: \n{self.download_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
||||||
|
|
||||||
|
frame.Destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,298 @@
|
|||||||
|
import wx
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from resources.wx_gui import gui_main_menu, gui_support, gui_download
|
||||||
|
from resources import (
|
||||||
|
constants,
|
||||||
|
macos_installer_handler,
|
||||||
|
utilities,
|
||||||
|
network_handler,
|
||||||
|
integrity_verification
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class macOSInstallerFrame(wx.Frame):
|
||||||
|
"""
|
||||||
|
Create a frame for downloading and creating macOS installers
|
||||||
|
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(macOSInstallerFrame, self).__init__(parent, title=title, size=(350, 200))
|
||||||
|
|
||||||
|
self.constants: constants.Constants = global_constants
|
||||||
|
self.title: str = title
|
||||||
|
self.parent: wx.Frame = parent
|
||||||
|
|
||||||
|
self.available_installers = None
|
||||||
|
self.available_installers_latest = None
|
||||||
|
|
||||||
|
self.frame_modal = wx.Dialog(parent, title=title, size=(330, 200))
|
||||||
|
|
||||||
|
self._generate_elements(self.frame_modal)
|
||||||
|
self.frame_modal.ShowWindowModal()
|
||||||
|
|
||||||
|
|
||||||
|
def _generate_elements(self, frame: wx.Frame = None) -> None:
|
||||||
|
"""
|
||||||
|
Format:
|
||||||
|
- Title: Create macOS Installer
|
||||||
|
- Button: Download macOS Installer
|
||||||
|
- Button: Use existing macOS Installer
|
||||||
|
- Button: Return to Main Menu
|
||||||
|
"""
|
||||||
|
|
||||||
|
frame = self if not frame else frame
|
||||||
|
|
||||||
|
title_label = wx.StaticText(frame, label="Create macOS Installer", 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)
|
||||||
|
|
||||||
|
# Button: Download macOS Installer
|
||||||
|
download_button = wx.Button(frame, label="Download macOS Installer", pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 5), size=(200, 30))
|
||||||
|
download_button.Bind(wx.EVT_BUTTON, self.on_download)
|
||||||
|
download_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Button: Use existing macOS Installer
|
||||||
|
existing_button = wx.Button(frame, label="Use existing macOS Installer", pos=(-1, download_button.GetPosition()[1] + download_button.GetSize()[1] - 5), size=(200, 30))
|
||||||
|
existing_button.Bind(wx.EVT_BUTTON, self.on_existing)
|
||||||
|
existing_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Button: Return to Main Menu
|
||||||
|
return_button = wx.Button(frame, label="Return to Main Menu", pos=(-1, existing_button.GetPosition()[1] + existing_button.GetSize()[1] + 5), size=(150, 30))
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self.on_return)
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set size of 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))
|
||||||
|
self.SetPosition((self.parent.GetPosition()[0], self.parent.GetPosition()[1]))
|
||||||
|
|
||||||
|
# Title: Pulling installer catalog
|
||||||
|
title_label = wx.StaticText(self, label="Pulling installer catalog", 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)
|
||||||
|
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
# Set size of frame
|
||||||
|
self.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||||
|
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
# Grab installer catalog
|
||||||
|
def fetch_installers():
|
||||||
|
remote_obj = macos_installer_handler.RemoteInstallerCatalog(seed_override=macos_installer_handler.SeedType.DeveloperSeed)
|
||||||
|
self.available_installers = remote_obj.available_apps
|
||||||
|
self.available_installers_latest = remote_obj.available_apps_latest
|
||||||
|
|
||||||
|
thread = threading.Thread(target=fetch_installers)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
while thread.is_alive():
|
||||||
|
wx.Yield()
|
||||||
|
|
||||||
|
progress_bar.Hide()
|
||||||
|
self._display_available_installers()
|
||||||
|
|
||||||
|
|
||||||
|
def _display_available_installers(self, event: wx.Event = None, show_full: bool = False) -> None:
|
||||||
|
self.frame_modal.Destroy()
|
||||||
|
dialog = wx.Dialog(self, title="Select macOS Installer", size=(300, 200))
|
||||||
|
|
||||||
|
# Title: Select macOS Installer
|
||||||
|
title_label = wx.StaticText(dialog, label="Select macOS Installer", 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)
|
||||||
|
|
||||||
|
# Subtitle: Installers currently available from Apple:
|
||||||
|
subtitle_label = wx.StaticText(dialog, label="Installers currently available from Apple:", pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 5))
|
||||||
|
subtitle_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
subtitle_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# List of installers
|
||||||
|
installers = self.available_installers_latest if show_full is False else self.available_installers
|
||||||
|
if installers:
|
||||||
|
spacer = 0
|
||||||
|
for app in installers:
|
||||||
|
logging.info(f"macOS {installers[app]['Version']} ({installers[app]['Build']}):\n - Size: {utilities.human_fmt(installers[app]['Size'])}\n - Source: {installers[app]['Source']}\n - Variant: {installers[app]['Variant']}\n - Link: {installers[app]['Link']}\n")
|
||||||
|
extra = " Beta" if installers[app]['Variant'] in ["DeveloperSeed" , "PublicSeed"] else ""
|
||||||
|
|
||||||
|
installer_button = wx.Button(dialog, label=f"macOS {installers[app]['Version']}{extra} ({installers[app]['Build']} - {utilities.human_fmt(installers[app]['Size'])})", pos=(-1, subtitle_label.GetPosition()[1] + subtitle_label.GetSize()[1] + 5 + spacer), size=(270, 30))
|
||||||
|
installer_button.Bind(wx.EVT_BUTTON, lambda event, temp=app: self.on_download_installer(installers[temp]))
|
||||||
|
installer_button.Center(wx.HORIZONTAL)
|
||||||
|
spacer += 25
|
||||||
|
|
||||||
|
# Show all available installers
|
||||||
|
show_all_button = wx.Button(dialog, label="Show all available installers" if show_full is False else "Show only latest installers", pos=(-1, installer_button.GetPosition()[1] + installer_button.GetSize()[1]), size=(180, 30))
|
||||||
|
show_all_button.Bind(wx.EVT_BUTTON, lambda event: self._display_available_installers(event, not show_full))
|
||||||
|
show_all_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Return to Main Menu
|
||||||
|
return_button = wx.Button(dialog, label="Return to Main Menu", pos=(-1, show_all_button.GetPosition()[1] + show_all_button.GetSize()[1] - 7), size=(150, 30))
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu)
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set size of frame
|
||||||
|
dialog.SetSize((-1, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
|
||||||
|
dialog.ShowWindowModal()
|
||||||
|
self.frame_modal = dialog
|
||||||
|
|
||||||
|
|
||||||
|
def on_download_installer(self, app: dict) -> None:
|
||||||
|
self.frame_modal.Close()
|
||||||
|
|
||||||
|
download_obj = network_handler.DownloadObject(app['Link'], self.constants.payload_path / "InstallAssistant.pkg")
|
||||||
|
|
||||||
|
gui_download.DownloadFrame(
|
||||||
|
self,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition(),
|
||||||
|
download_obj=download_obj,
|
||||||
|
item_name=f"macOS {app['Version']} ({app['Build']})",
|
||||||
|
)
|
||||||
|
|
||||||
|
if download_obj.download_complete is False:
|
||||||
|
self.on_return_to_main_menu()
|
||||||
|
return
|
||||||
|
|
||||||
|
self._validate_installer(app['integrity'])
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_installer(self, chunklist_link: str) -> None:
|
||||||
|
|
||||||
|
self.SetSize((300, 200))
|
||||||
|
for child in self.GetChildren():
|
||||||
|
child.Destroy()
|
||||||
|
|
||||||
|
# Title: Validating macOS Installer
|
||||||
|
title_label = wx.StaticText(self, label="Validating macOS Installer", 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)
|
||||||
|
|
||||||
|
# Label: Validating chunk 0 of 0
|
||||||
|
chunk_label = wx.StaticText(self, label="Validating chunk 0 of 0", pos=(-1, title_label.GetPosition()[1] + title_label.GetSize()[1] + 5))
|
||||||
|
chunk_label.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
||||||
|
chunk_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Progress bar
|
||||||
|
progress_bar = wx.Gauge(self, range=100, pos=(-1, chunk_label.GetPosition()[1] + chunk_label.GetSize()[1] + 5), size=(270, 30))
|
||||||
|
progress_bar.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
|
||||||
|
# Set size of frame
|
||||||
|
self.SetSize((-1, progress_bar.GetPosition()[1] + progress_bar.GetSize()[1] + 40))
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
chunklist_stream = network_handler.NetworkUtilities().get(chunklist_link).content
|
||||||
|
if chunklist_stream:
|
||||||
|
utilities.disable_sleep_while_running()
|
||||||
|
chunk_obj = integrity_verification.ChunklistVerification(self.constants.payload_path / Path("InstallAssistant.pkg"), chunklist_stream)
|
||||||
|
if chunk_obj.chunks:
|
||||||
|
progress_bar.SetValue(chunk_obj.current_chunk)
|
||||||
|
progress_bar.SetRange(chunk_obj.total_chunks)
|
||||||
|
|
||||||
|
wx.App.Get().Yield()
|
||||||
|
chunk_obj.validate()
|
||||||
|
|
||||||
|
while chunk_obj.status == integrity_verification.ChunklistStatus.IN_PROGRESS:
|
||||||
|
progress_bar.SetValue(chunk_obj.current_chunk)
|
||||||
|
chunk_label.SetLabel(f"Validating chunk {chunk_obj.current_chunk} of {chunk_obj.total_chunks}")
|
||||||
|
chunk_label.Center(wx.HORIZONTAL)
|
||||||
|
wx.App.Get().Yield()
|
||||||
|
|
||||||
|
if chunk_obj.status == integrity_verification.ChunklistStatus.FAILURE:
|
||||||
|
wx.MessageBox("Chunklist validation failed.\n\nThis generally happens when downloading on unstable connections such as WiFi or cellular.\n\nPlease try redownloading again on a stable connection (ie. Ethernet)", "Corrupted Installer!", wx.OK | wx.ICON_ERROR)
|
||||||
|
self.on_return_to_main_menu()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# Extract installer
|
||||||
|
title_label.SetLabel("Extracting macOS Installer")
|
||||||
|
title_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
chunk_label.SetLabel("May take a few minutes...")
|
||||||
|
chunk_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
progress_bar.Pulse()
|
||||||
|
|
||||||
|
# Start thread to extract installer
|
||||||
|
self.result = False
|
||||||
|
def extract_installer():
|
||||||
|
self.result = macos_installer_handler.InstallerCreation().install_macOS_installer(self.constants.payload_path)
|
||||||
|
|
||||||
|
thread = threading.Thread(target=extract_installer)
|
||||||
|
thread.start()
|
||||||
|
|
||||||
|
# Show frame
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
# Wait for thread to finish
|
||||||
|
while thread.is_alive():
|
||||||
|
wx.Yield()
|
||||||
|
|
||||||
|
if self.result is False:
|
||||||
|
progress_bar.SetValue(0)
|
||||||
|
chunk_label.SetLabel("Failed to extract macOS installer")
|
||||||
|
chunk_label.Center(wx.HORIZONTAL)
|
||||||
|
wx.MessageBox("An error occurred while extracting the macOS installer. Could be due to a corrupted installer", "Error", wx.OK | wx.ICON_ERROR)
|
||||||
|
|
||||||
|
progress_bar.Hide()
|
||||||
|
chunk_label.SetLabel("Successfully extracted macOS installer")
|
||||||
|
chunk_label.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Create macOS Installer button
|
||||||
|
create_installer_button = wx.Button(self, label="Create macOS Installer", pos=(-1, progress_bar.GetPosition()[1]), size=(170, 30))
|
||||||
|
create_installer_button.Bind(wx.EVT_BUTTON, self.on_existing)
|
||||||
|
create_installer_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Return to main menu button
|
||||||
|
return_button = wx.Button(self, label="Return to Main Menu", pos=(-1, create_installer_button.GetPosition()[1] + create_installer_button.GetSize()[1]), size=(150, 30))
|
||||||
|
return_button.Bind(wx.EVT_BUTTON, self.on_return_to_main_menu)
|
||||||
|
return_button.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
|
# Set size of frame
|
||||||
|
self.SetSize((-1, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
|
||||||
|
|
||||||
|
# Show frame
|
||||||
|
self.Show()
|
||||||
|
|
||||||
|
result = wx.MessageBox("Finished extracting the installer, would you like to continue and create a macOS installer?", "Create macOS Installer?", wx.YES_NO | wx.ICON_QUESTION)
|
||||||
|
if result == wx.YES:
|
||||||
|
self.on_existing()
|
||||||
|
|
||||||
|
|
||||||
|
def on_download(self, event: wx.Event) -> None:
|
||||||
|
self.frame_modal.Close()
|
||||||
|
self.parent.Hide()
|
||||||
|
self._generate_catalog_frame()
|
||||||
|
self.parent.Close()
|
||||||
|
|
||||||
|
def on_existing(self, event: wx.Event = None) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def on_return(self, event: wx.Event) -> None:
|
||||||
|
self.frame_modal.Close()
|
||||||
|
|
||||||
|
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(
|
||||||
|
None,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition()
|
||||||
|
)
|
||||||
|
main_menu_frame.Show()
|
||||||
|
if self.frame_modal:
|
||||||
|
self.frame_modal.Destroy()
|
||||||
|
self.Destroy()
|
||||||
@@ -4,6 +4,7 @@ from resources.wx_gui import (
|
|||||||
gui_sys_patch,
|
gui_sys_patch,
|
||||||
gui_support,
|
gui_support,
|
||||||
gui_help,
|
gui_help,
|
||||||
|
gui_macos_installer,
|
||||||
)
|
)
|
||||||
from resources import constants
|
from resources import constants
|
||||||
|
|
||||||
@@ -93,7 +94,13 @@ class MainMenu(wx.Frame):
|
|||||||
|
|
||||||
|
|
||||||
def on_create_macos_installer(self, event: wx.Event = None):
|
def on_create_macos_installer(self, event: wx.Event = None):
|
||||||
pass
|
gui_macos_installer.macOSInstallerFrame(
|
||||||
|
parent=self,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetPosition()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def on_settings(self, event: wx.Event = None):
|
def on_settings(self, event: wx.Event = None):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from resources.sys_patch import (
|
|||||||
from resources.wx_gui import (
|
from resources.wx_gui import (
|
||||||
gui_main_menu,
|
gui_main_menu,
|
||||||
gui_support,
|
gui_support,
|
||||||
|
gui_download,
|
||||||
)
|
)
|
||||||
|
|
||||||
class SysPatchMenu(wx.Frame):
|
class SysPatchMenu(wx.Frame):
|
||||||
@@ -89,46 +90,23 @@ class SysPatchMenu(wx.Frame):
|
|||||||
# KDK is already downloaded
|
# KDK is already downloaded
|
||||||
return True
|
return True
|
||||||
|
|
||||||
kdk_download_obj.download()
|
gui_download.DownloadFrame(
|
||||||
|
self,
|
||||||
|
title=self.title,
|
||||||
|
global_constants=self.constants,
|
||||||
|
screen_location=self.GetScreenPosition(),
|
||||||
|
download_obj=kdk_download_obj,
|
||||||
|
item_name=f"KDK Build {self.kdk_obj.kdk_url_build}"
|
||||||
|
)
|
||||||
|
if kdk_download_obj.download_complete is False:
|
||||||
|
return False
|
||||||
|
|
||||||
header.SetLabel(f"Downloading KDK Build: {self.kdk_obj.kdk_url_build}")
|
header.SetLabel(f"Validating KDK: {self.kdk_obj.kdk_url_build}")
|
||||||
header.Center(wx.HORIZONTAL)
|
header.Center(wx.HORIZONTAL)
|
||||||
|
|
||||||
progress_bar.SetValue(0)
|
subheader.SetLabel("Checking if checksum is valid...")
|
||||||
# Set below developer note
|
subheader.Center(wx.HORIZONTAL)
|
||||||
progress_bar.SetPosition(
|
wx.GetApp().Yield()
|
||||||
wx.Point(
|
|
||||||
subheader.GetPosition().x,
|
|
||||||
subheader.GetPosition().y + subheader.GetSize().height + 30
|
|
||||||
)
|
|
||||||
)
|
|
||||||
progress_bar.Center(wx.HORIZONTAL)
|
|
||||||
progress_bar.Show()
|
|
||||||
|
|
||||||
developer_note = wx.StaticText(frame, label="Starting shortly", pos=(-1, progress_bar.GetPosition().y - 23))
|
|
||||||
developer_note.SetFont(wx.Font(13, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, ".AppleSystemUIFont"))
|
|
||||||
developer_note.Center(wx.HORIZONTAL)
|
|
||||||
|
|
||||||
frame.SetSize(-1, progress_bar.GetPosition().y + progress_bar.GetSize().height + 40)
|
|
||||||
|
|
||||||
while kdk_download_obj.is_active():
|
|
||||||
subheader.SetLabel(f"{utilities.human_fmt(kdk_download_obj.downloaded_file_size)} downloaded of {utilities.human_fmt(kdk_download_obj.total_file_size)} ({kdk_download_obj.get_percent():.2f}%)")
|
|
||||||
subheader.Center(wx.HORIZONTAL)
|
|
||||||
developer_note.SetLabel(
|
|
||||||
f"Average download speed: {utilities.human_fmt(kdk_download_obj.get_speed())}/s"
|
|
||||||
)
|
|
||||||
developer_note.Center(wx.HORIZONTAL)
|
|
||||||
|
|
||||||
progress_bar.SetValue(int(kdk_download_obj.get_percent()))
|
|
||||||
wx.GetApp().Yield()
|
|
||||||
|
|
||||||
if kdk_download_obj.download_complete is False:
|
|
||||||
logging.info("Failed to download KDK")
|
|
||||||
logging.info(kdk_download_obj.error_msg)
|
|
||||||
# wx.MessageBox(f"KDK download failed: {kdk_download_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
|
||||||
msg = wx.MessageDialog(frame, f"KDK download failed: {kdk_download_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)
|
|
||||||
msg.ShowModal()
|
|
||||||
return False
|
|
||||||
|
|
||||||
if self.kdk_obj.validate_kdk_checksum() is False:
|
if self.kdk_obj.validate_kdk_checksum() is False:
|
||||||
logging.error("KDK checksum validation failed")
|
logging.error("KDK checksum validation failed")
|
||||||
|
|||||||
Reference in New Issue
Block a user