Compare commits
	
		
			4 Commits
		
	
	
		
			feebc5153a
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 2cc496a2b2 | |||
| 0bc6c01e7e | |||
| 4d00f83083 | |||
| 2c1233f304 | 
| @@ -8,7 +8,7 @@ from core.media import MediaRepository | |||||||
| from core.camera.camera_manager import CameraManager | from core.camera.camera_manager import CameraManager | ||||||
| from ui.widgets.color_list_widget import ColorListWidget | from ui.widgets.color_list_widget import ColorListWidget | ||||||
| from ui.widgets.thumbnail_list_widget import ThumbnailListWidget | from ui.widgets.thumbnail_list_widget import ThumbnailListWidget | ||||||
| from ui.widgets.split_view_widget import SplitView, CameraPlaceholder | from ui.widgets.split_view_widget import SplitView, CameraPlaceholder, ViewWithOverlay | ||||||
|  |  | ||||||
|  |  | ||||||
| class MainController: | class MainController: | ||||||
| @@ -23,6 +23,7 @@ class MainController: | |||||||
|         self.thumbnail_list: ThumbnailListWidget = view.thumbnail_widget |         self.thumbnail_list: ThumbnailListWidget = view.thumbnail_widget | ||||||
|         self.split_view: SplitView = view.preview_widget |         self.split_view: SplitView = view.preview_widget | ||||||
|         self.welcome_view: CameraPlaceholder = self.split_view.widget_start |         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.photo_button: QPushButton = view.photo_button | ||||||
|         self.record_button: QPushButton = view.record_button |         self.record_button: QPushButton = view.record_button | ||||||
|  |  | ||||||
| @@ -48,10 +49,9 @@ class MainController: | |||||||
|  |  | ||||||
|         # UI control signals |         # UI control signals | ||||||
|         self.photo_button.clicked.connect(self.take_photo) |         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.camera_detect) | ||||||
|         self.welcome_view.camera_start_btn.clicked.connect(self.start_liveview) |         self.live_view.rotateCW.connect(self.camera_manager.rotate_right) | ||||||
|         # You will need a way to select a camera, e.g., a combobox. |         self.live_view.rotateCCW.connect(self.camera_manager.rotate_left) | ||||||
|         # self.view.camera_combobox.currentIndexChanged.connect(self.on_camera_selected_in_ui) |  | ||||||
|  |  | ||||||
|     def load_colors(self) -> None: |     def load_colors(self) -> None: | ||||||
|         """Loads colors from the database and populates the list.""" |         """Loads colors from the database and populates the list.""" | ||||||
| @@ -93,6 +93,16 @@ class MainController: | |||||||
|         """Handles the list of detected cameras.""" |         """Handles the list of detected cameras.""" | ||||||
|         print("Detected cameras:", cameras) |         print("Detected cameras:", cameras) | ||||||
|         self.welcome_view.set_info_text(f"Detected {len(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 |         # Populate a combobox in the UI here | ||||||
|         # self.view.camera_combobox.clear() |         # self.view.camera_combobox.clear() | ||||||
|         # for camera in cameras: |         # for camera in cameras: | ||||||
| @@ -130,6 +140,9 @@ class MainController: | |||||||
|  |  | ||||||
|     # --- UI Actions --- |     # --- UI Actions --- | ||||||
|  |  | ||||||
|  |     def camera_detect(self): | ||||||
|  |         self.camera_manager.detect_cameras() | ||||||
|  |  | ||||||
|     def start_liveview(self): |     def start_liveview(self): | ||||||
|         """Starts the camera feed.""" |         """Starts the camera feed.""" | ||||||
|         detected_cameras = self.camera_manager.get_detected_cameras() |         detected_cameras = self.camera_manager.get_detected_cameras() | ||||||
|   | |||||||
| @@ -18,12 +18,13 @@ class CameraWorker(QObject): | |||||||
|         self.fps = 15 |         self.fps = 15 | ||||||
|         self.is_streaming = False |         self.is_streaming = False | ||||||
|         self.is_connected = False |         self.is_connected = False | ||||||
|  |         self._rotation_index = 0 | ||||||
|         self._camera_mutex = QMutex() |         self._camera_mutex = QMutex() | ||||||
|  |  | ||||||
|     @Slot() |     @Slot() | ||||||
|     def initialize_worker(self): |     def initialize_worker(self): | ||||||
|         """Initializes the timer in the worker's thread.""" |         """Initializes the timer in the worker's thread.""" | ||||||
|         self.timer = QTimer() |         self.timer = QTimer(self) | ||||||
|         self.timer.timeout.connect(self._update_frame) |         self.timer.timeout.connect(self._update_frame) | ||||||
|  |  | ||||||
|     @Slot(BaseCamera, int) |     @Slot(BaseCamera, int) | ||||||
| @@ -93,7 +94,16 @@ class CameraWorker(QObject): | |||||||
|                     self.error_occurred.emit(error_msg) |                     self.error_occurred.emit(error_msg) | ||||||
|                 return |                 return | ||||||
|  |  | ||||||
|         if frame is not None: |         if frame is None: | ||||||
|  |             return | ||||||
|  |          | ||||||
|  |         if self._rotation_index == 1: | ||||||
|  |             frame = cv2.rotate(frame, cv2.ROTATE_90_CLOCKWISE) | ||||||
|  |         elif self._rotation_index == 2: | ||||||
|  |             frame = cv2.rotate(frame, cv2.ROTATE_180) | ||||||
|  |         elif self._rotation_index == 3: | ||||||
|  |             frame = cv2.rotate(frame, cv2.ROTATE_90_COUNTERCLOCKWISE) | ||||||
|  |  | ||||||
|         # Process the frame and emit it. |         # Process the frame and emit it. | ||||||
|         rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) |         rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) | ||||||
|         h, w, ch = rgb_image.shape |         h, w, ch = rgb_image.shape | ||||||
| @@ -101,6 +111,14 @@ class CameraWorker(QObject): | |||||||
|         pixmap = QPixmap.fromImage(qimg) |         pixmap = QPixmap.fromImage(qimg) | ||||||
|         self.frame_ready.emit(pixmap) |         self.frame_ready.emit(pixmap) | ||||||
|  |  | ||||||
|  |     @Slot() | ||||||
|  |     def rotate_left(self): | ||||||
|  |         self._rotation_index = (self._rotation_index - 1) % 4 | ||||||
|  |  | ||||||
|  |     @Slot() | ||||||
|  |     def rotate_right(self): | ||||||
|  |         self._rotation_index = (self._rotation_index + 1) % 4 | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class CameraController(QObject): | class CameraController(QObject): | ||||||
| @@ -115,6 +133,8 @@ class CameraController(QObject): | |||||||
|     _stop_camera_requested = Signal() |     _stop_camera_requested = Signal() | ||||||
|     _start_stream_requested = Signal() |     _start_stream_requested = Signal() | ||||||
|     _stop_stream_requested = Signal() |     _stop_stream_requested = Signal() | ||||||
|  |     _rotate_left_requested = Signal() | ||||||
|  |     _rotate_right_requested = Signal() | ||||||
|  |  | ||||||
|     def __init__(self, parent: QObject | None = None) -> None: |     def __init__(self, parent: QObject | None = None) -> None: | ||||||
|         super().__init__(parent) |         super().__init__(parent) | ||||||
| @@ -135,15 +155,20 @@ class CameraController(QObject): | |||||||
|         self._stop_camera_requested.connect(self._worker.stop_camera) |         self._stop_camera_requested.connect(self._worker.stop_camera) | ||||||
|         self._start_stream_requested.connect(self._worker.start_stream) |         self._start_stream_requested.connect(self._worker.start_stream) | ||||||
|         self._stop_stream_requested.connect(self._worker.stop_stream) |         self._stop_stream_requested.connect(self._worker.stop_stream) | ||||||
|  |         self._rotate_left_requested.connect(self._worker.rotate_left) | ||||||
|  |         self._rotate_right_requested.connect(self._worker.rotate_right) | ||||||
|  |  | ||||||
|         # Initialize worker when thread starts |         # Initialize worker when thread starts | ||||||
|         self._thread.started.connect(self._worker.initialize_worker) |         self._thread.started.connect(self._worker.initialize_worker) | ||||||
|  |         self._thread.finished.connect(self._worker.stop_camera) | ||||||
|  |  | ||||||
|         self._thread.start() |         self._thread.start() | ||||||
|  |  | ||||||
|     def stop(self): |     def stop(self): | ||||||
|  |         if self._thread.isRunning(): | ||||||
|             self._thread.quit() |             self._thread.quit() | ||||||
|             self._thread.wait() |             self._thread.wait() | ||||||
|  |             self._thread.deleteLater() | ||||||
|  |  | ||||||
|     def set_camera(self, camera: BaseCamera, fps: int = 15) -> None: |     def set_camera(self, camera: BaseCamera, fps: int = 15) -> None: | ||||||
|         self._set_camera_requested.emit(camera, fps) |         self._set_camera_requested.emit(camera, fps) | ||||||
| @@ -160,3 +185,10 @@ class CameraController(QObject): | |||||||
|     def stop_stream(self) -> None: |     def stop_stream(self) -> None: | ||||||
|         self._stop_stream_requested.emit() |         self._stop_stream_requested.emit() | ||||||
|      |      | ||||||
|  |     def rotate_left(self): | ||||||
|  |         self._rotate_left_requested.emit() | ||||||
|  |  | ||||||
|  |     def rotate_right(self): | ||||||
|  |         self._rotate_right_requested.emit() | ||||||
|  |  | ||||||
|  |      | ||||||
| @@ -115,6 +115,12 @@ class CameraManager(QObject): | |||||||
| 	def get_active_camera_info(self) -> dict | None: | 	def get_active_camera_info(self) -> dict | None: | ||||||
| 		return self._active_camera_info | 		return self._active_camera_info | ||||||
|  |  | ||||||
|  | 	def rotate_left(self): | ||||||
|  | 		self._camera_controller.rotate_left() | ||||||
|  |  | ||||||
|  | 	def rotate_right(self): | ||||||
|  | 		self._camera_controller.rotate_right() | ||||||
|  |  | ||||||
| 	def shutdown(self) -> None: | 	def shutdown(self) -> None: | ||||||
| 		"""Zamyka kontroler kamery i jego wątek.""" | 		"""Zamyka kontroler kamery i jego wątek.""" | ||||||
| 		self.stop_camera() | 		self.stop_camera() | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| from PySide6.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QApplication, QMainWindow, QWidget, QVBoxLayout, QSplitter, QStackedWidget, QPushButton, QLabel, QToolButton | from PySide6.QtWidgets import QGraphicsView, QGraphicsScene, QGraphicsPixmapItem, QApplication, QMainWindow, QWidget, QVBoxLayout, QSplitter, QStackedWidget, QPushButton, QLabel, QToolButton | ||||||
| from PySide6.QtGui import QEnterEvent, QPixmap, QWheelEvent, QPainter, QBrush, QColor, QIcon | from PySide6.QtGui import QEnterEvent, QPixmap, QWheelEvent, QPainter, QBrush, QColor, QIcon, QImage, QTransform | ||||||
| from PySide6.QtCore import Qt, QSize, Signal, QEvent | from PySide6.QtCore import Qt, QSize, Signal, QEvent | ||||||
| import sys | import sys | ||||||
| from ui.widgets.placeholder_widget import PlaceholderWidget | from ui.widgets.placeholder_widget import PlaceholderWidget | ||||||
| @@ -33,10 +33,14 @@ class ZoomableImageView(QGraphicsView): | |||||||
| 		self._current_scale = 1.0 | 		self._current_scale = 1.0 | ||||||
|  |  | ||||||
| 	def set_image(self, pixmap: QPixmap): | 	def set_image(self, pixmap: QPixmap): | ||||||
| 		# pixmap = QPixmap(image_path) | 		if pixmap.isNull(): | ||||||
|  | 			return | ||||||
|  | 		 | ||||||
| 		self._pixmap_item.setPixmap(pixmap) | 		self._pixmap_item.setPixmap(pixmap) | ||||||
| 		self._scene.setSceneRect(pixmap.rect()) | 		self._scene.setSceneRect(pixmap.rect()) | ||||||
| 		# self.reset_transform() | 		if self._current_scale == 1.0: | ||||||
|  | 			self.fitInView(self._pixmap_item, Qt.AspectRatioMode.KeepAspectRatio) | ||||||
|  | 			self._first_image = False | ||||||
|  |  | ||||||
| 	def reset_transform(self): | 	def reset_transform(self): | ||||||
| 		"""Resetuje skalowanie i ustawia 1:1""" | 		"""Resetuje skalowanie i ustawia 1:1""" | ||||||
| @@ -281,10 +285,15 @@ class SplitView(QSplitter): | |||||||
| 		# pixmap.fill(Qt.GlobalColor.lightGray) | 		# pixmap.fill(Qt.GlobalColor.lightGray) | ||||||
| 		# self.widget_live.set_image(pixmap) | 		# self.widget_live.set_image(pixmap) | ||||||
|  |  | ||||||
|  | 		self.ref_image_rotate = 0 | ||||||
|  | 		self.ref_pixmap = None | ||||||
|  |  | ||||||
| 		self.widget_live.toggleOrientation.connect(self.toggle_orientation) | 		self.widget_live.toggleOrientation.connect(self.toggle_orientation) | ||||||
| 		self.widget_ref.toggleOrientation.connect(self.toggle_orientation) | 		self.widget_ref.toggleOrientation.connect(self.toggle_orientation) | ||||||
| 		self.widget_live.swapViews.connect(self.swap_views) | 		self.widget_live.swapViews.connect(self.swap_views) | ||||||
| 		self.widget_ref.swapViews.connect(self.swap_views) | 		self.widget_ref.swapViews.connect(self.swap_views) | ||||||
|  | 		self.widget_ref.rotateCCW.connect(self.rotate_left) | ||||||
|  | 		self.widget_ref.rotateCW.connect(self.rotate_right) | ||||||
|  |  | ||||||
| 	def toggle_orientation(self): | 	def toggle_orientation(self): | ||||||
| 		if self.orientation() == Qt.Orientation.Vertical: | 		if self.orientation() == Qt.Orientation.Vertical: | ||||||
| @@ -315,8 +324,10 @@ class SplitView(QSplitter): | |||||||
|  |  | ||||||
| 	def set_reference_image(self, path_image: str): | 	def set_reference_image(self, path_image: str): | ||||||
| 		"""Ustawienie obrazu referencyjnego""" | 		"""Ustawienie obrazu referencyjnego""" | ||||||
| 		pixmap = QPixmap(path_image) | 		self.ref_pixmap = QPixmap(path_image) | ||||||
| 		self.widget_ref.set_image(pixmap) | 		if self.ref_image_rotate != 0: | ||||||
|  | 			self.ref_pixmap = self.ref_pixmap.transformed(QTransform().rotate(self.ref_image_rotate)) | ||||||
|  | 		self.widget_ref.set_image(self.ref_pixmap) | ||||||
|  |  | ||||||
| 	def toggle_live_view(self): | 	def toggle_live_view(self): | ||||||
| 		"""Przełączanie widoku na żywo""" | 		"""Przełączanie widoku na żywo""" | ||||||
| @@ -324,3 +335,17 @@ class SplitView(QSplitter): | |||||||
| 			self.stack.setCurrentWidget(self.widget_live) | 			self.stack.setCurrentWidget(self.widget_live) | ||||||
| 		else: | 		else: | ||||||
| 			self.stack.setCurrentWidget(self.widget_start) | 			self.stack.setCurrentWidget(self.widget_start) | ||||||
|  |  | ||||||
|  | 	def rotate_left(self): | ||||||
|  | 		if not self.ref_pixmap: | ||||||
|  | 			return | ||||||
|  | 		self.ref_image_rotate = (self.ref_image_rotate - 90) % 360 | ||||||
|  | 		self.ref_pixmap  = self.ref_pixmap.transformed(QTransform().rotate(-90)) | ||||||
|  | 		self.widget_ref.set_image(self.ref_pixmap) | ||||||
|  | 	 | ||||||
|  | 	def rotate_right(self): | ||||||
|  | 		if not self.ref_pixmap: | ||||||
|  | 			return | ||||||
|  | 		self.ref_image_rotate = (self.ref_image_rotate + 90) % 360 | ||||||
|  | 		self.ref_pixmap  = self.ref_pixmap.transformed(QTransform().rotate(90)) | ||||||
|  | 		self.widget_ref.set_image(self.ref_pixmap) | ||||||
		Reference in New Issue
	
	Block a user