Files
MayoStainHelper/controllers/main_controller.py

154 lines
6.1 KiB
Python

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
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.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.record_button.clicked.connect(self.toggle_record) # Placeholder
self.welcome_view.camera_start_btn.clicked.connect(self.start_liveview)
# You will need a way to select a camera, e.g., a combobox.
# self.view.camera_combobox.currentIndexChanged.connect(self.on_camera_selected_in_ui)
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.")
# 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.show_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 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?