Files
OpCore-Simplify/Scripts/pages/configuration_page.py
Hoang Hong Quan 0e608a56ce Add GUI Support for OpCore Simplify (#512)
* Refactor OpCore-Simplify to GUI version

* New ConfigEditor

* Add requirement checks and installation in launchers

* Add GitHub Actions workflow to generate manifest.json

* Set compression level for asset

* Skip .git and __pycache__ folders

* Refactor update process to include integrity checker

* Add SMBIOS model selection

* Update README.md

* Update to main branch
2025-12-30 14:19:47 +07:00

293 lines
12 KiB
Python

import os
from PyQt6.QtWidgets import QWidget, QVBoxLayout
from PyQt6.QtCore import Qt
from qfluentwidgets import (
ScrollArea, SubtitleLabel, BodyLabel, FluentIcon,
PushSettingCard, ExpandGroupSettingCard,
SettingCard, PushButton
)
from Scripts.custom_dialogs import show_macos_version_dialog
from Scripts.styles import SPACING, COLORS
from Scripts import ui_utils
class macOSCard(SettingCard):
def __init__(self, controller, on_select_version, parent=None):
super().__init__(
FluentIcon.GLOBE,
"macOS Version",
"Target operating system version",
parent
)
self.controller = controller
self.versionLabel = BodyLabel(self.controller.macos_state.selected_version_name)
self.versionLabel.setStyleSheet("color: {}; margin-right: 10px;".format(COLORS["text_secondary"]))
self.selectVersionBtn = PushButton("Select Version")
self.selectVersionBtn.clicked.connect(on_select_version)
self.selectVersionBtn.setFixedWidth(150)
self.hBoxLayout.addWidget(self.versionLabel)
self.hBoxLayout.addWidget(self.selectVersionBtn)
self.hBoxLayout.addSpacing(16)
def update_version(self):
self.versionLabel.setText(self.controller.macos_state.selected_version_name)
class AudioLayoutCard(SettingCard):
def __init__(self, controller, on_select_layout, parent=None):
super().__init__(
FluentIcon.MUSIC,
"Audio Layout ID",
"Select layout ID for your audio codec",
parent
)
self.controller = controller
layout_text = str(self.controller.hardware_state.audio_layout_id) if self.controller.hardware_state.audio_layout_id is not None else "Not configured"
self.layoutLabel = BodyLabel(layout_text)
self.layoutLabel.setStyleSheet("color: {}; margin-right: 10px;".format(COLORS["text_secondary"]))
self.selectLayoutBtn = PushButton("Configure Layout")
self.selectLayoutBtn.clicked.connect(on_select_layout)
self.selectLayoutBtn.setFixedWidth(150)
self.hBoxLayout.addWidget(self.layoutLabel)
self.hBoxLayout.addWidget(self.selectLayoutBtn)
self.hBoxLayout.addSpacing(16)
self.setVisible(False)
def update_layout(self):
layout_text = str(self.controller.hardware_state.audio_layout_id) if self.controller.hardware_state.audio_layout_id is not None else "Not configured"
self.layoutLabel.setText(layout_text)
class SMBIOSModelCard(SettingCard):
def __init__(self, controller, on_select_model, parent=None):
super().__init__(
FluentIcon.TAG,
"SMBIOS Model",
"Select Mac model identifier for your system",
parent
)
self.controller = controller
model_text = self.controller.smbios_state.model_name if self.controller.smbios_state.model_name != "Not selected" else "Not configured"
self.modelLabel = BodyLabel(model_text)
self.modelLabel.setStyleSheet("color: {}; margin-right: 10px;".format(COLORS["text_secondary"]))
self.selectModelBtn = PushButton("Configure Model")
self.selectModelBtn.clicked.connect(on_select_model)
self.selectModelBtn.setFixedWidth(150)
self.hBoxLayout.addWidget(self.modelLabel)
self.hBoxLayout.addWidget(self.selectModelBtn)
self.hBoxLayout.addSpacing(16)
def update_model(self):
model_text = self.controller.smbios_state.model_name if self.controller.smbios_state.model_name != "Not selected" else "Not configured"
self.modelLabel.setText(model_text)
class ConfigurationPage(ScrollArea):
def __init__(self, parent, ui_utils_instance=None):
super().__init__(parent)
self.setObjectName("configurationPage")
self.controller = parent
self.settings = self.controller.backend.settings
self.scrollWidget = QWidget()
self.expandLayout = QVBoxLayout(self.scrollWidget)
self.ui_utils = ui_utils_instance if ui_utils_instance else ui_utils.UIUtils()
self.setWidget(self.scrollWidget)
self.setWidgetResizable(True)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.enableTransparentBackground()
self.status_card = None
self._init_ui()
def _init_ui(self):
self.expandLayout.setContentsMargins(SPACING["xxlarge"], SPACING["xlarge"], SPACING["xxlarge"], SPACING["xlarge"])
self.expandLayout.setSpacing(SPACING["large"])
self.expandLayout.addWidget(self.ui_utils.create_step_indicator(3))
header_container = QWidget()
header_layout = QVBoxLayout(header_container)
header_layout.setContentsMargins(0, 0, 0, 0)
header_layout.setSpacing(SPACING["tiny"])
title_label = SubtitleLabel("Configuration")
header_layout.addWidget(title_label)
subtitle_label = BodyLabel("Configure your OpenCore EFI settings")
subtitle_label.setStyleSheet("color: {};".format(COLORS["text_secondary"]))
header_layout.addWidget(subtitle_label)
self.expandLayout.addWidget(header_container)
self.expandLayout.addSpacing(SPACING["large"])
self.status_start_index = self.expandLayout.count()
self._update_status_card()
self.macos_card = macOSCard(self.controller, self.select_macos_version, self.scrollWidget)
self.expandLayout.addWidget(self.macos_card)
self.acpi_card = PushSettingCard(
"Configure Patches",
FluentIcon.DEVELOPER_TOOLS,
"ACPI Patches",
"Customize system ACPI table modifications for hardware compatibility",
self.scrollWidget
)
self.acpi_card.clicked.connect(self.customize_acpi_patches)
self.expandLayout.addWidget(self.acpi_card)
self.kexts_card = PushSettingCard(
"Manage Kexts",
FluentIcon.CODE,
"Kernel Extensions",
"Configure kexts required for your hardware",
self.scrollWidget
)
self.kexts_card.clicked.connect(self.customize_kexts)
self.expandLayout.addWidget(self.kexts_card)
self.audio_layout_card = None
self.audio_layout_card_index = None
self.audio_layout_card = AudioLayoutCard(self.controller, self.customize_audio_layout, self.scrollWidget)
self.expandLayout.addWidget(self.audio_layout_card)
self.smbios_card = SMBIOSModelCard(self.controller, self.customize_smbios_model, self.scrollWidget)
self.expandLayout.addWidget(self.smbios_card)
self.expandLayout.addStretch()
def _update_status_card(self):
if self.status_card is not None:
self.expandLayout.removeWidget(self.status_card)
self.status_card.deleteLater()
self.status_card = None
disabled_devices = self.controller.hardware_state.disabled_devices or {}
status_text = ""
status_color = COLORS["text_secondary"]
bg_color = COLORS["bg_card"]
icon = FluentIcon.INFO
if disabled_devices:
status_text = "Hardware components excluded from configuration"
status_color = COLORS["text_secondary"]
bg_color = COLORS["warning_bg"]
elif not self.controller.hardware_state.hardware_report:
status_text = "Please select hardware report first"
elif not self.controller.macos_state.darwin_version:
status_text = "Please select target macOS version first"
else:
status_text = "All hardware components are compatible and enabled"
status_color = COLORS["success"]
bg_color = COLORS["success_bg"]
icon = FluentIcon.ACCEPT
self.status_card = ExpandGroupSettingCard(
icon,
"Compatibility Status",
status_text,
self.scrollWidget
)
if disabled_devices:
for device_name, device_info in disabled_devices.items():
self.ui_utils.add_group_with_indent(
self.status_card,
FluentIcon.CLOSE,
device_name,
"Incompatible" if device_info.get("Compatibility") == (None, None) else "Disabled",
)
else:
pass
self.expandLayout.insertWidget(self.status_start_index, self.status_card)
def select_macos_version(self):
if not self.controller.validate_prerequisites(require_darwin_version=False, require_customized_hardware=False):
return
selected_version = show_macos_version_dialog(
self.controller.macos_state.native_version,
self.controller.macos_state.ocl_patched_version,
self.controller.macos_state.suggested_version
)
if selected_version:
self.controller.apply_macos_version(selected_version)
self.controller.update_status("macOS version updated to {}".format(self.controller.macos_state.selected_version_name), "success")
if hasattr(self, "macos_card"):
self.macos_card.update_version()
def customize_acpi_patches(self):
if not self.controller.validate_prerequisites():
return
self.controller.backend.ac.customize_patch_selection()
self.controller.update_status("ACPI patches configuration updated successfully", "success")
def customize_kexts(self):
if not self.controller.validate_prerequisites():
return
self.controller.backend.k.kext_configuration_menu(self.controller.macos_state.darwin_version)
self.controller.update_status("Kext configuration updated successfully", "success")
def customize_audio_layout(self):
if not self.controller.validate_prerequisites():
return
audio_layout_id, audio_controller_properties = self.controller.backend.k._select_audio_codec_layout(
self.controller.hardware_state.hardware_report,
default_layout_id=self.controller.hardware_state.audio_layout_id
)
if audio_layout_id is not None:
self.controller.hardware_state.audio_layout_id = audio_layout_id
self.controller.hardware_state.audio_controller_properties = audio_controller_properties
self._update_audio_layout_card_visibility()
self.controller.update_status("Audio layout updated to {}".format(audio_layout_id), "success")
def customize_smbios_model(self):
if not self.controller.validate_prerequisites():
return
current_model = self.controller.smbios_state.model_name
selected_model = self.controller.backend.s.customize_smbios_model(self.controller.hardware_state.customized_hardware, current_model, self.controller.macos_state.darwin_version, self.controller.window())
if selected_model and selected_model != current_model:
self.controller.smbios_state.model_name = selected_model
self.controller.backend.s.smbios_specific_options(self.controller.hardware_state.customized_hardware, selected_model, self.controller.macos_state.darwin_version, self.controller.backend.ac.patches, self.controller.backend.k)
if hasattr(self, "smbios_card"):
self.smbios_card.update_model()
self.controller.update_status("SMBIOS model updated to {}".format(selected_model), "success")
def _update_audio_layout_card_visibility(self):
if self.controller.hardware_state.audio_layout_id is not None:
self.audio_layout_card.setVisible(True)
self.audio_layout_card.update_layout()
else:
self.audio_layout_card.setVisible(False)
def update_display(self):
self._update_status_card()
if hasattr(self, "macos_card"):
self.macos_card.update_version()
self._update_audio_layout_card_visibility()
if hasattr(self, "smbios_card"):
self.smbios_card.update_model()
def refresh(self):
self.update_display()