Files
duck-stain-yolo/app/settings_dialog.py
bartool 090865af76 Initial MVP application skeleton
Add PySide6 camera UI, YOLO/Tesseract detection pipeline, capture metadata, configuration, and project gitignore.
2026-05-07 00:18:38 +02:00

126 lines
4.0 KiB
Python

from __future__ import annotations
from copy import deepcopy
from typing import Any
from PySide6.QtCore import Qt, Signal
from PySide6.QtWidgets import (
QCheckBox,
QDialog,
QFormLayout,
QHBoxLayout,
QLabel,
QPushButton,
QSlider,
QSpinBox,
QVBoxLayout,
QWidget,
)
CAMERA_PROPERTY_LABELS = {
"brightness": "Jasnosc",
"contrast": "Kontrast",
"saturation": "Nasycenie",
"hue": "Barwa",
"gain": "Gain",
"exposure": "Ekspozycja",
"sharpness": "Ostrosc",
"auto_exposure": "Auto ekspozycja",
"focus": "Focus",
"auto_focus": "Auto focus",
}
class PropertySlider(QWidget):
value_changed = Signal(str, object)
def __init__(self, name: str, value: float | None) -> None:
super().__init__()
self.name = name
self.enabled_box = QCheckBox()
self.enabled_box.setChecked(value is not None)
self.slider = QSlider(Qt.Horizontal)
self.slider.setRange(-100, 100)
self.slider.setValue(int(value) if value is not None else 0)
self.value_box = QSpinBox()
self.value_box.setRange(-100, 100)
self.value_box.setValue(self.slider.value())
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.addWidget(self.enabled_box)
layout.addWidget(self.slider, 1)
layout.addWidget(self.value_box)
self.slider.valueChanged.connect(self.value_box.setValue)
self.value_box.valueChanged.connect(self.slider.setValue)
self.slider.valueChanged.connect(self._emit_value)
self.enabled_box.toggled.connect(self._emit_value)
def _emit_value(self) -> None:
self.value_changed.emit(self.name, self.value())
def value(self) -> float | None:
if not self.enabled_box.isChecked():
return None
return float(self.slider.value())
class SettingsDialog(QDialog):
settings_saved = Signal(dict)
def __init__(self, config: dict[str, Any], parent: QWidget | None = None) -> None:
super().__init__(parent)
self.setWindowTitle("Ustawienia obrazu")
self.setMinimumWidth(520)
self.config = deepcopy(config)
self.property_widgets: dict[str, PropertySlider] = {}
camera_cfg = self.config["camera"]
main_layout = QVBoxLayout(self)
form = QFormLayout()
self.width_box = QSpinBox()
self.width_box.setRange(160, 7680)
self.width_box.setValue(int(camera_cfg.get("width", 1920)))
self.height_box = QSpinBox()
self.height_box.setRange(120, 4320)
self.height_box.setValue(int(camera_cfg.get("height", 1080)))
self.fps_box = QSpinBox()
self.fps_box.setRange(1, 240)
self.fps_box.setValue(int(camera_cfg.get("fps", 30)))
form.addRow("Szerokosc", self.width_box)
form.addRow("Wysokosc", self.height_box)
form.addRow("FPS", self.fps_box)
for name, label in CAMERA_PROPERTY_LABELS.items():
widget = PropertySlider(name, camera_cfg.get("properties", {}).get(name))
self.property_widgets[name] = widget
form.addRow(QLabel(label), widget)
main_layout.addLayout(form)
buttons = QHBoxLayout()
buttons.addStretch(1)
cancel_button = QPushButton("Anuluj")
save_button = QPushButton("Zapisz")
save_button.setDefault(True)
buttons.addWidget(cancel_button)
buttons.addWidget(save_button)
main_layout.addLayout(buttons)
cancel_button.clicked.connect(self.reject)
save_button.clicked.connect(self._save)
def _save(self) -> None:
self.config["camera"]["width"] = int(self.width_box.value())
self.config["camera"]["height"] = int(self.height_box.value())
self.config["camera"]["fps"] = int(self.fps_box.value())
self.config["camera"]["properties"] = {
name: widget.value() for name, widget in self.property_widgets.items()
}
self.settings_saved.emit(self.config["camera"])
self.accept()