KNEO-Academy/src/views/components/media_panel.py
abin 7e323cf3e1 Fix: resolve 5 bugs found during project onboarding health check
- 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>
2026-04-07 14:33:37 +08:00

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())