Compare commits

...

4 Commits

4 changed files with 96 additions and 20 deletions

View File

@@ -8,7 +8,7 @@ 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
from ui.widgets.split_view_widget import SplitView, CameraPlaceholder, ViewWithOverlay
class MainController:
@@ -23,6 +23,7 @@ class MainController:
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
@@ -48,10 +49,9 @@ class MainController:
# 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)
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."""
@@ -93,6 +93,16 @@ class MainController:
"""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:
@@ -130,6 +140,9 @@ class MainController:
# --- 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()

View File

@@ -18,12 +18,13 @@ class CameraWorker(QObject):
self.fps = 15
self.is_streaming = False
self.is_connected = False
self._rotation_index = 0
self._camera_mutex = QMutex()
@Slot()
def initialize_worker(self):
"""Initializes the timer in the worker's thread."""
self.timer = QTimer()
self.timer = QTimer(self)
self.timer.timeout.connect(self._update_frame)
@Slot(BaseCamera, int)
@@ -93,13 +94,30 @@ class CameraWorker(QObject):
self.error_occurred.emit(error_msg)
return
if frame is not None:
# Process the frame and emit it.
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgb_image.shape
qimg = QImage(rgb_image.data, w, h, ch * w, QImage.Format.Format_RGB888)
pixmap = QPixmap.fromImage(qimg)
self.frame_ready.emit(pixmap)
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.
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = rgb_image.shape
qimg = QImage(rgb_image.data, w, h, ch * w, QImage.Format.Format_RGB888)
pixmap = QPixmap.fromImage(qimg)
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
@@ -115,6 +133,8 @@ class CameraController(QObject):
_stop_camera_requested = Signal()
_start_stream_requested = Signal()
_stop_stream_requested = Signal()
_rotate_left_requested = Signal()
_rotate_right_requested = Signal()
def __init__(self, parent: QObject | None = None) -> None:
super().__init__(parent)
@@ -135,15 +155,20 @@ class CameraController(QObject):
self._stop_camera_requested.connect(self._worker.stop_camera)
self._start_stream_requested.connect(self._worker.start_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
self._thread.started.connect(self._worker.initialize_worker)
self._thread.finished.connect(self._worker.stop_camera)
self._thread.start()
def stop(self):
self._thread.quit()
self._thread.wait()
if self._thread.isRunning():
self._thread.quit()
self._thread.wait()
self._thread.deleteLater()
def set_camera(self, camera: BaseCamera, fps: int = 15) -> None:
self._set_camera_requested.emit(camera, fps)
@@ -159,4 +184,11 @@ class CameraController(QObject):
def stop_stream(self) -> None:
self._stop_stream_requested.emit()
def rotate_left(self):
self._rotate_left_requested.emit()
def rotate_right(self):
self._rotate_right_requested.emit()

View File

@@ -115,6 +115,12 @@ class CameraManager(QObject):
def get_active_camera_info(self) -> dict | None:
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:
"""Zamyka kontroler kamery i jego wątek."""
self.stop_camera()

View File

@@ -1,5 +1,5 @@
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
import sys
from ui.widgets.placeholder_widget import PlaceholderWidget
@@ -33,10 +33,14 @@ class ZoomableImageView(QGraphicsView):
self._current_scale = 1.0
def set_image(self, pixmap: QPixmap):
# pixmap = QPixmap(image_path)
if pixmap.isNull():
return
self._pixmap_item.setPixmap(pixmap)
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):
"""Resetuje skalowanie i ustawia 1:1"""
@@ -281,10 +285,15 @@ class SplitView(QSplitter):
# pixmap.fill(Qt.GlobalColor.lightGray)
# 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_ref.toggleOrientation.connect(self.toggle_orientation)
self.widget_live.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):
if self.orientation() == Qt.Orientation.Vertical:
@@ -315,8 +324,10 @@ class SplitView(QSplitter):
def set_reference_image(self, path_image: str):
"""Ustawienie obrazu referencyjnego"""
pixmap = QPixmap(path_image)
self.widget_ref.set_image(pixmap)
self.ref_pixmap = QPixmap(path_image)
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):
"""Przełączanie widoku na żywo"""
@@ -324,3 +335,17 @@ class SplitView(QSplitter):
self.stack.setCurrentWidget(self.widget_live)
else:
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)