""" Main Window for Frank GUI PyQt6-based desktop application with dashboard, jobs, and history views """ import sys from PyQt6.QtWidgets import ( QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QTabWidget, QLabel, QPushButton, QStatusBar, QMessageBox, QSystemTrayIcon ) from PyQt6.QtCore import QTimer, Qt from PyQt6.QtGui import QIcon, QFont from loguru import logger from core.database import Database from core.config import SchedulerConfig from gui.dashboard_widget import DashboardWidget from gui.jobs_widget import JobsWidget from gui.schedules_widget import SchedulesWidget from gui.history_widget import HistoryWidget from gui.backup_widget import BackupWidget from gui.system_tray import SchedulerSystemTray class MainWindow(QMainWindow): """Main application window""" def __init__(self, db: Database, config: SchedulerConfig): super().__init__() self.db = db self.config = config self.setWindowTitle("Frank - Control Panel") self.setMinimumSize(1200, 800) # Setup UI self._setup_ui() # Setup system tray self.tray_icon = SchedulerSystemTray(self, self.db) self.tray_icon.show() # Setup refresh timer refresh_interval = self.config.get('gui.refresh_interval_ms', 2000) self.refresh_timer = QTimer() self.refresh_timer.timeout.connect(self._refresh_data) self.refresh_timer.start(refresh_interval) logger.info("Main window initialized") def _setup_ui(self): """Setup main UI components""" # Central widget central_widget = QWidget() self.setCentralWidget(central_widget) # Main layout main_layout = QVBoxLayout(central_widget) main_layout.setContentsMargins(10, 10, 10, 10) # Header header_layout = self._create_header() main_layout.addLayout(header_layout) # Tab widget self.tabs = QTabWidget() self.tabs.setTabPosition(QTabWidget.TabPosition.North) # Dashboard tab self.dashboard_widget = DashboardWidget(self.db, self.config) self.tabs.addTab(self.dashboard_widget, "๐Ÿ“Š Dashboard") # Jobs tab self.jobs_widget = JobsWidget(self.db, self.config) self.tabs.addTab(self.jobs_widget, "๐Ÿ“‹ Jobs") # Schedules tab self.schedules_widget = SchedulesWidget(self.db, self.config) self.tabs.addTab(self.schedules_widget, "โฐ Schedules") # Backup tab self.backup_widget = BackupWidget(self.db, self.config) self.tabs.addTab(self.backup_widget, "๐Ÿ’พ Backup") # History tab self.history_widget = HistoryWidget(self.db, self.config) self.tabs.addTab(self.history_widget, "๐Ÿ“œ History") main_layout.addWidget(self.tabs) # Status bar self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.status_bar.showMessage("Ready") def _create_header(self) -> QHBoxLayout: """Create header with title and controls""" header_layout = QHBoxLayout() # Title title_label = QLabel("๐Ÿš€ Frank - Control Panel") title_font = QFont() title_font.setPointSize(16) title_font.setBold(True) title_label.setFont(title_font) header_layout.addWidget(title_label) header_layout.addStretch() # Refresh button refresh_btn = QPushButton("๐Ÿ”„ Refresh") refresh_btn.clicked.connect(self._refresh_data) header_layout.addWidget(refresh_btn) return header_layout def _refresh_data(self): """Refresh all widgets data โ€” solo se la finestra รจ visibile""" if not self.isVisible(): return try: # Get current tab current_widget = self.tabs.currentWidget() # Refresh current tab if hasattr(current_widget, 'refresh'): current_widget.refresh() # Update status bar active_count = len(self.db.get_active_executions()) if active_count > 0: self.status_bar.showMessage(f"๐ŸŸข Active: {active_count} job(s) running") else: self.status_bar.showMessage("๐ŸŸข Ready - No jobs running") except Exception as e: logger.error(f"Error refreshing data: {e}") def closeEvent(self, event): """Handle window close event""" # Minimize to tray instead of closing event.ignore() self.hide() self.tray_icon.showMessage( "Frank", "Application minimized to system tray", QSystemTrayIcon.MessageIcon.Information, 2000 ) def show_window(self): """Show and activate window""" self.show() self.activateWindow() self.raise_()