Files
OpenCore-Legacy-Patcher/resources/wx_gui/gui_build.py
2023-05-19 22:06:14 -06:00

160 lines
5.8 KiB
Python

# Generate UI for Building OpenCore
import wx
import logging
import threading
import traceback
from resources import constants
from resources.build import build
from resources.wx_gui import (
gui_main_menu,
gui_install_oc,
gui_support
)
class BuildFrame(wx.Frame):
"""
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) -> 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
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)
if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE:
self.constants.update_stage = gui_support.AutoUpdateStages.BUILDING
self.Centre()
self.frame_modal.ShowWindowModal()
self._invoke_build()
def _generate_elements(self, frame: wx.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.Centre(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.Centre(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.Centre(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.Centre(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.Centre(wx.HORIZONTAL)
return_button.Disable()
self.return_button = return_button
# Adjust window size to fit all elements
frame.SetSize((-1, return_button.GetPosition()[1] + return_button.GetSize()[1] + 40))
def _invoke_build(self) -> None:
"""
Invokes build function and waits for it to finish
"""
while gui_support.PayloadMount(self.constants, self).is_unpack_finished() is False:
wx.Yield()
thread = threading.Thread(target=self._build)
thread.start()
while thread.is_alive():
wx.Yield()
self.return_button.Enable()
dialog = wx.MessageDialog(
parent=self,
message=f"Would you like to install OpenCore now?",
caption="Finished building your OpenCore configuration!",
style=wx.YES_NO | wx.ICON_QUESTION
)
dialog.SetYesNoLabels("Install to disk", "View build log")
self.on_install() if dialog.ShowModal() == wx.ID_YES else self.install_button.Enable()
def _build(self) -> None:
"""
Calls build function and redirects stdout to the text box
"""
logger = logging.getLogger()
logger.addHandler(gui_support.ThreadHandler(self.text_box))
try:
build.BuildOpenCore(self.constants.custom_model or self.constants.computer.real_model, self.constants)
except:
logging.error("- An internal error occurred while building:\n")
logging.error(traceback.format_exc())
logger.removeHandler(logger.handlers[2])
def on_return_to_main_menu(self, event: wx.Event = None) -> None:
"""
Return to main menu
"""
self.frame_modal.Hide()
main_menu_frame = gui_main_menu.MainFrame(
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: wx.Event = None) -> None:
"""
Launch install frame
"""
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()