from pathlib import Path from PySide6.QtCore import Slot from PySide6.QtGui import QPixmap from PySide6.QtWidgets import QPushButton from core.database import DatabaseManager from core.media import MediaRepository from core.camera.camera_manager import CameraManager from ui.widgets.color_list_widget import ColorListWidget from ui.widgets.thumbnail_list_widget import ThumbnailListWidget from ui.widgets.split_view_widget import SplitView, CameraPlaceholder, ViewWithOverlay class MainController: def __init__(self, view): self.view = view self.db = DatabaseManager() self.media_repo = MediaRepository(self.db) self.camera_manager = CameraManager() # --- UI Widgets --- self.color_list: ColorListWidget = view.color_list_widget self.thumbnail_list: ThumbnailListWidget = view.thumbnail_widget self.split_view: SplitView = view.preview_widget self.welcome_view: CameraPlaceholder = self.split_view.widget_start self.live_view: ViewWithOverlay = self.split_view.widget_live self.photo_button: QPushButton = view.photo_button self.record_button: QPushButton = view.record_button self._connect_signals() self.db.connect() self.media_repo.sync_media() self.camera_manager.detect_cameras() def _connect_signals(self): """Connects all signals to slots.""" # Database and media signals self.color_list.colorSelected.connect(self.on_color_selected) self.color_list.editColor.connect(self.on_edit_color) self.thumbnail_list.selectedThumbnail.connect(self.on_thumbnail_selected) # Camera signals self.camera_manager.cameras_detected.connect(self.on_cameras_detected) self.camera_manager.frame_ready.connect(self.on_frame_ready) self.camera_manager.error_occurred.connect(self.on_camera_error) self.camera_manager.camera_started.connect(self.on_camera_started) self.camera_manager.camera_stopped.connect(self.on_camera_stopped) # UI control signals self.photo_button.clicked.connect(self.take_photo) self.welcome_view.camera_start_btn.clicked.connect(self.camera_detect) self.live_view.rotateCW.connect(self.camera_manager.rotate_right) self.live_view.rotateCCW.connect(self.camera_manager.rotate_left) def load_colors(self) -> None: """Loads colors from the database and populates the list.""" colors = self.db.get_all_colors() self.color_list.set_colors(colors) def shutdown(self): """Cleans up resources before application exit.""" self.camera_manager.shutdown() self.db.disconnect() # --- Slots for Database/Media --- @Slot(str) def on_color_selected(self, color_name: str): color_id = self.db.get_color_id(color_name) if color_id is not None: media_items = self.db.get_media_for_color(color_id) self.thumbnail_list.list_widget.clear() for media in media_items: if media['file_type'] == 'photo': file_name = Path(media['media_path']).name self.thumbnail_list.add_thumbnail(media['media_path'], file_name, media['id']) @Slot(str) def on_edit_color(self, color_name: str): print(f"Edycja koloru: {color_name}") # Placeholder @Slot(int) def on_thumbnail_selected(self, media_id: int): media = self.db.get_media(media_id) if media: self.split_view.set_reference_image(media['media_path']) # --- Slots for CameraManager --- @Slot(list) def on_cameras_detected(self, cameras: list[dict]): """Handles the list of detected cameras.""" print("Detected cameras:", cameras) self.welcome_view.set_info_text(f"Detected {len(cameras)} cameras.") self.welcome_view.camera_start_btn.clicked.disconnect() if len(cameras) == 0: self.welcome_view.set_button_text("Wykryj kamery") self.welcome_view.camera_start_btn.clicked.connect(self.camera_detect) else: self.welcome_view.set_button_text("Uruchom kamere") self.welcome_view.camera_start_btn.clicked.connect(self.start_liveview) # Populate a combobox in the UI here # self.view.camera_combobox.clear() # for camera in cameras: # self.view.camera_combobox.addItem(camera['name'], userData=camera['id']) @Slot(QPixmap) def on_frame_ready(self, pixmap: QPixmap): """Displays a new frame from the camera.""" self.split_view.set_live_image(pixmap) @Slot(str) def on_camera_error(self, error_message: str): """Shows an error message from the camera.""" print(f"Camera Error: {error_message}") self.welcome_view.set_error_text(error_message) @Slot() def on_camera_started(self): """Updates UI when the camera stream starts.""" self.split_view.toggle_live_view() self.welcome_view.set_button_text("Stop Camera") # Re-route button click to stop the camera self.welcome_view.camera_start_btn.clicked.disconnect() self.welcome_view.camera_start_btn.clicked.connect(self.stop_liveview) @Slot() def on_camera_stopped(self): """Updates UI when the camera stream stops.""" # self.split_view.show_placeholder() self.welcome_view.set_button_text("Start Camera") # Re-route button click to start the camera self.welcome_view.camera_start_btn.clicked.disconnect() self.welcome_view.camera_start_btn.clicked.connect(self.start_liveview) # --- UI Actions --- def camera_detect(self): self.camera_manager.detect_cameras() def start_liveview(self): """Starts the camera feed.""" detected_cameras = self.camera_manager.get_detected_cameras() if not detected_cameras: self.on_camera_error("No cameras detected.") return # For now, just start the first detected camera. # In a real app, you'd get the selected camera ID from the UI. camera_id = detected_cameras[0]['id'] self.camera_manager.start_camera(camera_id) def stop_liveview(self): """Stops the camera feed.""" self.camera_manager.stop_camera() def take_photo(self): """Takes a photo with the active camera.""" print("Taking photo...") # Placeholder # This needs to be implemented in CameraManager and called here. # e.g., self.camera_manager.take_photo() self.split_view.toggle_live_view() # This seems like a UI toggle, maybe rename?