"""Main window for the countdown timer application.""" from PyQt6.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QListWidget, QGroupBox, QLabel, QScrollArea, QFrame) from PyQt6.QtCore import QSettings, Qt, QTimer from PyQt6.QtGui import QFont from ui.settings_dialog import SettingsDialog from ui.timer_dialog import TimerDialog from ui.timer_widget import TimerWidget from ui.fullscreen_display import FullscreenDisplay from models.timer_model import Timer class MainWindow(QMainWindow): def __init__(self): super().__init__() self.settings = QSettings() self.timers = [] self.timer_widgets = [] self.fullscreen_display = None self.init_ui() self.load_timers() def init_ui(self): self.setWindowTitle("Countdown Timer Manager") self.setMinimumSize(1000, 600) # Central widget central_widget = QWidget() self.setCentralWidget(central_widget) main_layout = QHBoxLayout(central_widget) # Left panel - Timer management left_panel = QWidget() left_layout = QVBoxLayout(left_panel) left_panel.setMaximumWidth(350) # Timer list group timer_group = QGroupBox("Timer Library") timer_layout = QVBoxLayout() self.timer_list = QListWidget() timer_layout.addWidget(self.timer_list) # Timer management buttons timer_btn_layout = QVBoxLayout() self.add_timer_btn = QPushButton("Add Timer") self.edit_timer_btn = QPushButton("Edit Timer") self.delete_timer_btn = QPushButton("Delete Timer") self.start_timer_btn = QPushButton("Start Selected Timer") self.add_timer_btn.clicked.connect(self.add_timer) self.edit_timer_btn.clicked.connect(self.edit_timer) self.delete_timer_btn.clicked.connect(self.delete_timer) self.start_timer_btn.clicked.connect(self.start_timer) timer_btn_layout.addWidget(self.add_timer_btn) timer_btn_layout.addWidget(self.edit_timer_btn) timer_btn_layout.addWidget(self.delete_timer_btn) timer_btn_layout.addWidget(self.start_timer_btn) timer_layout.addLayout(timer_btn_layout) timer_group.setLayout(timer_layout) left_layout.addWidget(timer_group) # Global controls controls_group = QGroupBox("Global Controls") controls_layout = QVBoxLayout() self.stop_all_btn = QPushButton("Stop All Timers") self.pause_all_btn = QPushButton("Pause All Timers") self.resume_all_btn = QPushButton("Resume All Timers") self.stop_all_btn.clicked.connect(self.stop_all_timers) self.pause_all_btn.clicked.connect(self.pause_all_timers) self.resume_all_btn.clicked.connect(self.resume_all_timers) controls_layout.addWidget(self.pause_all_btn) controls_layout.addWidget(self.resume_all_btn) controls_layout.addWidget(self.stop_all_btn) controls_group.setLayout(controls_layout) left_layout.addWidget(controls_group) # Display mode group display_group = QGroupBox("Display Mode") display_layout = QVBoxLayout() self.fullscreen_btn = QPushButton("Show Fullscreen on Monitor") self.fullscreen_btn.clicked.connect(self.show_fullscreen_display) display_layout.addWidget(self.fullscreen_btn) display_group.setLayout(display_layout) left_layout.addWidget(display_group) # Settings button settings_btn = QPushButton("Settings") settings_btn.clicked.connect(self.open_settings) left_layout.addWidget(settings_btn) left_layout.addStretch() main_layout.addWidget(left_panel) # Right panel - Active timers display right_panel = QWidget() right_layout = QVBoxLayout(right_panel) title_label = QLabel("Active Timers") title_font = QFont("Arial", 16, QFont.Weight.Bold) title_label.setFont(title_font) title_label.setAlignment(Qt.AlignmentFlag.AlignCenter) right_layout.addWidget(title_label) # Scroll area for timers scroll_area = QScrollArea() scroll_area.setWidgetResizable(True) scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.timers_container = QWidget() self.timers_layout = QVBoxLayout(self.timers_container) self.timers_layout.setAlignment(Qt.AlignmentFlag.AlignTop) scroll_area.setWidget(self.timers_container) right_layout.addWidget(scroll_area) main_layout.addWidget(right_panel, stretch=1) # Status bar self.statusBar().showMessage("Ready") def add_timer(self): dialog = TimerDialog(self) if dialog.exec(): timer = dialog.get_timer() self.timers.append(timer) self.timer_list.addItem(timer.name) self.save_timers() self.statusBar().showMessage(f"Timer '{timer.name}' added", 3000) def edit_timer(self): current_row = self.timer_list.currentRow() if current_row >= 0: timer = self.timers[current_row] dialog = TimerDialog(self, timer) if dialog.exec(): updated_timer = dialog.get_timer() self.timers[current_row] = updated_timer self.timer_list.item(current_row).setText(updated_timer.name) self.save_timers() self.statusBar().showMessage(f"Timer '{updated_timer.name}' updated", 3000) def delete_timer(self): current_row = self.timer_list.currentRow() if current_row >= 0: timer_name = self.timers[current_row].name del self.timers[current_row] self.timer_list.takeItem(current_row) self.save_timers() self.statusBar().showMessage(f"Timer '{timer_name}' deleted", 3000) def start_timer(self): current_row = self.timer_list.currentRow() if current_row >= 0: timer = self.timers[current_row] # Create timer widget timer_widget = TimerWidget(timer) timer_widget.finished.connect(lambda: self.remove_timer_widget(timer_widget)) self.timer_widgets.append(timer_widget) self.timers_layout.addWidget(timer_widget) # If fullscreen display is active, update it if self.fullscreen_display and self.fullscreen_display.isVisible(): self.fullscreen_display.add_timer_widget(timer_widget) self.statusBar().showMessage(f"Timer '{timer.name}' started", 3000) def remove_timer_widget(self, timer_widget): if timer_widget in self.timer_widgets: self.timer_widgets.remove(timer_widget) self.timers_layout.removeWidget(timer_widget) timer_widget.deleteLater() # Update fullscreen display if active if self.fullscreen_display and self.fullscreen_display.isVisible(): self.fullscreen_display.remove_timer_widget(timer_widget) self.statusBar().showMessage("Timer finished", 3000) def show_fullscreen_display(self): """Show all active timers on a fullscreen display.""" if not self.timer_widgets: self.statusBar().showMessage("No timers running. Start a timer first.", 3000) return monitor_index = self.settings.value("monitor_index", 0, type=int) if self.fullscreen_display is None: self.fullscreen_display = FullscreenDisplay(monitor_index) self.fullscreen_display.closed.connect(self.on_fullscreen_closed) # Add all active timer widgets to fullscreen display for timer_widget in self.timer_widgets: self.fullscreen_display.add_timer_widget(timer_widget) self.fullscreen_display.show() self.statusBar().showMessage("Fullscreen display opened on selected monitor", 3000) def on_fullscreen_closed(self): """Handle fullscreen display being closed.""" self.fullscreen_display = None self.statusBar().showMessage("Fullscreen display closed", 3000) def stop_all_timers(self): if not self.timer_widgets: self.statusBar().showMessage("No timers running", 3000) return count = len(self.timer_widgets) for timer_widget in list(self.timer_widgets): timer_widget.stop_timer() self.statusBar().showMessage(f"Stopped {count} timer(s)", 3000) def pause_all_timers(self): if not self.timer_widgets: self.statusBar().showMessage("No timers running", 3000) return count = 0 for timer_widget in self.timer_widgets: if not timer_widget.is_paused: timer_widget.toggle_pause() count += 1 self.statusBar().showMessage(f"Paused {count} timer(s)", 3000) def resume_all_timers(self): if not self.timer_widgets: self.statusBar().showMessage("No timers running", 3000) return count = 0 for timer_widget in self.timer_widgets: if timer_widget.is_paused: timer_widget.toggle_pause() count += 1 self.statusBar().showMessage(f"Resumed {count} timer(s)", 3000) def open_settings(self): dialog = SettingsDialog(self) dialog.exec() def save_timers(self): self.settings.beginWriteArray("timers") for i, timer in enumerate(self.timers): self.settings.setArrayIndex(i) self.settings.setValue("name", timer.name) self.settings.setValue("duration", timer.duration) self.settings.setValue("font_size", timer.font_size) self.settings.setValue("bg_color", timer.bg_color) self.settings.setValue("text_color", timer.text_color) self.settings.endArray() def load_timers(self): size = self.settings.beginReadArray("timers") for i in range(size): self.settings.setArrayIndex(i) timer = Timer( name=self.settings.value("name", ""), duration=self.settings.value("duration", 60, type=int), font_size=self.settings.value("font_size", 120, type=int), bg_color=self.settings.value("bg_color", "#000000"), text_color=self.settings.value("text_color", "#FFFFFF") ) self.timers.append(timer) self.timer_list.addItem(timer.name) self.settings.endArray()