import os import sys from PySide6.QtCore import Qt from PySide6.QtGui import QColor, QFont, QFontInfo, QIcon, QPalette from PySide6.QtWidgets import ( QApplication, QGridLayout, QHBoxLayout, QLabel, QMainWindow, QPushButton, QWidget, ) from .autoslicer import Autoslicer, AutoslicerParams from .controller import ScanSlicerControllerMixin from .ui_builders import ScanSlicerUiBuilderMixin # _unwrap_qvariant: function definition for ScanSlicer behavior. def _unwrap_qvariant(value): unwrapped = value for _ in range(4): if hasattr(unwrapped, "variant"): try: candidate = unwrapped.variant() except Exception: candidate = unwrapped if candidate is not unwrapped: unwrapped = candidate continue if hasattr(unwrapped, "value"): try: candidate = unwrapped.value() except TypeError: candidate = unwrapped.value except Exception: candidate = unwrapped if candidate is not unwrapped: unwrapped = candidate continue break return unwrapped # _read_portal_dark_preference: function definition for ScanSlicer behavior. def _read_portal_dark_preference(): try: from PySide6.QtDBus import QDBusConnection, QDBusInterface, QDBusMessage except Exception: return None bus = QDBusConnection.sessionBus() if not bus.isConnected(): return None iface = QDBusInterface( "org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop", "org.freedesktop.portal.Settings", bus, ) if not iface.isValid(): return None for method in ("ReadOne", "Read"): reply = iface.call(method, "org.freedesktop.appearance", "color-scheme") if reply.type() == QDBusMessage.MessageType.ErrorMessage: continue args = reply.arguments() if not args: continue raw_value = _unwrap_qvariant(args[0]) if isinstance(raw_value, dict) and "color-scheme" in raw_value: raw_value = _unwrap_qvariant(raw_value["color-scheme"]) if isinstance(raw_value, (list, tuple)) and raw_value: raw_value = _unwrap_qvariant(raw_value[0]) try: color_scheme = int(raw_value) except Exception: continue # XDG portal color-scheme values: # 0 = no preference, 1 = prefer dark, 2 = prefer light if color_scheme == 1: return True if color_scheme == 2: return False return None # apply_dark_theme_if_requested: function definition for ScanSlicer behavior. def apply_dark_theme_if_requested(app): theme_value = os.environ.get("GTK_THEME", "").lower() dark_theme_requested = "dark" in theme_value if not dark_theme_requested: portal_pref = _read_portal_dark_preference() if portal_pref is not None: dark_theme_requested = portal_pref if not dark_theme_requested: try: dark_theme_requested = app.styleHints().colorScheme() == Qt.ColorScheme.Dark except Exception: dark_theme_requested = False if not dark_theme_requested: return # Some container/desktop combinations do not propagate GTK dark theme # correctly to Qt widgets; enforce a dark palette when dark mode is requested. app.setStyle("Fusion") palette = QPalette() palette.setColor(QPalette.Window, QColor(53, 53, 53)) palette.setColor(QPalette.WindowText, QColor(255, 255, 255)) palette.setColor(QPalette.Base, QColor(35, 35, 35)) palette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) palette.setColor(QPalette.ToolTipBase, QColor(35, 35, 35)) palette.setColor(QPalette.ToolTipText, QColor(255, 255, 255)) palette.setColor(QPalette.Text, QColor(255, 255, 255)) palette.setColor(QPalette.Button, QColor(53, 53, 53)) palette.setColor(QPalette.ButtonText, QColor(255, 255, 255)) palette.setColor(QPalette.BrightText, QColor(255, 0, 0)) palette.setColor(QPalette.Highlight, QColor(42, 130, 218)) palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255)) app.setPalette(palette) # apply_global_text_size_offset: function definition for ScanSlicer behavior. def apply_global_text_size_offset(app, pixel_offset=2): font = app.font() info = QFontInfo(font) pixel_size = info.pixelSize() if pixel_size > 0: font.setPixelSize(pixel_size + pixel_offset) else: point_size = info.pointSizeF() if point_size <= 0: point_size = 10.0 font.setPointSizeF(point_size + (pixel_offset * 0.75)) app.setFont(font) # resolve_app_icon: function definition for ScanSlicer behavior. def resolve_app_icon(): icon = QIcon.fromTheme("scanslicer") if not icon.isNull(): return icon appdir = os.environ.get("APPDIR", "").strip() if not appdir: return QIcon() candidates = ( os.path.join(appdir, "usr", "share", "icons", "scanslicer.png"), os.path.join(appdir, "usr", "share", "icons", "scanslicer.svg"), os.path.join(appdir, "usr", "share", "pixmaps", "scanslicer.png"), os.path.join(appdir, "usr", "share", "pixmaps", "scanslicer.svg"), os.path.join(appdir, ".DirIcon"), ) for candidate_path in candidates: if not os.path.exists(candidate_path): continue candidate_icon = QIcon(candidate_path) if not candidate_icon.isNull(): return candidate_icon return QIcon()