forked from masonhuang/KNEO-Academy
- custom_inference_worker: reuse existing device_group from DeviceController to avoid double kp.connect_devices() conflict on same USB port - custom_inference_worker: add TYPE_CHECKING guard for kp type annotations to prevent potential NameError at import time - utilities_screen: replace missing back_arrow.png with text arrow (←) - utilities_screen: add set_device_controller() so AppController can inject MainWindow's shared DeviceController instance - main.py: wire UtilitiesScreen to share MainWindow's DeviceController - video_thread: emit camera_error_signal on failure and max-retry exhaustion - media_controller: connect camera_error_signal and display error on canvas - media_panel: fix pause button using wrong delete icon; use video_normal SVG Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
101 lines
4.2 KiB
Python
101 lines
4.2 KiB
Python
from PyQt5.QtWidgets import QFrame, QVBoxLayout, QHBoxLayout, QPushButton
|
|
from PyQt5.QtSvg import QSvgWidget
|
|
from PyQt5.QtCore import Qt
|
|
import os
|
|
|
|
from src.config import SECONDARY_COLOR, UXUI_ASSETS
|
|
|
|
def create_media_panel(parent, media_controller, file_service):
|
|
"""Create the media control panel with buttons for media operations"""
|
|
try:
|
|
# Create a vertical layout for the buttons
|
|
media_panel = QFrame(parent)
|
|
media_panel.setStyleSheet(f"background: {SECONDARY_COLOR}; border-radius: 20px;")
|
|
media_layout = QVBoxLayout(media_panel)
|
|
media_layout.setAlignment(Qt.AlignCenter)
|
|
|
|
# 確保使用正確的路徑分隔符
|
|
assets_path = UXUI_ASSETS.replace('\\', '/')
|
|
if not assets_path.endswith('/'):
|
|
assets_path += '/'
|
|
|
|
# Media button information
|
|
media_buttons_info = [
|
|
('screenshot', os.path.join(assets_path, "Assets_svg/bt_function_screencapture_normal.svg").replace('\\', '/'),
|
|
media_controller.take_screenshot),
|
|
('upload file', os.path.join(assets_path, "Assets_svg/bt_function_upload_normal.svg").replace('\\', '/'),
|
|
file_service.upload_file),
|
|
('pause/resume', os.path.join(assets_path, "Assets_svg/bt_function_video_normal.svg").replace('\\', '/'),
|
|
lambda: toggle_pause_button(parent, media_controller)),
|
|
('voice', os.path.join(assets_path, "Assets_svg/ic_recording_voice.svg").replace('\\', '/'),
|
|
lambda: media_controller.record_audio(None)),
|
|
('video', os.path.join(assets_path, "Assets_svg/ic_recording_camera.svg").replace('\\', '/'),
|
|
lambda: media_controller.record_video(None)),
|
|
]
|
|
|
|
for button_name, icon_path, callback in media_buttons_info:
|
|
button = QPushButton()
|
|
button.setFixedSize(50, 50)
|
|
button.setStyleSheet("""
|
|
QPushButton {
|
|
background: transparent;
|
|
color: white;
|
|
border: 1px transparent;
|
|
border-radius: 10px;
|
|
}
|
|
QPushButton:hover {
|
|
background-color: rgba(255, 255, 255, 50);
|
|
}
|
|
QPushButton:pressed {
|
|
background-color: rgba(255, 255, 255, 100);
|
|
}
|
|
""")
|
|
|
|
button_layout = QHBoxLayout(button)
|
|
button_layout.setContentsMargins(0, 0, 0, 0)
|
|
button_layout.setAlignment(Qt.AlignCenter)
|
|
|
|
icon = QSvgWidget(icon_path)
|
|
icon.setFixedSize(40, 40)
|
|
button_layout.addWidget(icon)
|
|
|
|
# 為暫停按鈕儲存參考
|
|
if button_name == 'pause/resume':
|
|
parent.pause_button = button
|
|
parent.pause_icon = icon
|
|
parent.pause_icon_path = icon_path
|
|
parent.play_icon_path = os.path.join(assets_path, "Assets_svg/bt_function_video_hover.svg").replace('\\', '/')
|
|
|
|
button.clicked.connect(callback)
|
|
media_layout.addWidget(button, alignment=Qt.AlignCenter)
|
|
|
|
media_panel.setLayout(media_layout)
|
|
media_panel.setFixedSize(90, 290) # 增加高度以容納新按鈕
|
|
|
|
return media_panel
|
|
except Exception as e:
|
|
print(f"Error in create_media_panel: {e}")
|
|
return QFrame(parent)
|
|
|
|
def toggle_pause_button(parent, media_controller):
|
|
"""切換暫停/恢復按鈕圖示並觸發相應功能"""
|
|
try:
|
|
is_paused = media_controller.toggle_inference_pause()
|
|
|
|
# 切換圖示
|
|
if is_paused:
|
|
# 檢查文件是否存在
|
|
if os.path.exists(parent.play_icon_path):
|
|
parent.pause_icon.load(parent.play_icon_path)
|
|
else:
|
|
print(f"警告: 播放圖標文件不存在: {parent.play_icon_path}")
|
|
else:
|
|
# 檢查文件是否存在
|
|
if os.path.exists(parent.pause_icon_path):
|
|
parent.pause_icon.load(parent.pause_icon_path)
|
|
else:
|
|
print(f"警告: 暫停圖標文件不存在: {parent.pause_icon_path}")
|
|
except Exception as e:
|
|
print(f"切換暫停按鈕時發生錯誤: {e}")
|
|
import traceback
|
|
print(traceback.format_exc()) |