Adding python files
This commit is contained in:
0
src/gui/dialogs/__init__.py
Normal file
0
src/gui/dialogs/__init__.py
Normal file
291
src/gui/dialogs/config_dialog.py
Normal file
291
src/gui/dialogs/config_dialog.py
Normal file
@@ -0,0 +1,291 @@
|
||||
"""
|
||||
Configuration dialog for the microscopy object detection application.
|
||||
"""
|
||||
|
||||
from PySide6.QtWidgets import (
|
||||
QDialog,
|
||||
QVBoxLayout,
|
||||
QHBoxLayout,
|
||||
QFormLayout,
|
||||
QPushButton,
|
||||
QLineEdit,
|
||||
QSpinBox,
|
||||
QDoubleSpinBox,
|
||||
QFileDialog,
|
||||
QTabWidget,
|
||||
QWidget,
|
||||
QLabel,
|
||||
QGroupBox,
|
||||
)
|
||||
from PySide6.QtCore import Qt
|
||||
|
||||
from src.utils.config_manager import ConfigManager
|
||||
from src.utils.logger import get_logger
|
||||
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class ConfigDialog(QDialog):
|
||||
"""Configuration dialog window."""
|
||||
|
||||
def __init__(self, config_manager: ConfigManager, parent=None):
|
||||
super().__init__(parent)
|
||||
|
||||
self.config_manager = config_manager
|
||||
|
||||
self.setWindowTitle("Settings")
|
||||
self.setMinimumWidth(500)
|
||||
self.setMinimumHeight(400)
|
||||
|
||||
self._setup_ui()
|
||||
self._load_settings()
|
||||
|
||||
def _setup_ui(self):
|
||||
"""Setup user interface."""
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# Create tab widget for different setting categories
|
||||
self.tab_widget = QTabWidget()
|
||||
|
||||
# General settings tab
|
||||
general_tab = self._create_general_tab()
|
||||
self.tab_widget.addTab(general_tab, "General")
|
||||
|
||||
# Training settings tab
|
||||
training_tab = self._create_training_tab()
|
||||
self.tab_widget.addTab(training_tab, "Training")
|
||||
|
||||
# Detection settings tab
|
||||
detection_tab = self._create_detection_tab()
|
||||
self.tab_widget.addTab(detection_tab, "Detection")
|
||||
|
||||
layout.addWidget(self.tab_widget)
|
||||
|
||||
# Buttons
|
||||
button_layout = QHBoxLayout()
|
||||
button_layout.addStretch()
|
||||
|
||||
self.save_button = QPushButton("Save")
|
||||
self.save_button.clicked.connect(self.accept)
|
||||
button_layout.addWidget(self.save_button)
|
||||
|
||||
self.cancel_button = QPushButton("Cancel")
|
||||
self.cancel_button.clicked.connect(self.reject)
|
||||
button_layout.addWidget(self.cancel_button)
|
||||
|
||||
layout.addLayout(button_layout)
|
||||
|
||||
self.setLayout(layout)
|
||||
|
||||
def _create_general_tab(self) -> QWidget:
|
||||
"""Create general settings tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
# Image repository group
|
||||
repo_group = QGroupBox("Image Repository")
|
||||
repo_layout = QFormLayout()
|
||||
|
||||
# Repository path
|
||||
path_layout = QHBoxLayout()
|
||||
self.repo_path_edit = QLineEdit()
|
||||
self.repo_path_edit.setPlaceholderText("Path to image repository")
|
||||
path_layout.addWidget(self.repo_path_edit)
|
||||
|
||||
browse_button = QPushButton("Browse...")
|
||||
browse_button.clicked.connect(self._browse_repository)
|
||||
path_layout.addWidget(browse_button)
|
||||
|
||||
repo_layout.addRow("Base Path:", path_layout)
|
||||
repo_group.setLayout(repo_layout)
|
||||
layout.addWidget(repo_group)
|
||||
|
||||
# Database group
|
||||
db_group = QGroupBox("Database")
|
||||
db_layout = QFormLayout()
|
||||
|
||||
self.db_path_edit = QLineEdit()
|
||||
self.db_path_edit.setPlaceholderText("Path to database file")
|
||||
db_layout.addRow("Database Path:", self.db_path_edit)
|
||||
|
||||
db_group.setLayout(db_layout)
|
||||
layout.addWidget(db_group)
|
||||
|
||||
# Models group
|
||||
models_group = QGroupBox("Models")
|
||||
models_layout = QFormLayout()
|
||||
|
||||
self.models_dir_edit = QLineEdit()
|
||||
self.models_dir_edit.setPlaceholderText("Directory for saved models")
|
||||
models_layout.addRow("Models Directory:", self.models_dir_edit)
|
||||
|
||||
self.base_model_edit = QLineEdit()
|
||||
self.base_model_edit.setPlaceholderText("yolov8s.pt")
|
||||
models_layout.addRow("Default Base Model:", self.base_model_edit)
|
||||
|
||||
models_group.setLayout(models_layout)
|
||||
layout.addWidget(models_group)
|
||||
|
||||
layout.addStretch()
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def _create_training_tab(self) -> QWidget:
|
||||
"""Create training settings tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
form_layout = QFormLayout()
|
||||
|
||||
# Epochs
|
||||
self.epochs_spin = QSpinBox()
|
||||
self.epochs_spin.setRange(1, 1000)
|
||||
self.epochs_spin.setValue(100)
|
||||
form_layout.addRow("Default Epochs:", self.epochs_spin)
|
||||
|
||||
# Batch size
|
||||
self.batch_size_spin = QSpinBox()
|
||||
self.batch_size_spin.setRange(1, 128)
|
||||
self.batch_size_spin.setValue(16)
|
||||
form_layout.addRow("Default Batch Size:", self.batch_size_spin)
|
||||
|
||||
# Image size
|
||||
self.imgsz_spin = QSpinBox()
|
||||
self.imgsz_spin.setRange(320, 1280)
|
||||
self.imgsz_spin.setSingleStep(32)
|
||||
self.imgsz_spin.setValue(640)
|
||||
form_layout.addRow("Default Image Size:", self.imgsz_spin)
|
||||
|
||||
# Patience
|
||||
self.patience_spin = QSpinBox()
|
||||
self.patience_spin.setRange(1, 200)
|
||||
self.patience_spin.setValue(50)
|
||||
form_layout.addRow("Default Patience:", self.patience_spin)
|
||||
|
||||
# Learning rate
|
||||
self.lr_spin = QDoubleSpinBox()
|
||||
self.lr_spin.setRange(0.0001, 0.1)
|
||||
self.lr_spin.setSingleStep(0.001)
|
||||
self.lr_spin.setDecimals(4)
|
||||
self.lr_spin.setValue(0.01)
|
||||
form_layout.addRow("Default Learning Rate:", self.lr_spin)
|
||||
|
||||
layout.addLayout(form_layout)
|
||||
layout.addStretch()
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def _create_detection_tab(self) -> QWidget:
|
||||
"""Create detection settings tab."""
|
||||
widget = QWidget()
|
||||
layout = QVBoxLayout()
|
||||
|
||||
form_layout = QFormLayout()
|
||||
|
||||
# Confidence threshold
|
||||
self.conf_spin = QDoubleSpinBox()
|
||||
self.conf_spin.setRange(0.0, 1.0)
|
||||
self.conf_spin.setSingleStep(0.05)
|
||||
self.conf_spin.setDecimals(2)
|
||||
self.conf_spin.setValue(0.25)
|
||||
form_layout.addRow("Default Confidence:", self.conf_spin)
|
||||
|
||||
# IoU threshold
|
||||
self.iou_spin = QDoubleSpinBox()
|
||||
self.iou_spin.setRange(0.0, 1.0)
|
||||
self.iou_spin.setSingleStep(0.05)
|
||||
self.iou_spin.setDecimals(2)
|
||||
self.iou_spin.setValue(0.45)
|
||||
form_layout.addRow("Default IoU:", self.iou_spin)
|
||||
|
||||
# Max batch size
|
||||
self.max_batch_spin = QSpinBox()
|
||||
self.max_batch_spin.setRange(1, 1000)
|
||||
self.max_batch_spin.setValue(100)
|
||||
form_layout.addRow("Max Batch Size:", self.max_batch_spin)
|
||||
|
||||
layout.addLayout(form_layout)
|
||||
layout.addStretch()
|
||||
widget.setLayout(layout)
|
||||
return widget
|
||||
|
||||
def _browse_repository(self):
|
||||
"""Browse for image repository directory."""
|
||||
directory = QFileDialog.getExistingDirectory(
|
||||
self, "Select Image Repository", self.repo_path_edit.text()
|
||||
)
|
||||
|
||||
if directory:
|
||||
self.repo_path_edit.setText(directory)
|
||||
|
||||
def _load_settings(self):
|
||||
"""Load current settings into dialog."""
|
||||
# General settings
|
||||
self.repo_path_edit.setText(
|
||||
self.config_manager.get("image_repository.base_path", "")
|
||||
)
|
||||
self.db_path_edit.setText(
|
||||
self.config_manager.get("database.path", "data/detections.db")
|
||||
)
|
||||
self.models_dir_edit.setText(
|
||||
self.config_manager.get("models.models_directory", "data/models")
|
||||
)
|
||||
self.base_model_edit.setText(
|
||||
self.config_manager.get("models.default_base_model", "yolov8s.pt")
|
||||
)
|
||||
|
||||
# Training settings
|
||||
self.epochs_spin.setValue(
|
||||
self.config_manager.get("training.default_epochs", 100)
|
||||
)
|
||||
self.batch_size_spin.setValue(
|
||||
self.config_manager.get("training.default_batch_size", 16)
|
||||
)
|
||||
self.imgsz_spin.setValue(self.config_manager.get("training.default_imgsz", 640))
|
||||
self.patience_spin.setValue(
|
||||
self.config_manager.get("training.default_patience", 50)
|
||||
)
|
||||
self.lr_spin.setValue(self.config_manager.get("training.default_lr0", 0.01))
|
||||
|
||||
# Detection settings
|
||||
self.conf_spin.setValue(
|
||||
self.config_manager.get("detection.default_confidence", 0.25)
|
||||
)
|
||||
self.iou_spin.setValue(self.config_manager.get("detection.default_iou", 0.45))
|
||||
self.max_batch_spin.setValue(
|
||||
self.config_manager.get("detection.max_batch_size", 100)
|
||||
)
|
||||
|
||||
def accept(self):
|
||||
"""Save settings and close dialog."""
|
||||
logger.info("Saving configuration")
|
||||
|
||||
# Save general settings
|
||||
self.config_manager.set(
|
||||
"image_repository.base_path", self.repo_path_edit.text()
|
||||
)
|
||||
self.config_manager.set("database.path", self.db_path_edit.text())
|
||||
self.config_manager.set("models.models_directory", self.models_dir_edit.text())
|
||||
self.config_manager.set(
|
||||
"models.default_base_model", self.base_model_edit.text()
|
||||
)
|
||||
|
||||
# Save training settings
|
||||
self.config_manager.set("training.default_epochs", self.epochs_spin.value())
|
||||
self.config_manager.set(
|
||||
"training.default_batch_size", self.batch_size_spin.value()
|
||||
)
|
||||
self.config_manager.set("training.default_imgsz", self.imgsz_spin.value())
|
||||
self.config_manager.set("training.default_patience", self.patience_spin.value())
|
||||
self.config_manager.set("training.default_lr0", self.lr_spin.value())
|
||||
|
||||
# Save detection settings
|
||||
self.config_manager.set("detection.default_confidence", self.conf_spin.value())
|
||||
self.config_manager.set("detection.default_iou", self.iou_spin.value())
|
||||
self.config_manager.set("detection.max_batch_size", self.max_batch_spin.value())
|
||||
|
||||
# Save to file
|
||||
self.config_manager.save_config()
|
||||
|
||||
super().accept()
|
||||
Reference in New Issue
Block a user