Created
June 3, 2025 09:17
-
-
Save joelgraff/603c7b0a21e566b2b615215f8fba79cf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# source_screen_ui.py: UI setup for SourceScreen | |
# | |
# Overview: | |
# Defines the setup_ui function for the Local Files screen. | |
# Sets up file list, USB/Internal toggles, TV output toggles, Play/Stop/Schedule buttons, Back button, and playback state label. | |
# | |
# Recent Changes (as of June 2025): | |
# - Fixed 'setAlignment' error on Back button using QHBoxLayout. | |
# - Extracted hardcoded values to config.py. | |
# - Updated filepaths to use /home/admin/kiosk/ project root (except VIDEO_DIR). | |
# - Fixed QFont error by using QFont.Bold in TITLE_FONT. | |
# - Added file listing for videos directory. | |
# - Added Back button connection to show_controls. | |
# - Improved file listing with directory checks and case-insensitive extensions. | |
# - Disabled Play/Stop buttons until file selected. | |
# - Moved ScheduleDialog import inside open_schedule_dialog to avoid circular imports. | |
# - Moved event handlers to source_screen.py to fix AttributeError. | |
# - Added placeholder QMessageBox and enhanced logging for Schedule dialog. | |
# - Moved placeholder to except blocks and added window flags logging. | |
# - Added dialog.show(), raise_(), activateWindow(), and centered geometry. | |
# - Removed test dialog, DebugScheduleDialog, and excessive logging. | |
# - Removed "TV" label, changed "Local Files" to "Select File", moved Back button to bottom-left, | |
# eliminated Sync notification, moved Play/Stop to top-right, moved Schedule below TV outputs. | |
# - Moved Schedule to bottom-right, positioned Playback between Schedule/Back, matched Back/Schedule heights, | |
# reduced Play/Stop height, widened Play/Stop to match TV buttons, added USB/Internal toggles. | |
# - Moved update_file_list, toggle_source, update_source_button_style to source_screen.py to fix AttributeError. | |
# - Styled USB/Internal buttons to match TV buttons, increased Back button font, reduced file list height, | |
# aligned file list top with TV buttons. | |
# - Changed Schedule button background to gray, moved file listbox to top of VBoxLayout, | |
# moved Schedule to bottom-left and Back to bottom-right, set Back width to TV buttons. | |
# - Fixed TV output buttons disappearing due to layout typo, added gray text for disabled USB button. | |
# - Removed update_file_list call to fix AttributeError, updated ICON_DIR to /home/admin/kiosk/gui/icons. | |
# - Scaled Play/Stop icons to 24x24px, then doubled to 48x48px. | |
# - Aligned file listbox top with TV buttons, repositioned USB/Internal buttons equidistant between file listbox and Schedule. | |
# - Corrected file listbox top alignment to match Fellowship 1/2 buttons, adjusted USB/Internal buttons downward with OUTPUT_LAYOUT_SPACING. | |
# - Moved Schedule button next to Back button, moved Playback State label to bottom-left. | |
# - Prevented selecting error messages in file listbox. | |
# - Fixed NameError by using back_button.setIcon instead of button.setIcon in setup_file_select_ui and setup_output_select_ui. | |
# - Moved Home button to center and added Next button with right arrow in setup_file_select_ui. | |
# - Assigned title QLabel to self.title_label for dynamic updates. | |
# - Removed file_list and next_button signal connections (moved to source_screen.py). | |
# - Fixed BUTTON_PAD import error and undefined color in setup_usb_source_ui. | |
# - Added logging, UI refresh, and visibility checks for USBSourceScreen controls. | |
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QListWidget, QLabel, QPushButton, QStyle | |
from PyQt5.QtCore import Qt, QSize | |
from PyQt5.QtGui import QFont, QIcon | |
import logging | |
import os | |
from config import ( | |
ICON_DIR, ICON_FILES, TV_OUTPUTS, SOURCE_SCREEN_BACKGROUND, TITLE_FONT, WIDGET_FONT, | |
TEXT_COLOR, FILE_LIST_BORDER_COLOR, PLAY_BUTTON_COLOR, STOP_BUTTON_COLOR, | |
FILE_LIST_HEIGHT, FILE_LIST_ITEM_HEIGHT, OUTPUT_BUTTON_SIZE, PLAY_STOP_BUTTON_SIZE, | |
MAIN_LAYOUT_SPACING, TOP_LAYOUT_SPACING, OUTPUTS_CONTAINER_SPACING, OUTPUT_LAYOUT_SPACING, | |
BUTTONS_LAYOUT_SPACING, BUTTON_PADDING, BORDER_RADIUS, LOCAL_FILES_INPUT_NUM, | |
OUTPUT_BUTTON_COLORS | |
) | |
def setup_usb_source_ui(self): | |
logging.debug("USBSourceScreen: Setting up UI") | |
main_layout = QVBoxLayout(self.widget) | |
main_layout.setContentsMargins(MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING) | |
main_layout.setSpacing(MAIN_LAYOUT_SPACING) | |
logging.debug("USBSourceScreen: Created main_layout") | |
title = QLabel("Choose Source") | |
title.setFont(QFont(*TITLE_FONT)) | |
title.setStyleSheet(f"color: {TEXT_COLOR}; background: transparent;") | |
title.setVisible(True) | |
main_layout.addWidget(title, alignment=Qt.AlignCenter) | |
logging.debug("USBSourceScreen: Added title QLabel") | |
buttons_layout = QHBoxLayout() | |
buttons_layout.setSpacing(BUTTONS_LAYOUT_SPACING) | |
for source in ["USB", "Internal"]: | |
button = QPushButton(source) # Add text for visibility | |
button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1] * 2) | |
button.setFont(QFont(*WIDGET_FONT)) | |
if source == "USB": | |
icon_path = os.path.join(ICON_DIR, "usb.png") | |
logging.debug(f"USBSourceScreen: Attempting to load USB icon: {icon_path}") | |
if os.path.exists(icon_path): | |
button.setIcon(QIcon(icon_path)) | |
logging.debug(f"USBSourceScreen: Loaded custom USB icon: {icon_path}") | |
else: | |
button.setIcon(self.widget.style().standardIcon(QStyle.SP_DriveHDIcon)) | |
logging.warning(f"USBSourceScreen: Custom USB icon not found: {icon_path}") | |
button.setIconSize(QSize(96, 96)) | |
else: | |
button.setIcon(self.widget.style().standardIcon(QStyle.SP_DriveHDIcon)) | |
button.setIconSize(QSize(64, 64)) | |
stylesheet = f""" | |
QPushButton {{ | |
background: {OUTPUT_BUTTON_COLORS['unselected']}; | |
color: white; | |
border: 1px solid white; | |
border-radius: 5px; | |
padding: {BUTTON_PADDING['padding']}px; | |
}} | |
""" | |
button.setStyleSheet(stylesheet) | |
button.setVisible(True) | |
logging.debug(f"Button {source}: Applied stylesheet: {stylesheet}") | |
button.clicked.connect(lambda checked, s=source: self.select_source(s)) | |
buttons_layout.addWidget(button) | |
logging.debug(f"USBSourceScreen: Added {source} button") | |
main_layout.addLayout(buttons_layout, stretch=1) | |
logging.debug("USBSourceScreen: Added buttons_layout") | |
main_layout.addStretch() | |
home_button = QPushButton("") | |
home_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
home_button.setIcon(self.widget.style().standardIcon(QStyle.SP_DirHomeIcon)) | |
home_button.setIconSize(QSize(48, 48)) | |
stylesheet = f""" | |
QPushButton {{ | |
background: {OUTPUT_BUTTON_COLORS['unselected']}; | |
color: white; | |
border: 1px solid white; | |
border-radius: 5px; | |
padding: {BUTTON_PADDING['back']}px; | |
}} | |
""" | |
home_button.setStyleSheet(stylesheet) | |
home_button.setVisible(True) | |
logging.debug(f"USBSourceScreen: Applied stylesheet to Home button: {stylesheet}") | |
home_button.clicked.connect(self.parent.go_home) | |
main_layout.addWidget(home_button, alignment=Qt.AlignLeft) | |
logging.debug("USBSourceScreen: Added Home button") | |
self.widget.setStyleSheet(f"QWidget {{ background: {SOURCE_SCREEN_BACKGROUND}; }}") | |
self.widget.setMinimumSize(787, 492) | |
self.widget.show() | |
QApplication.processEvents() | |
logging.debug("USBSourceScreen: UI setup completed") | |
def setup_file_select_ui(self): | |
logging.debug("FileSelectScreen: Setting up UI") | |
main_layout = QVBoxLayout(self.widget) | |
main_layout.setContentsMargins(MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING) | |
main_layout.setSpacing(MAIN_LAYOUT_SPACING) | |
self.title_label = QLabel("File") | |
self.title_label.setFont(QFont(*TITLE_FONT)) | |
self.title_label.setStyleSheet(f"color: {TEXT_COLOR}; background: transparent;") | |
main_layout.addWidget(self.title_label, alignment=Qt.AlignCenter) | |
logging.debug("FileSelectScreen: Assigned title_label") | |
self.file_list = QListWidget() | |
self.file_list.setFont(QFont(*WIDGET_FONT)) | |
self.file_list.setFixedHeight(FILE_LIST_HEIGHT - 50) | |
self.file_list.setStyleSheet(f""" | |
QListWidget {{ | |
color: {TEXT_COLOR}; | |
background: {SOURCE_SCREEN_BACKGROUND}; | |
border: 2px solid {FILE_LIST_BORDER_COLOR}; | |
border-radius: {BORDER_RADIUS}px; | |
}} | |
QListWidget::item {{ height: {FILE_LIST_ITEM_HEIGHT}px; padding: 2px; }} | |
""") | |
self.file_list.setEnabled(True) | |
self.file_list.setFocusPolicy(Qt.StrongFocus) | |
logging.debug("FileSelectScreen: Created file_list") | |
main_layout.addWidget(self.file_list, stretch=1) | |
nav_layout = QHBoxLayout() | |
back_button = QPushButton("") | |
back_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
icon_path = os.path.join(ICON_DIR, "back.png") | |
logging.debug(f"FileSelectScreen: Attempting to load Back icon: {icon_path}") | |
if os.path.exists(icon_path): | |
back_button.setIcon(QIcon(icon_path)) | |
logging.debug(f"FileSelectScreen: Loaded back icon: {icon_path}") | |
else: | |
back_button.setIcon(self.widget.style().standardIcon(QStyle.SP_ArrowBack)) | |
logging.warning(f"FileSelectScreen: Custom Back icon not found: {icon_path}") | |
back_button.setIconSize(QSize(48, 48)) | |
stylesheet = f""" | |
QPushButton {{ | |
background: {OUTPUT_BUTTON_COLORS['unselected']}; | |
color: white; | |
border: 1px solid white; | |
border-radius: 5px; | |
padding: {BUTTON_PADDING['back']}px; | |
}} | |
""" | |
back_button.setStyleSheet(stylesheet) | |
logging.debug(f"FileSelectScreen: Applied stylesheet to Back button: {stylesheet}") | |
back_button.clicked.connect(self.parent.go_back) | |
nav_layout.addWidget(back_button) | |
nav_layout.addStretch() | |
home_button = QPushButton("") | |
home_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
home_button.setIcon(self.widget.style().standardIcon(QStyle.SP_DirHomeIcon)) | |
home_button.setIconSize(QSize(48, 48)) | |
home_button.setStyleSheet(stylesheet) | |
logging.debug(f"FileSelectScreen: Applied stylesheet to Home button: {stylesheet}") | |
home_button.clicked.connect(self.parent.go_home) | |
nav_layout.addWidget(home_button) | |
nav_layout.addStretch() | |
self.next_button = QPushButton("") | |
self.next_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
self.next_button.setEnabled(True) | |
icon_path = os.path.join(ICON_DIR, "next.png") | |
logging.debug(f"FileSelectScreen: Attempting to load Next icon: {icon_path}") | |
if os.path.exists(icon_path): | |
self.next_button.setIcon(QIcon(icon_path)) | |
logging.debug(f"FileSelectScreen: Loaded custom Next icon: {icon_path}") | |
else: | |
self.next_button.setIcon(self.widget.style().standardIcon(QStyle.SP_ArrowRight)) | |
logging.warning(f"FileSelectScreen: Custom Next icon not found: {icon_path}") | |
self.next_button.setIconSize(QSize(48, 48)) | |
self.next_button.setStyleSheet(stylesheet) | |
logging.debug(f"FileSelectScreen: Applied stylesheet to Next button: {stylesheet}") | |
nav_layout.addWidget(self.next_button) | |
main_layout.addLayout(nav_layout) | |
self.widget.setStyleSheet(f"QWidget {{ background: {SOURCE_SCREEN_BACKGROUND}; }}") | |
logging.debug("FileSelectScreen: UI setup completed") | |
def setup_output_select_ui(self): | |
logging.debug("OutputSelectScreen: Setting up UI") | |
main_layout = QVBoxLayout(self.widget) | |
main_layout.setContentsMargins(MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING) | |
main_layout.setSpacing(MAIN_LAYOUT_SPACING) | |
title = QLabel("Output") | |
title.setFont(QFont(*TITLE_FONT)) | |
title.setStyleSheet(f"color: {TEXT_COLOR}; background: transparent;") | |
main_layout.addWidget(title, alignment=Qt.AlignCenter) | |
outputs_container = QHBoxLayout() | |
outputs_container.setSpacing(OUTPUTS_CONTAINER_SPACING) | |
outputs_left_layout = QVBoxLayout() | |
outputs_right_layout = QVBoxLayout() | |
outputs_left_layout.setSpacing(OUTPUT_LAYOUT_SPACING) | |
outputs_right_layout.setSpacing(OUTPUT_LAYOUT_SPACING) | |
for name in TV_OUTPUTS: | |
button = QPushButton(name) | |
button.setFont(QFont(*WIDGET_FONT)) | |
button.setFixedSize(*OUTPUT_BUTTON_SIZE) | |
button.setCheckable(True) | |
output_idx = TV_OUTPUTS[name] | |
is_current = LOCAL_FILES_INPUT_NUM in self.parent.input_output_map and output_idx in self.parent.input_output_map.get(LOCAL_FILES_INPUT_NUM, []) | |
is_other = any(other_input != LOCAL_FILES_INPUT_NUM and output_idx in self.parent.input_output_map.get(other_input, []) and self.parent.active_inputs.get(other_input, False) for other_input in self.parent.input_output_map) | |
button.setEnabled(not is_other) | |
self.output_buttons[name] = button | |
self.update_output_button_style(name, is_current) | |
button.clicked.connect(lambda checked, n=name: self.toggle_output(n, checked)) | |
if name in ["Fellowship 1", "Nursery"]: | |
outputs_left_layout.addWidget(button) | |
else: | |
outputs_right_layout.addWidget(button) | |
outputs_container.addLayout(outputs_left_layout) | |
outputs_container.addLayout(outputs_right_layout) | |
main_layout.addLayout(outputs_container, stretch=1) | |
nav_layout = QHBoxLayout() | |
back_button = QPushButton("") | |
back_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
icon_path = os.path.join(ICON_DIR, "back.png") | |
logging.debug(f"OutputSelectScreen: Attempting to load Back icon: {icon_path}") | |
if os.path.exists(icon_path): | |
back_button.setIcon(QIcon(icon_path)) | |
logging.debug(f"OutputSelectScreen: Loaded custom Back icon: {icon_path}") | |
else: | |
back_button.setIcon(self.widget.style().standardIcon(QStyle.SP_ArrowBack)) | |
logging.warning(f"OutputSelectScreen: Custom Back icon not found: {icon_path}") | |
back_button.setIconSize(QSize(48, 48)) | |
stylesheet = f""" | |
QPushButton {{ | |
background: {OUTPUT_BUTTON_COLORS['unselected']}; | |
color: white; | |
border: 1px solid white; | |
border-radius: 5px; | |
padding: {BUTTON_PADDING['back']}px; | |
}} | |
""" | |
back_button.setStyleSheet(stylesheet) | |
logging.debug(f"OutputSelectScreen: Applied stylesheet to Back button: {stylesheet}") | |
back_button.clicked.connect(self.parent.go_back) | |
nav_layout.addWidget(back_button) | |
nav_layout.addStretch() | |
proceed_button = QPushButton("Next") | |
proceed_button.setFont(QFont(*WIDGET_FONT)) | |
proceed_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
proceed_button.setStyleSheet(stylesheet.replace("unselected", "selected")) | |
logging.debug(f"OutputSelectScreen: Applied stylesheet to Proceed button: {stylesheet}") | |
proceed_button.clicked.connect(self.proceed) | |
nav_layout.addWidget(proceed_button) | |
home_button = QPushButton("") | |
home_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
home_button.setIcon(self.widget.style().standardIcon(QStyle.SP_DirHomeIcon)) | |
home_button.setIconSize(QSize(48, 48)) | |
home_button.setStyleSheet(stylesheet) | |
logging.debug(f"OutputSelectScreen: Applied stylesheet to Home button: {stylesheet}") | |
home_button.clicked.connect(self.parent.go_home) | |
nav_layout.addWidget(home_button) | |
main_layout.addLayout(nav_layout) | |
self.widget.setStyleSheet(f"QWidget {{ background: {SOURCE_SCREEN_BACKGROUND}; }}") | |
logging.debug("OutputSelectScreen: UI setup completed") | |
def setup_playback_control_ui(self): | |
logging.debug("PlaybackControlScreen: Setting up UI") | |
main_layout = QVBoxLayout(self.widget) | |
main_layout.setContentsMargins(MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING, MAIN_LAYOUT_SPACING) | |
main_layout.setSpacing(MAIN_LAYOUT_SPACING) | |
title = QLabel("Playback Control") | |
title.setFont(QFont(*TITLE_FONT)) | |
title.setStyleSheet(f"color: {TEXT_COLOR}; background: transparent;") | |
main_layout.addWidget(title, alignment=Qt.AlignCenter) | |
buttons_layout = QHBoxLayout() | |
buttons_layout.setSpacing(BUTTONS_LAYOUT_SPACING) | |
for action, icon, color, qt_icon in [ | |
("Play", ICON_FILES["play"], PLAY_BUTTON_COLOR, QStyle.SP_MediaPlay), | |
("Stop", ICON_FILES["stop"], STOP_BUTTON_COLOR, QStyle.SP_MediaStop) | |
]: | |
button = QPushButton() | |
button.setFixedSize(*PLAY_STOP_BUTTON_SIZE) | |
button.setFont(QFont(*WIDGET_FONT)) | |
icon_path = os.path.join(ICON_DIR, icon) | |
logging.debug(f"PlaybackControlScreen: Attempting to load icon for {action}: {icon_path}") | |
if os.path.exists(icon_path): | |
button.setIcon(QIcon(icon_path)) | |
logging.debug(f"PlaybackControlScreen: Loaded icon: {icon_path}") | |
else: | |
button.setIcon(self.widget.style().standardIcon(qt_icon)) | |
logging.warning(f"PlaybackControlScreen: Custom icon not found: {icon_path}") | |
button.setIconSize(QSize(48, 48)) | |
stylesheet = f""" | |
QPushButton {{ | |
background: {color}; | |
color: {TEXT_COLOR}; | |
border: 1px solid white; | |
border-radius: 5px; | |
padding: {BUTTON_BUTTON['padding']}px; | |
}} | |
""" | |
button.setStyleSheet(stylesheet) | |
logging.debug(f"PlaybackControlScreen: Applied stylesheet to {action} button: {stylesheet}") | |
if action == "Play": | |
self.play_button = button | |
button.clicked.connect(self.on_play_clicked) | |
elif action == "Stop": | |
self.stop_button = button | |
button.clicked.connect(self.on_stop_clicked) | |
buttons_layout.addWidget(button) | |
main_layout.addLayout(buttons_layout, stretch=1) | |
main_layout.addStretch() | |
nav_layout = QHBoxLayout() | |
back_button = QPushButton("") | |
back_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
icon_path = os.path.join(ICON_DIR, "back.png") | |
logging.debug(f"PlaybackControlScreen: Attempting to load Back icon: {icon_path}") | |
if os.path.exists(icon_path): | |
back_button.setIcon(QIcon(icon_path)) | |
logging.debug(f"PlaybackControlScreen: Loaded custom Back icon: {icon_path}") | |
else: | |
back_button.setIcon(self.widget.style().standardIcon(QStyle.SP_ArrowBack)) | |
logging.warning(f"PlaybackControlScreen: Custom Back icon not found: {icon_path}") | |
back_button.setIconSize(QSize(48, 48)) | |
stylesheet = f""" | |
QPushButton {{ | |
background: {OUTPUT_BUTTON_COLORS['unselected']}; | |
color: white; | |
border: 1px solid white; | |
border-radius: 5px; | |
padding: {BUTTON_PADDING['back']}px; | |
}} | |
""" | |
back_button.setStyleSheet(stylesheet) | |
logging.debug(f"PlaybackControlScreen: Applied stylesheet to Back button: {stylesheet}") | |
back_button.clicked.connect(self.parent.go_back) | |
nav_layout.addWidget(back_button) | |
nav_layout.addStretch() | |
home_button = QPushButton("") | |
home_button.setFixedSize(OUTPUT_BUTTON_SIZE[0], OUTPUT_BUTTON_SIZE[1]) | |
home_button.setIcon(self.widget.style().standardIcon(QStyle.SP_DirHomeIcon)) | |
home_button.setIconSize(QSize(48, 48)) | |
home_button.setStyleSheet(stylesheet) | |
logging.debug(f"PlaybackControlScreen: Applied stylesheet to Home button: {stylesheet}") | |
home_button.clicked.connect(self.parent.go_home) | |
nav_layout.addWidget(home_button) | |
main_layout.addLayout(nav_layout) | |
self.widget.setStyleSheet(f"QWidget {{ background: {SOURCE_SCREEN_BACKGROUND}; }}") | |
logging.debug("PlaybackControlScreen: UI setup completed") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment