206 lines
6.6 KiB
Python
206 lines
6.6 KiB
Python
from enum import Enum
|
|
from typing import Any
|
|
import logging
|
|
|
|
from PySide6.QtWidgets import QGridLayout, QHBoxLayout, QMainWindow, QStyle, QToolButton, QWidget, QVBoxLayout, QPushButton, QLabel
|
|
from PySide6.QtGui import QIcon, QPixmap
|
|
from PySide6.QtCore import Qt, QSize
|
|
|
|
from .video_stream.controller import VideoStreamController, FrameMetrics
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class VideoMode(Enum):
|
|
STREAMING = "streaming"
|
|
RECORDING = "recording"
|
|
PLAYING = "playing"
|
|
STOPPED = "stopped"
|
|
|
|
icons = {
|
|
"load_file":{
|
|
"path": "assets/folder-svgrepo-com.svg",
|
|
"tooltip": "Open File",
|
|
"size": QSize(48, 48)
|
|
},
|
|
"close_file": {
|
|
"path": "assets/close-square-svgrepo-com.svg",
|
|
"tooltip": "Close File",
|
|
"size": QSize(32, 32)
|
|
},
|
|
"record_on": {
|
|
"path": "assets/record_btn_on.svg",
|
|
"tooltip": "Start Recording",
|
|
"size": QSize(48, 48)
|
|
},
|
|
"record_off": {
|
|
"path": "assets/record_btn_off.svg",
|
|
"tooltip": "Stop Recording",
|
|
"size": QSize(48, 48)
|
|
},
|
|
|
|
"play": {
|
|
"path": "assets/play-svgrepo-com.svg",
|
|
"tooltip": "Play Video",
|
|
"size": QSize(48, 48)
|
|
},
|
|
"pause": {
|
|
"path": "assets/pause-svgrepo-com.svg",
|
|
"tooltip": "Pause Video",
|
|
"size": QSize(32, 32)
|
|
}
|
|
}
|
|
|
|
def set_icon(button: QToolButton, icon: str):
|
|
button.setIcon(QIcon(icons[icon]["path"]))
|
|
button.setToolTip(icons[icon]["tooltip"])
|
|
button.setIconSize(icons[icon]["size"])
|
|
|
|
|
|
def create_tool_button(icon: str) -> QToolButton:
|
|
button = QToolButton()
|
|
set_icon(button, icon)
|
|
button.setFixedSize(48, 48)
|
|
button.setStyleSheet("background-color: transparent; border: none;")
|
|
return button
|
|
|
|
class MainWindow(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("Duck Stain OCR")
|
|
self.resize(1280, 720)
|
|
|
|
self.video_mode = VideoMode.STREAMING
|
|
logger.debug(f"Initial video mode: {self.video_mode}")
|
|
|
|
|
|
self.video_controller = VideoStreamController()
|
|
self.video_controller.change_source(0) # Start with default camera
|
|
self.video_controller.image_ready.connect(self.update_frame)
|
|
|
|
self.setup_ui()
|
|
|
|
self.video_controller.start()
|
|
|
|
def setup_ui(self):
|
|
self.central_widget = QWidget()
|
|
self.setCentralWidget(self.central_widget)
|
|
self.central_widget.setStyleSheet("background-color: #001e1e;")
|
|
|
|
self.video_label = QLabel(self.central_widget)
|
|
|
|
self.toolbar_widget = QWidget(self.central_widget)
|
|
self.toolbar_widget.setMinimumWidth(400)
|
|
self.toolbar_widget.setObjectName("bottomToolbar")
|
|
self.toolbar_widget.setStyleSheet(
|
|
"""
|
|
QWidget#bottomToolbar {
|
|
background: rgba(0, 0, 0, 0.1);
|
|
border-radius: 18px;
|
|
}
|
|
"""
|
|
)
|
|
|
|
left_layout = QHBoxLayout()
|
|
right_layout = QHBoxLayout()
|
|
|
|
self.toolbar_layout = QGridLayout(self.toolbar_widget)
|
|
self.toolbar_layout.setContentsMargins(18, 16, 18, 16)
|
|
self.toolbar_layout.setColumnStretch(0, 1)
|
|
self.toolbar_layout.setColumnStretch(1, 0)
|
|
self.toolbar_layout.setColumnStretch(2, 1)
|
|
|
|
self.toolbar_layout.addLayout(left_layout, 0, 0)
|
|
self.toolbar_layout.addLayout(right_layout, 0, 2)
|
|
|
|
# Add buttons to the left layout
|
|
self.open_file_button = create_tool_button("load_file")
|
|
self.open_file_button.clicked.connect(self.load_video)
|
|
left_layout.addWidget(self.open_file_button)
|
|
self.close_file_button = create_tool_button("close_file")
|
|
self.close_file_button.clicked.connect(self.close_video)
|
|
self.close_file_button.setEnabled(False)
|
|
left_layout.addWidget(self.close_file_button)
|
|
|
|
left_layout.addStretch()
|
|
|
|
# Add the record button to the center of the toolbar
|
|
self.action_button = create_tool_button("record_off")
|
|
self.action_button.clicked.connect(self.toggle_action)
|
|
self.toolbar_layout.addWidget(self.action_button, 0, 1, alignment=Qt.AlignmentFlag.AlignCenter)
|
|
|
|
# Add buttons to the right layout
|
|
right_layout.addStretch()
|
|
|
|
|
|
def resizeEvent(self, event: Any) -> None:
|
|
super().resizeEvent(event)
|
|
|
|
self.toolbar_widget.adjustSize()
|
|
toolbar_size = self.toolbar_widget.sizeHint()
|
|
self.toolbar_widget.setGeometry(
|
|
(self.central_widget.width() - self.toolbar_widget.width()) // 2,
|
|
self.central_widget.height() - self.toolbar_widget.height() - 80,
|
|
self.toolbar_widget.width(),
|
|
self.toolbar_widget.height(),
|
|
)
|
|
self.toolbar_widget.raise_() # Ensure the toolbar is above other widgets
|
|
|
|
def toggle_action(self):
|
|
match self.video_mode:
|
|
case VideoMode.STREAMING:
|
|
self.start_recording()
|
|
case VideoMode.RECORDING:
|
|
self.stop_recording()
|
|
case VideoMode.PLAYING:
|
|
self.pause_video()
|
|
case VideoMode.STOPPED:
|
|
self.play_video()
|
|
case _:
|
|
pass
|
|
|
|
def start_recording(self):
|
|
logger.debug("Starting recording")
|
|
self.video_mode = VideoMode.RECORDING
|
|
set_icon(self.action_button, "record_on")
|
|
|
|
self.open_file_button.setEnabled(False)
|
|
self.close_file_button.setEnabled(False)
|
|
|
|
def stop_recording(self):
|
|
logger.debug("Stopping recording")
|
|
self.video_mode = VideoMode.STREAMING
|
|
set_icon(self.action_button, "record_off")
|
|
|
|
self.open_file_button.setEnabled(True)
|
|
self.close_file_button.setEnabled(False)
|
|
|
|
def load_video(self):
|
|
logger.debug("Loading video")
|
|
self.video_mode = VideoMode.STOPPED
|
|
set_icon(self.action_button, "play")
|
|
|
|
self.close_file_button.setEnabled(True)
|
|
|
|
def close_video(self):
|
|
logger.debug("Closing video")
|
|
self.video_mode = VideoMode.STREAMING
|
|
set_icon(self.action_button, "record_off")
|
|
|
|
self.close_file_button.setEnabled(False)
|
|
|
|
def play_video(self):
|
|
logger.debug("Playing video")
|
|
self.video_mode = VideoMode.PLAYING
|
|
set_icon(self.action_button, "pause")
|
|
|
|
def pause_video(self):
|
|
logger.debug("Pausing video")
|
|
self.video_mode = VideoMode.STOPPED
|
|
set_icon(self.action_button, "play")
|
|
|
|
def closeEvent(self, event: Any) -> None:
|
|
logger.debug("Closing main window, cleaning up resources.")
|
|
self.video_controller.cleanup()
|
|
super().closeEvent(event)
|
|
|
|
def update_frame(self, frame):
|
|
self.video_label.setPixmap(QPixmap.fromImage(frame)) |