""" Eigenschaften-Panel (rechte Seitenleiste): - Globale Strichdicke - Globaler Buchstabenabstand - Pro-Glyph-Einstellungen (Offset, Strichdicke-Faktor) - Tracing-Schwellenwert """ from __future__ import annotations from PySide6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox, QSpinBox, QGroupBox, QScrollArea, QSlider, QPushButton, QFormLayout, QFrame, ) from PySide6.QtCore import Signal, Qt class PropertiesPanel(QWidget): # Signale für Änderungen letter_spacing_changed = Signal(float) stroke_width_changed = Signal(float) threshold_changed = Signal(int) retrace_requested = Signal() export_requested = Signal() def __init__(self, parent=None): super().__init__(parent) self.setFixedWidth(320) self._build_ui() def _build_ui(self): layout = QVBoxLayout(self) layout.setContentsMargins(8, 8, 8, 8) layout.setSpacing(12) # --- Titel --- title = QLabel("Eigenschaften") title.setStyleSheet("font-size: 16px; font-weight: bold; color: #e0e0e0;") layout.addWidget(title) layout.addWidget(self._separator()) # --- Globale Einstellungen --- global_group = QGroupBox("Globale Parameter") global_group.setStyleSheet(self._group_style()) gl = QFormLayout(global_group) gl.setSpacing(8) self.spin_letter_spacing = QDoubleSpinBox() self.spin_letter_spacing.setRange(-50.0, 200.0) self.spin_letter_spacing.setSingleStep(0.5) self.spin_letter_spacing.setValue(0.0) self.spin_letter_spacing.setSuffix(" px") self.spin_letter_spacing.setDecimals(1) self.spin_letter_spacing.valueChanged.connect(self.letter_spacing_changed.emit) gl.addRow("Buchstabenabstand:", self.spin_letter_spacing) self.spin_stroke_width = QDoubleSpinBox() self.spin_stroke_width.setRange(0.0, 50.0) self.spin_stroke_width.setSingleStep(0.1) self.spin_stroke_width.setValue(1.0) self.spin_stroke_width.setSuffix(" px") self.spin_stroke_width.setDecimals(1) self.spin_stroke_width.valueChanged.connect(self.stroke_width_changed.emit) gl.addRow("Strichdicke:", self.spin_stroke_width) layout.addWidget(global_group) # --- Tracing-Einstellungen --- trace_group = QGroupBox("Vektorisierung") trace_group.setStyleSheet(self._group_style()) tl = QFormLayout(trace_group) tl.setSpacing(8) self.slider_threshold = QSlider(Qt.Orientation.Horizontal) self.slider_threshold.setRange(1, 254) self.slider_threshold.setValue(128) self.slider_threshold.setTickInterval(16) self.slider_threshold.setTickPosition(QSlider.TickPosition.TicksBelow) self.lbl_threshold = QLabel("128") self.slider_threshold.valueChanged.connect( lambda v: self.lbl_threshold.setText(str(v)) ) self.slider_threshold.valueChanged.connect(self.threshold_changed.emit) th_row = QHBoxLayout() th_row.addWidget(self.slider_threshold, stretch=1) th_row.addWidget(self.lbl_threshold) tl.addRow("Schwellenwert:", th_row) self.btn_retrace = QPushButton("Neu vektorisieren") self.btn_retrace.setStyleSheet(self._button_style()) self.btn_retrace.clicked.connect(self.retrace_requested.emit) tl.addRow(self.btn_retrace) layout.addWidget(trace_group) # --- Glyph-Liste (scrollbar) --- glyph_group = QGroupBox("Pfadgruppen") glyph_group.setStyleSheet(self._group_style()) glyph_layout = QVBoxLayout(glyph_group) self.glyph_scroll = QScrollArea() self.glyph_scroll.setWidgetResizable(True) self.glyph_container = QWidget() self.glyph_list_layout = QVBoxLayout(self.glyph_container) self.glyph_list_layout.setAlignment(Qt.AlignmentFlag.AlignTop) self.glyph_scroll.setWidget(self.glyph_container) glyph_layout.addWidget(self.glyph_scroll) layout.addWidget(glyph_group, stretch=1) layout.addWidget(self._separator()) # --- Export --- self.btn_export = QPushButton("Als PNG exportieren") self.btn_export.setStyleSheet(self._button_style(primary=True)) self.btn_export.clicked.connect(self.export_requested.emit) layout.addWidget(self.btn_export) def populate_glyphs(self, glyph_names: list[str]): """Füllt die Glyph-Liste mit Einträgen.""" while self.glyph_list_layout.count(): item = self.glyph_list_layout.takeAt(0) if item.widget(): item.widget().deleteLater() for name in glyph_names: lbl = QLabel(f" {name}") lbl.setStyleSheet("color: #c0c0c0; padding: 4px 0;") self.glyph_list_layout.addWidget(lbl) @staticmethod def _separator() -> QFrame: line = QFrame() line.setFrameShape(QFrame.Shape.HLine) line.setStyleSheet("color: #555;") return line @staticmethod def _group_style() -> str: return """ QGroupBox { font-weight: bold; color: #aaa; border: 1px solid #444; border-radius: 4px; margin-top: 8px; padding-top: 16px; } QGroupBox::title { subcontrol-origin: margin; left: 10px; padding: 0 4px; } """ @staticmethod def _button_style(primary: bool = False) -> str: bg = "#0078d4" if primary else "#3c3c3c" hover = "#1a8ae8" if primary else "#505050" return f""" QPushButton {{ background-color: {bg}; color: white; border: 1px solid #555; border-radius: 4px; padding: 8px 16px; font-size: 13px; }} QPushButton:hover {{ background-color: {hover}; }} """