ScanSlicer/scanslicer/main.py

148 lines
4.7 KiB
Python

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)