319 lines
9.5 KiB
Python
319 lines
9.5 KiB
Python
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.QtCore import Qt, QSize, Signal, QEvent
|
|
import sys
|
|
from ui.widgets.placeholder_widget import PlaceholderWidget
|
|
|
|
|
|
class ZoomableImageView(QGraphicsView):
|
|
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
|
|
|
|
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)
|
|
|
|
# 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 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
|
|
|
|
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)
|
|
|
|
self.setAutoFillBackground(True)
|
|
self.setStyleSheet("background-color: #141414;")
|
|
|
|
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;
|
|
}
|
|
|
|
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)
|
|
|
|
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)
|
|
|
|
def set_info_text(self, text: str):
|
|
self.info_label.setText(text)
|
|
|
|
|
|
class ViewWithOverlay(QWidget):
|
|
cameraConnection = Signal()
|
|
cameraSettings = Signal()
|
|
toggleOrientation = Signal()
|
|
swapViews = Signal()
|
|
rotateCW = Signal()
|
|
rotateCCW = Signal()
|
|
|
|
def __init__(self, live: bool = False):
|
|
super().__init__()
|
|
self.live = live
|
|
|
|
layout = QVBoxLayout(self)
|
|
layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
self.viewer = ZoomableImageView()
|
|
layout.addWidget(self.viewer)
|
|
|
|
self._create_top_right_buttons()
|
|
if self.live:
|
|
self._create_top_left_buttons()
|
|
|
|
self.resize(self.size())
|
|
|
|
# self.cw_btn.raise_()
|
|
# self.ccw_btn.raise_()
|
|
# self.flip_btn.raise_()
|
|
# self.orient_btn.raise_()
|
|
|
|
self.toggle_orientation(Qt.Orientation.Vertical)
|
|
|
|
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)
|
|
|
|
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.ccw_btn = self._create_tool_button(
|
|
icon_path="ui/icons/rotate-ccw-svgrepo-com.svg",
|
|
callback=self.rotateCCW,
|
|
)
|
|
|
|
self.flip_btn = self._create_tool_button(
|
|
icon_path=None,
|
|
callback=self.swapViews,
|
|
)
|
|
|
|
self.orient_btn = self._create_tool_button(
|
|
icon_path=None,
|
|
callback=self.toggleOrientation,
|
|
)
|
|
|
|
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)
|
|
|
|
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.addWidget(self.stack)
|
|
self.addWidget(self.widget_ref)
|
|
|
|
self.setSizes([self.height(), 0])
|
|
|
|
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)
|
|
|
|
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 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 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)
|