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
This commit is contained in:
Hoang Hong Quan
2025-12-30 14:19:47 +07:00
committed by GitHub
parent 871d826ea4
commit 0e608a56ce
38 changed files with 4948 additions and 1636 deletions

183
Scripts/ui_utils.py Normal file
View File

@@ -0,0 +1,183 @@
from typing import Optional, Tuple, TYPE_CHECKING
from PyQt6.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QColor
from qfluentwidgets import FluentIcon, BodyLabel, CardWidget, StrongBodyLabel
from .styles import SPACING, COLORS, RADIUS
if TYPE_CHECKING:
from qfluentwidgets import GroupHeaderCardWidget, CardGroupWidget
class ProgressStatusHelper:
def __init__(self, status_icon_label, progress_label, progress_bar, progress_container):
self.status_icon_label = status_icon_label
self.progress_label = progress_label
self.progress_bar = progress_bar
self.progress_container = progress_container
def update(self, status, message, progress=None):
icon_size = 28
icon_map = {
"loading": (FluentIcon.SYNC, COLORS["primary"]),
"success": (FluentIcon.COMPLETED, COLORS["success"]),
"error": (FluentIcon.CLOSE, COLORS["error"]),
"warning": (FluentIcon.INFO, COLORS["warning"]),
}
if status in icon_map:
icon, color = icon_map[status]
pixmap = icon.icon(color=color).pixmap(icon_size, icon_size)
self.status_icon_label.setPixmap(pixmap)
self.progress_label.setText(message)
if status == "success":
self.progress_label.setStyleSheet("color: {}; font-size: 15px; font-weight: 600;".format(COLORS["success"]))
elif status == "error":
self.progress_label.setStyleSheet("color: {}; font-size: 15px; font-weight: 600;".format(COLORS["error"]))
elif status == "warning":
self.progress_label.setStyleSheet("color: {}; font-size: 15px; font-weight: 600;".format(COLORS["warning"]))
else:
self.progress_label.setStyleSheet("color: {}; font-size: 15px; font-weight: 600;".format(COLORS["primary"]))
if progress is not None:
self.progress_bar.setRange(0, 100)
self.progress_bar.setValue(progress)
else:
self.progress_bar.setRange(0, 0)
self.progress_container.setVisible(True)
class UIUtils:
def __init__(self):
pass
def build_icon_label(self, icon: FluentIcon, color: str, size: int = 32) -> QLabel:
label = QLabel()
label.setPixmap(icon.icon(color=color).pixmap(size, size))
label.setAlignment(Qt.AlignmentFlag.AlignCenter)
label.setFixedSize(size + 12, size + 12)
return label
def create_info_widget(self, text: str, color: Optional[str] = None) -> QWidget:
if not text:
return QWidget()
label = BodyLabel(text)
label.setWordWrap(True)
if color:
label.setStyleSheet("color: {};".format(color))
return label
def colored_icon(self, icon: FluentIcon, color_hex: str) -> FluentIcon:
if not icon or not color_hex:
return icon
tint = QColor(color_hex)
return icon.colored(tint, tint)
def get_compatibility_icon(self, compat_tuple: Optional[Tuple[Optional[str], Optional[str]]]) -> FluentIcon:
if not compat_tuple or compat_tuple == (None, None):
return self.colored_icon(FluentIcon.CLOSE, COLORS["error"])
return self.colored_icon(FluentIcon.ACCEPT, COLORS["success"])
def add_group_with_indent(self, card: "GroupHeaderCardWidget", icon: FluentIcon, title: str, content: str, widget: Optional[QWidget] = None, indent_level: int = 0) -> "CardGroupWidget":
if widget is None:
widget = QWidget()
group = card.addGroup(icon, title, content, widget)
if indent_level > 0:
base_margin = 24
indent = 20 * indent_level
group.hBoxLayout.setContentsMargins(base_margin + indent, 10, 24, 10)
return group
def create_step_indicator(self, step_number: int, total_steps: int = 4, color: str = "#0078D4") -> BodyLabel:
label = BodyLabel("STEP {} OF {}".format(step_number, total_steps))
label.setStyleSheet("color: {}; font-weight: bold;".format(color))
return label
def create_vertical_spacer(self, spacing: int = SPACING["medium"]) -> QWidget:
spacer = QWidget()
spacer.setFixedHeight(spacing)
return spacer
def custom_card(self, card_type: str = "note", icon: Optional[FluentIcon] = None, title: str = "", body: str = "", custom_widget: Optional[QWidget] = None, parent: Optional[QWidget] = None) -> CardWidget:
card_styles = {
"note": {
"bg": COLORS["note_bg"],
"text": COLORS["note_text"],
"border": "rgba(21, 101, 192, 0.2)",
"default_icon": FluentIcon.INFO
},
"warning": {
"bg": COLORS["warning_bg"],
"text": COLORS["warning_text"],
"border": "rgba(245, 124, 0, 0.25)",
"default_icon": FluentIcon.MEGAPHONE
},
"success": {
"bg": COLORS["success_bg"],
"text": COLORS["success"],
"border": "rgba(16, 124, 16, 0.2)",
"default_icon": FluentIcon.COMPLETED
},
"error": {
"bg": "#FFEBEE",
"text": COLORS["error"],
"border": "rgba(232, 17, 35, 0.25)",
"default_icon": FluentIcon.CLOSE
},
"info": {
"bg": COLORS["note_bg"],
"text": COLORS["info"],
"border": "rgba(0, 120, 212, 0.2)",
"default_icon": FluentIcon.INFO
}
}
style = card_styles.get(card_type, card_styles["note"])
if icon is None:
icon = style["default_icon"]
card = CardWidget(parent)
card.setStyleSheet(f"""
CardWidget {{
background-color: {style["bg"]};
border: 1px solid {style["border"]};
border-radius: {RADIUS["card"]}px;
}}
""")
main_layout = QHBoxLayout(card)
main_layout.setContentsMargins(SPACING["large"], SPACING["large"], SPACING["large"], SPACING["large"])
main_layout.setSpacing(SPACING["large"])
icon_label = self.build_icon_label(icon, style["text"], size=40)
main_layout.addWidget(icon_label, 0, Qt.AlignmentFlag.AlignVCenter)
text_layout = QVBoxLayout()
text_layout.setSpacing(SPACING["small"])
if title:
title_label = StrongBodyLabel(title)
title_label.setStyleSheet("color: {}; font-size: 16px;".format(style["text"]))
text_layout.addWidget(title_label)
if body:
body_label = BodyLabel(body)
body_label.setWordWrap(True)
body_label.setOpenExternalLinks(True)
body_label.setStyleSheet("color: #424242; line-height: 1.6;")
text_layout.addWidget(body_label)
if custom_widget:
text_layout.addWidget(custom_widget)
main_layout.addLayout(text_layout)
return card