diff --git a/ui/icons/camera_hdmi.svg b/ui/icons/camera_hdmi.svg new file mode 100644 index 0000000..7c2dd96 --- /dev/null +++ b/ui/icons/camera_hdmi.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + HDMI + + diff --git a/ui/icons/camera_usb.svg b/ui/icons/camera_usb.svg new file mode 100644 index 0000000..4d88842 --- /dev/null +++ b/ui/icons/camera_usb.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + USB + + diff --git a/ui/icons/camera_usb_hdmi.svg b/ui/icons/camera_usb_hdmi.svg new file mode 100644 index 0000000..4f24bd1 --- /dev/null +++ b/ui/icons/camera_usb_hdmi.svg @@ -0,0 +1,75 @@ + + + + + + + + + + + HDMI + USB + + diff --git a/ui/icons/error-16-svgrepo-com.svg b/ui/icons/error-16-svgrepo-com.svg new file mode 100644 index 0000000..6fd3924 --- /dev/null +++ b/ui/icons/error-16-svgrepo-com.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/ui/icons/settings-svgrepo-com.svg b/ui/icons/settings-svgrepo-com.svg new file mode 100644 index 0000000..9b8a117 --- /dev/null +++ b/ui/icons/settings-svgrepo-com.svg @@ -0,0 +1,17 @@ + + + + + settings + Created with Sketch Beta. + + + + + + + + + + + \ No newline at end of file diff --git a/ui/widgets/split_view_widget.py b/ui/widgets/split_view_widget.py index 1a18486..c57bad1 100644 --- a/ui/widgets/split_view_widget.py +++ b/ui/widgets/split_view_widget.py @@ -6,284 +6,313 @@ from ui.widgets.placeholder_widget import PlaceholderWidget class ZoomableImageView(QGraphicsView): - def __init__(self, parent=None): - super().__init__(parent) + def __init__(self, parent=None): + super().__init__(parent) - # Scena i element obrazu - self._scene = QGraphicsScene(self) - self.setScene(self._scene) - self._scene.setBackgroundBrush( - QBrush(QColor(20, 20, 20))) # ciemne tło + # Scena i element obrazu + self._scene = QGraphicsScene(self) + self.setScene(self._scene) + self._scene.setBackgroundBrush( + QBrush(QColor(20, 20, 20))) # ciemne tło - self._pixmap_item = QGraphicsPixmapItem() - self._scene.addItem(self._pixmap_item) + self._pixmap_item = QGraphicsPixmapItem() + self._scene.addItem(self._pixmap_item) - # Ustawienia widoku - # przesuwanie myszą - self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag) - self.setRenderHint(QPainter.RenderHint.Antialiasing) - self.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform) + # Ustawienia widoku + # przesuwanie myszą + self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag) + self.setRenderHint(QPainter.RenderHint.Antialiasing) + self.setRenderHint(QPainter.RenderHint.SmoothPixmapTransform) - # Wyłączenie suwaków - self.setHorizontalScrollBarPolicy( - Qt.ScrollBarPolicy.ScrollBarAlwaysOff) - self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) - # Parametry zoomu - self._zoom_factor = 1.25 - self._current_scale = 1.0 + # Wyłączenie suwaków + self.setHorizontalScrollBarPolicy( + Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + # Parametry zoomu + self._zoom_factor = 1.25 + self._current_scale = 1.0 - def set_image(self, pixmap: QPixmap): - # pixmap = QPixmap(image_path) - self._pixmap_item.setPixmap(pixmap) - self._scene.setSceneRect(pixmap.rect()) - # self.reset_transform() + def set_image(self, pixmap: QPixmap): + # pixmap = QPixmap(image_path) + self._pixmap_item.setPixmap(pixmap) + self._scene.setSceneRect(pixmap.rect()) + # self.reset_transform() - def reset_transform(self): - """Resetuje skalowanie i ustawia 1:1""" - self._current_scale = 1.0 - self.setTransform(self.transform().fromScale(1, 1)) + def reset_transform(self): + """Resetuje skalowanie i ustawia 1:1""" + self._current_scale = 1.0 + self.setTransform(self.transform().fromScale(1, 1)) - def wheelEvent(self, event: QWheelEvent): - """Zoom kółkiem myszy""" - if event.modifiers() & Qt.KeyboardModifier.ControlModifier: # zoom tylko z CTRL - if event.angleDelta().y() > 0: - zoom = self._zoom_factor - else: - zoom = 1 / self._zoom_factor + def wheelEvent(self, event: QWheelEvent): + """Zoom kółkiem myszy""" + if event.modifiers() & Qt.KeyboardModifier.ControlModifier: # zoom tylko z CTRL + if event.angleDelta().y() > 0: + zoom = self._zoom_factor + else: + zoom = 1 / self._zoom_factor - self._current_scale *= zoom - self.scale(zoom, zoom) - else: - return - super().wheelEvent(event) # normalne przewijanie + self._current_scale *= zoom + self.scale(zoom, zoom) + else: + return + super().wheelEvent(event) # normalne przewijanie class CameraPlaceholder(QWidget): - def __init__(self, parent=None): - super().__init__(parent) + def __init__(self, parent=None): + super().__init__(parent) - self.setAutoFillBackground(True) - self.setStyleSheet("background-color: #141414;") + self.setAutoFillBackground(True) + self.setStyleSheet("background-color: #141414;") - layout = QVBoxLayout(self) - layout.setSpacing(20) + layout = QVBoxLayout(self) + layout.setSpacing(20) - self.camera_start_btn = QPushButton("Start Camera") - self.camera_start_btn.setFixedSize(200, 50) - style_sheet = """ - QPushButton { - /* --- Styl podstawowy --- */ - background-color: transparent; - border: 2px solid #CECECE; /* Grubość, styl i kolor obramowania */ - border-radius: 25px; /* Kluczowa właściwość do zaokrąglenia rogów! */ - color: #CECECE; - padding: 10px 20px; /* Wewnętrzny margines */ - font-size: 16px; - } + self.camera_start_btn = QPushButton("Start Camera") + self.camera_start_btn.setFixedSize(200, 50) + style_sheet = """ + QPushButton { + /* --- Styl podstawowy --- */ + background-color: transparent; + border: 2px solid #CECECE; /* Grubość, styl i kolor obramowania */ + border-radius: 25px; /* Kluczowa właściwość do zaokrąglenia rogów! */ + color: #CECECE; + padding: 10px 20px; /* Wewnętrzny margines */ + font-size: 16px; + } - QPushButton:hover { - /* --- Styl po najechaniu myszką --- */ - color: #F0F0F0; - border: 2px solid #F0F0F0; - } + QPushButton:hover { + /* --- Styl po najechaniu myszką --- */ + color: #F0F0F0; + border: 2px solid #F0F0F0; + } - QPushButton:pressed { - /* --- Styl po naciśnięciu --- */ - background-color: #e0e0e0; /* Ciemniejsze tło w momencie kliknięcia */ - border: 2px solid #e0e0e0; /* Zmiana koloru ramki dla sygnalizacji akcji */ - } - """ - self.camera_start_btn.setStyleSheet(style_sheet) + QPushButton:pressed { + /* --- Styl po naciśnięciu --- */ + background-color: #e0e0e0; /* Ciemniejsze tło w momencie kliknięcia */ + border: 2px solid #e0e0e0; /* Zmiana koloru ramki dla sygnalizacji akcji */ + } + """ + self.camera_start_btn.setStyleSheet(style_sheet) - self.info_label = QLabel("Kliknij, aby uruchomić kamerę") - self.info_label.setStyleSheet( - "background-color: transparent; color: #CECECE; font-size: 18px;") - self.info_label.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.info_label = QLabel("Kliknij, aby uruchomić kamerę") + self.info_label.setStyleSheet( + "background-color: transparent; color: #CECECE; font-size: 18px;") + self.info_label.setAlignment(Qt.AlignmentFlag.AlignCenter) - layout.addStretch() - layout.addWidget(self.camera_start_btn, - alignment=Qt.AlignmentFlag.AlignCenter) - layout.addWidget(self.info_label) - layout.addStretch() - self.setLayout(layout) + layout.addStretch() + layout.addWidget(self.camera_start_btn, + alignment=Qt.AlignmentFlag.AlignCenter) + layout.addWidget(self.info_label) + layout.addStretch() + self.setLayout(layout) - def set_info_text(self, text: str): - self.info_label.setText(text) + def set_info_text(self, text: str): + self.info_label.setText(text) class ViewWithOverlay(QWidget): - toggleOrientation = Signal() - swapViews = Signal() - rotateCW = Signal() - rotateCCW = Signal() + cameraConnection = Signal() + cameraSettings = Signal() + toggleOrientation = Signal() + swapViews = Signal() + rotateCW = Signal() + rotateCCW = Signal() - def __init__(self): - super().__init__() - layout = QVBoxLayout(self) - layout.setContentsMargins(0, 0, 0, 0) + def __init__(self, live: bool = False): + super().__init__() + self.live = live - self.viewer = ZoomableImageView() - layout.addWidget(self.viewer) + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) - icon_size = QSize(32, 32) - btn_size = (48, 48) - btn_style = """ - background-color: rgba(255, 255, 255, 0.5); - border-radius: 8px; - border: 2px solid #1f1f1f; - """ + self.viewer = ZoomableImageView() + layout.addWidget(self.viewer) + self._create_top_right_buttons() + if self.live: + self._create_top_left_buttons() - self.cw_btn = QToolButton(self) - self.cw_btn.setIcon(QIcon("ui/icons/rotate-cw-svgrepo-com.svg")) - self.cw_btn.setIconSize(icon_size) - self.cw_btn.setStyleSheet(btn_style) - self.cw_btn.setFixedSize(*btn_size) - move_x = self.cw_btn.width() + 10 - self.cw_btn.move(self.width() - move_x, 10) - self.cw_btn.clicked.connect(self.rotateCW) + self.resize(self.size()) - self.ccw_btn = QToolButton(self) - self.ccw_btn.setIcon(QIcon("ui/icons/rotate-ccw-svgrepo-com.svg")) - self.ccw_btn.setIconSize(icon_size) - self.ccw_btn.setStyleSheet(btn_style) - self.ccw_btn.setFixedSize(*btn_size) - move_x += self.ccw_btn.width() + 10 - self.ccw_btn.move(self.width() - move_x, 10) - self.ccw_btn.clicked.connect(self.rotateCCW) + # self.cw_btn.raise_() + # self.ccw_btn.raise_() + # self.flip_btn.raise_() + # self.orient_btn.raise_() - self.flip_btn = QToolButton(self) - # self.flip_btn.setIcon(QIcon("ui/icons/flip-vertical-svgrepo-com.svg")) - self.flip_btn.setIconSize(icon_size) - self.flip_btn.setStyleSheet(btn_style) - self.flip_btn.setFixedSize(*btn_size) - move_x += self.flip_btn.width() + 10 - self.flip_btn.move(self.width() - move_x, 10) - self.flip_btn.clicked.connect(self.swapViews) + self.toggle_orientation(Qt.Orientation.Vertical) - self.orient_btn = QToolButton(self) - # self.orient_btn.setIcon(QIcon("ui/icons/horizontal-stacks-svgrepo-com.svg")) - self.orient_btn.setIconSize(icon_size) - self.orient_btn.setStyleSheet(btn_style) - self.orient_btn.setFixedSize(*btn_size) - move_x += self.orient_btn.width() + 10 - self.orient_btn.move(self.width() - move_x, 10) - self.orient_btn.clicked.connect(self.toggleOrientation) + def _create_tool_button(self, callback, icon_path: str | None): + icon_size = QSize(32, 32) + btn_size = (48, 48) + btn_style = """ + background-color: rgba(255, 255, 255, 0.5); + border-radius: 8px; + border: 2px solid #1f1f1f; + """ + btn = QToolButton(self) + if icon_path: + btn.setIcon(QIcon(icon_path)) + btn.setIconSize(icon_size) + btn.setStyleSheet(btn_style) + btn.setFixedSize(*btn_size) + btn.clicked.connect(callback) - self.cw_btn.raise_() - self.ccw_btn.raise_() - self.flip_btn.raise_() - self.orient_btn.raise_() + return btn + + def _create_top_right_buttons(self): + self.cw_btn = self._create_tool_button( + icon_path="ui/icons/rotate-cw-svgrepo-com.svg", + callback=self.rotateCW, + ) - self.toggle_orientation(Qt.Orientation.Vertical) + self.ccw_btn = self._create_tool_button( + icon_path="ui/icons/rotate-ccw-svgrepo-com.svg", + callback=self.rotateCCW, + ) - def set_image(self, pixmap: QPixmap): - self.viewer.set_image(pixmap) + self.flip_btn = self._create_tool_button( + icon_path=None, + callback=self.swapViews, + ) - def resizeEvent(self, event): - super().resizeEvent(event) - # Aktualizacja pozycji przycisku przy zmianie rozmiaru - move_x = self.cw_btn.width() + 10 - self.cw_btn.move(self.width() - move_x, 10) - move_x += self.ccw_btn.width() + 10 - self.ccw_btn.move(self.width() - move_x, 10) - move_x += self.flip_btn.width() + 10 - self.flip_btn.move(self.width() - move_x, 10) - move_x += self.orient_btn.width() + 10 - self.orient_btn.move(self.width() - move_x, 10) + self.orient_btn = self._create_tool_button( + icon_path=None, + callback=self.toggleOrientation, + ) - def toggle_orientation(self, orientation): - if orientation == Qt.Orientation.Vertical: - self.flip_btn.setIcon(QIcon("ui/icons/flip-vertical-svgrepo-com.svg")) - self.orient_btn.setIcon(QIcon("ui/icons/horizontal-stacks-svgrepo-com.svg")) - else: - self.flip_btn.setIcon(QIcon("ui/icons/flip-horizontal-svgrepo-com.svg")) - self.orient_btn.setIcon(QIcon("ui/icons/vertical-stacks-svgrepo-com.svg")) - - def enterEvent(self, event: QEnterEvent) -> None: - self.orient_btn.show() - self.flip_btn.show() - self.ccw_btn.show() - self.cw_btn.show() - return super().enterEvent(event) - - def leaveEvent(self, event: QEvent) -> None: - self.orient_btn.hide() - self.flip_btn.hide() - self.ccw_btn.hide() - self.cw_btn.hide() - return super().leaveEvent(event) - + def _create_top_left_buttons(self): + self.camera_btn = self._create_tool_button( + icon_path="ui/icons/settings-svgrepo-com.svg", + callback=self.cameraConnection + ) + + self.settings_btn = self._create_tool_button( + icon_path="ui/icons/error-16-svgrepo-com.svg", + callback=self.cameraSettings + ) + + def set_image(self, pixmap: QPixmap): + self.viewer.set_image(pixmap) + + def resizeEvent(self, event): + super().resizeEvent(event) + # Aktualizacja pozycji przycisku przy zmianie rozmiaru + if self.live: + left_corner = 10 + self.camera_btn.move(left_corner, 10) + left_corner += self.camera_btn.width() + 10 + self.settings_btn.move(left_corner, 10) + + right_corner = self.cw_btn.width() + 10 + self.cw_btn.move(self.width() - right_corner, 10) + right_corner += self.ccw_btn.width() + 10 + self.ccw_btn.move(self.width() - right_corner, 10) + right_corner += self.flip_btn.width() + 10 + self.flip_btn.move(self.width() - right_corner, 10) + right_corner += self.orient_btn.width() + 10 + self.orient_btn.move(self.width() - right_corner, 10) + + def toggle_orientation(self, orientation): + if orientation == Qt.Orientation.Vertical: + self.flip_btn.setIcon(QIcon("ui/icons/flip-vertical-svgrepo-com.svg")) + self.orient_btn.setIcon(QIcon("ui/icons/horizontal-stacks-svgrepo-com.svg")) + else: + self.flip_btn.setIcon(QIcon("ui/icons/flip-horizontal-svgrepo-com.svg")) + self.orient_btn.setIcon(QIcon("ui/icons/vertical-stacks-svgrepo-com.svg")) + + def enterEvent(self, event: QEnterEvent) -> None: + if self.live: + self.camera_btn.show() + self.settings_btn.show() + + self.orient_btn.show() + self.flip_btn.show() + self.ccw_btn.show() + self.cw_btn.show() + return super().enterEvent(event) + + def leaveEvent(self, event: QEvent) -> None: + if self.live: + self.camera_btn.hide() + self.settings_btn.hide() + + self.orient_btn.hide() + self.flip_btn.hide() + self.ccw_btn.hide() + self.cw_btn.hide() + return super().leaveEvent(event) + class SplitView(QSplitter): - def __init__(self, parent=None): - super().__init__(parent) - print("Inicjalizacja SplitView2") - self.setOrientation(Qt.Orientation.Vertical) + def __init__(self, parent=None): + super().__init__(parent) + print("Inicjalizacja SplitView2") + self.setOrientation(Qt.Orientation.Vertical) - self.widget_start = CameraPlaceholder() - # self.widget_live = ZoomableImageView() - self.widget_live = ViewWithOverlay() - # self.widget_live = PlaceholderWidget("Camera View", "#750466") - # self.widget_ref = ZoomableImageView() - self.widget_ref = ViewWithOverlay() - # self.widget_ref = PlaceholderWidget("Image View", "#007981") + self.widget_start = CameraPlaceholder() + # self.widget_live = ZoomableImageView() + self.widget_live = ViewWithOverlay() + # self.widget_live = PlaceholderWidget("Camera View", "#750466") + # self.widget_ref = ZoomableImageView() + self.widget_ref = ViewWithOverlay() + # self.widget_ref = PlaceholderWidget("Image View", "#007981") - self.stack = QStackedWidget() - self.stack.addWidget(self.widget_start) - self.stack.addWidget(self.widget_live) - self.stack.setCurrentWidget(self.widget_start) + self.stack = QStackedWidget() + self.stack.addWidget(self.widget_start) + self.stack.addWidget(self.widget_live) + self.stack.setCurrentWidget(self.widget_start) - self.addWidget(self.stack) - self.addWidget(self.widget_ref) + self.addWidget(self.stack) + self.addWidget(self.widget_ref) - self.setSizes([self.height(), 0]) + self.setSizes([self.height(), 0]) - pixmap = QPixmap("media/empty_guitar_h.jpg") - # pixmap.fill(Qt.GlobalColor.lightGray) - self.widget_live.set_image(pixmap) + pixmap = QPixmap("media/empty_guitar_h.jpg") + # pixmap.fill(Qt.GlobalColor.lightGray) + self.widget_live.set_image(pixmap) - 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_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) - def toggle_orientation(self): - if self.orientation() == Qt.Orientation.Vertical: - self.setOrientation(Qt.Orientation.Horizontal) - self.setSizes([self.width()//2, self.width()//2]) - self.widget_live.toggle_orientation(Qt.Orientation.Horizontal) - self.widget_ref.toggle_orientation(Qt.Orientation.Horizontal) - else: - self.setOrientation(Qt.Orientation.Vertical) - self.setSizes([self.height()//2, self.height()//2]) - self.widget_live.toggle_orientation(Qt.Orientation.Vertical) - self.widget_ref.toggle_orientation(Qt.Orientation.Vertical) + def toggle_orientation(self): + if self.orientation() == Qt.Orientation.Vertical: + self.setOrientation(Qt.Orientation.Horizontal) + self.setSizes([self.width()//2, self.width()//2]) + self.widget_live.toggle_orientation(Qt.Orientation.Horizontal) + self.widget_ref.toggle_orientation(Qt.Orientation.Horizontal) + else: + self.setOrientation(Qt.Orientation.Vertical) + self.setSizes([self.height()//2, self.height()//2]) + self.widget_live.toggle_orientation(Qt.Orientation.Vertical) + self.widget_ref.toggle_orientation(Qt.Orientation.Vertical) - def swap_views(self): - """Zamiana widoków miejscami""" - index_live = self.indexOf(self.stack) - index_ref = self.indexOf(self.widget_ref) - sizes = self.sizes() - self.insertWidget(index_live, self.widget_ref) - self.insertWidget(index_ref, self.stack) - self.setSizes(sizes) + def swap_views(self): + """Zamiana widoków miejscami""" + index_live = self.indexOf(self.stack) + index_ref = self.indexOf(self.widget_ref) + sizes = self.sizes() + self.insertWidget(index_live, self.widget_ref) + self.insertWidget(index_ref, self.stack) + self.setSizes(sizes) - def set_live_image(self, pixmap: QPixmap): - """Ustawienie obrazu na żywo""" - self.widget_live.set_image(pixmap) - if self.stack.currentWidget() != self.widget_live: - self.stack.setCurrentWidget(self.widget_live) + def set_live_image(self, pixmap: QPixmap): + """Ustawienie obrazu na żywo""" + self.widget_live.set_image(pixmap) + if self.stack.currentWidget() != self.widget_live: + self.stack.setCurrentWidget(self.widget_live) - def set_reference_image(self, path_image: str): - """Ustawienie obrazu referencyjnego""" - pixmap = QPixmap(path_image) - self.widget_ref.set_image(pixmap) + def set_reference_image(self, path_image: str): + """Ustawienie obrazu referencyjnego""" + pixmap = QPixmap(path_image) + self.widget_ref.set_image(pixmap) - def toglle_live_view(self): - """Przełączanie widoku na żywo""" - if self.stack.currentWidget() == self.widget_start: - self.stack.setCurrentWidget(self.widget_live) - else: - self.stack.setCurrentWidget(self.widget_start) + def toglle_live_view(self): + """Przełączanie widoku na żywo""" + if self.stack.currentWidget() == self.widget_start: + self.stack.setCurrentWidget(self.widget_live) + else: + self.stack.setCurrentWidget(self.widget_start)