Compare commits
4 Commits
feebc5153a
...
2cc496a2b2
| Author | SHA1 | Date | |
|---|---|---|---|
| 2cc496a2b2 | |||
| 0bc6c01e7e | |||
| 4d00f83083 | |||
| 2c1233f304 |
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user