From d63d6166757b5ecf01d0652e9241e4d45e9fdc4b Mon Sep 17 00:00:00 2001 From: bartool Date: Sun, 12 Oct 2025 10:31:40 +0200 Subject: [PATCH] working on camera-manager --- controllers/main_controller.py | 69 ++++++++++++++++-- core/camera/camera_manager.py | 123 +++++++++++++++++++++++++++++---- 2 files changed, 175 insertions(+), 17 deletions(-) diff --git a/controllers/main_controller.py b/controllers/main_controller.py index 6453a84..3853eb4 100644 --- a/controllers/main_controller.py +++ b/controllers/main_controller.py @@ -4,7 +4,7 @@ from core.database import DatabaseManager from core.media import MediaRepository from ui.widgets.color_list_widget import ColorListWidget from ui.widgets.thumbnail_list_widget import ThumbnailListWidget -from ui.widgets.split_view_widget import SplitView +from ui.widgets.split_view_widget import SplitView, CameraPlaceholder # from .camera_controller import CameraController from core.camera.camera_controller import CameraController from core.camera.camera_manager import CameraManager @@ -23,8 +23,9 @@ class MainController: # camera = GPhotoCamera() # self.manager = CameraController(camera) manager = CameraManager() - manager.detect_gphoto() - manager.detect_opencv() + # manager.detect_gphoto() + # manager.detect_opencv() + manager.detect_camera() # self.camera_controller = CameraController() @@ -32,6 +33,7 @@ class MainController: 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.photo_button.clicked.connect(self.take_photo) @@ -50,6 +52,9 @@ class MainController: # self.split_view.widget_start.camera_start_btn.clicked.connect(self.camera_controller.start) self.split_view.widget_start.camera_start_btn.clicked.connect(self.start_liveview) + self.welcome_view.set_button_text("tada") + self.welcome_view.set_error_text("errorsy") + def start_camera(self): pass @@ -97,4 +102,60 @@ class MainController: def shutdown(self): pass - # self.manager.stop() \ No newline at end of file + # self.manager.stop() + + + + # @Slot(list) + def on_cameras_detected(self, cameras: list[dict]): + print("Wykryto kamery:", cameras) + # Tutaj zaktualizuj swój ComboBox w UI, np.: + # self.main_window.camera_combobox.clear() + # for camera in cameras: + # self.main_window.camera_combobox.addItem(camera['name'], userData=camera['id']) + + # @Slot(QPixmap) + def on_frame_ready(self, pixmap: QPixmap): + # Tutaj zaktualizuj widget wyświetlający obraz, np. QLabel + # self.main_window.video_label.setPixmap(pixmap) + pass + + # @Slot(str) + def on_camera_error(self, error_message: str): + print(f"Błąd kamery: {error_message}") + # Wyświetl błąd w UI, np. w status barze + # self.main_window.statusBar().showMessage(error_message, 5000) + + # @Slot() + def on_camera_started(self): + # Zmień stan UI, np. tekst przycisku na "Stop" + # self.main_window.toggle_camera_button.setText("Stop") + pass + + # @Slot() + def on_camera_stopped(self): + # Zmień stan UI, np. tekst przycisku na "Start" + # self.main_window.toggle_camera_button.setText("Start") + pass + + def toggle_camera(self): + # Logika do przełączania start/stop + if self.camera_manager.get_active_camera_info(): + self.camera_manager.stop_camera() + else: + # Pobierz ID kamery z ComboBoxa + # camera_id = self.main_window.camera_combobox.currentData() + # if camera_id: + # self.camera_manager.start_camera(camera_id) + pass + + def on_camera_selected(self, index: int): + # Automatycznie uruchom kamerę po wybraniu z listy + # camera_id = self.main_window.camera_combobox.itemData(index) + # if camera_id: + # self.camera_manager.start_camera(camera_id) + pass + + def cleanup(self): + # Wywołaj to przy zamykaniu aplikacji + self.camera_manager.shutdown() \ No newline at end of file diff --git a/core/camera/camera_manager.py b/core/camera/camera_manager.py index 5fbea5c..e3b7e2c 100644 --- a/core/camera/camera_manager.py +++ b/core/camera/camera_manager.py @@ -1,20 +1,117 @@ +from PySide6.QtCore import QObject, Signal +from PySide6.QtGui import QPixmap - +from .camera_controller import CameraController from .gphoto_camera import GPhotoCamera from .opencv_camera import OpenCvCamera -from .camera_controller import CameraController +from .base_camera import BaseCamera + +class CameraManager(QObject): + """ + Zarządza wszystkimi operacjami związanymi z kamerami, + stanowiąc fasadę dla reszty aplikacji. + """ + frame_ready = Signal(QPixmap) + error_occurred = Signal(str) + cameras_detected = Signal(list) + camera_started = Signal() + camera_stopped = Signal() + + def __init__(self, parent: QObject | None = None) -> None: + super().__init__(parent) + self._camera_controller = CameraController() + self._detected_cameras: list[dict] = [] + self._active_camera: BaseCamera | None = None + self._active_camera_info: dict | None = None + + # Przekazywanie sygnałów z kontrolera kamery na zewnątrz + self._camera_controller.frame_ready.connect(self.frame_ready) + self._camera_controller.error_occurred.connect(self.error_occurred) + + def detect_cameras(self) -> None: + """Wykrywa wszystkie dostępne kamery (GPhoto i OpenCV).""" + self._detected_cameras.clear() + + # Wykryj kamery GPhoto + try: + gphoto_cameras = GPhotoCamera.detect() + for index, info in gphoto_cameras.items(): + self._detected_cameras.append({ + "id": f"gphoto_{index}", + "name": f"{info['name']} ({info['port']})", + "type": "gphoto", + "index": index + }) + except Exception as e: + self.error_occurred.emit(f"Błąd podczas wykrywania kamer GPhoto: {e}") + + # Wykryj kamery OpenCV + try: + opencv_cameras = OpenCvCamera.detect() + for index, info in opencv_cameras.items(): + self._detected_cameras.append({ + "id": f"opencv_{index}", + "name": f"OpenCV: {info['name']}", + "type": "opencv", + "index": index + }) + except Exception as e: + self.error_occurred.emit(f"Błąd podczas wykrywania kamer OpenCV: {e}") + + self.cameras_detected.emit(self._detected_cameras) + + def get_detected_cameras(self) -> list[dict]: + return self._detected_cameras + + def start_camera(self, camera_id: str, fps: int = 15) -> None: + """Uruchamia wybraną kamerę.""" + if self._active_camera: + self.stop_camera() + + camera_info = next((c for c in self._detected_cameras if c['id'] == camera_id), None) + + if not camera_info: + self.error_occurred.emit(f"Nie znaleziono kamery o ID: {camera_id}") + return + + camera_type = camera_info['type'] + camera_index = camera_info['index'] + + if camera_type == "gphoto": + self._active_camera = GPhotoCamera() + elif camera_type == "opencv": + self._active_camera = OpenCvCamera() + else: + self.error_occurred.emit(f"Nieznany typ kamery: {camera_type}") + return + + self._active_camera_info = camera_info + + self._camera_controller.set_camera(self._active_camera, fps) + self._camera_controller.start_camera() + + # Trzeba sprawdzić, czy połączenie się udało + if self._camera_controller.is_connected: + self._camera_controller.start_stream() + self.camera_started.emit() + else: + # Błąd został już wyemitowany przez CameraController + self._active_camera = None + self._active_camera_info = None -class CameraManager: - def __init__(self) -> None: - pass + def stop_camera(self) -> None: + """Zatrzymuje aktywną kamerę.""" + if self._active_camera: + self._camera_controller.stop_camera() + self._active_camera = None + self._active_camera_info = None + self.camera_stopped.emit() - def detect_gphoto(self): - camera_list = GPhotoCamera.detect() - print(camera_list) - return camera_list + def get_active_camera_info(self) -> dict | None: + return self._active_camera_info - def detect_opencv(self): - camera_list = OpenCvCamera.detect() - print(camera_list) - return camera_list + def shutdown(self) -> None: + """Zamyka kontroler kamery i jego wątek.""" + self.stop_camera() + self._camera_controller.stop() \ No newline at end of file