""" 시스템 트레이 아이콘 """ from PyQt5.QtWidgets import QSystemTrayIcon, QMenu, QAction from PyQt5.QtGui import QIcon, QPixmap, QPainter, QFont, QColor from PyQt5.QtCore import Qt, QSize from core.i18n import tr class SystemTrayIcon(QSystemTrayIcon): """시스템 트레이 아이콘 클래스""" def __init__(self, parent=None): # 기본 아이콘 생성 icon = self.create_icon("⏰") super().__init__(icon, parent) self.parent_window = parent self.setup_menu() # 클릭 이벤트 self.activated.connect(self.on_tray_activated) def create_icon(self, text: str, color: QColor = None) -> QIcon: """ 텍스트로 아이콘 생성 Args: text: 아이콘에 표시할 텍스트 (이모지 또는 시간) color: 배경색 Returns: QIcon: 생성된 아이콘 """ pixmap = QPixmap(64, 64) if color: pixmap.fill(color) else: pixmap.fill(Qt.transparent) painter = QPainter(pixmap) # 텍스트 그리기 if len(text) <= 2: # 이모지 font = QFont("Segoe UI Emoji", 40) else: # 시간 표시 font = QFont("Consolas", 12, QFont.Bold) painter.fillRect(pixmap.rect(), QColor(255, 255, 255)) painter.setFont(font) painter.setPen(QColor(0, 0, 0)) painter.drawText(pixmap.rect(), Qt.AlignCenter, text) painter.end() return QIcon(pixmap) def setup_menu(self): """트레이 메뉴 설정""" menu = QMenu() show_action = QAction(tr('tray.open'), self) show_action.triggered.connect(self.show_window) menu.addAction(show_action) mini_action = QAction(tr('tray.mini_widget'), self) mini_action.triggered.connect(self._open_mini_widget) menu.addAction(mini_action) menu.addSeparator() lunch_action = QAction(tr('tray.toggle_lunch'), self) lunch_action.triggered.connect(self._toggle_lunch) menu.addAction(lunch_action) break_out_action = QAction(tr('btn.break_out'), self) break_out_action.triggered.connect(self._break_out) menu.addAction(break_out_action) break_in_action = QAction(tr('btn.break_in'), self) break_in_action.triggered.connect(self._break_in) menu.addAction(break_in_action) menu.addSeparator() clock_out_action = QAction("✅ " + tr('btn.clock_out'), self) clock_out_action.triggered.connect(self.quick_clock_out) menu.addAction(clock_out_action) menu.addSeparator() stats_action = QAction("📊 " + tr('menu.stats'), self) stats_action.triggered.connect(lambda: self._call_parent('show_stats')) menu.addAction(stats_action) cal_action = QAction("📅 " + tr('menu.calendar'), self) cal_action.triggered.connect(lambda: self._call_parent('show_calendar')) menu.addAction(cal_action) schedule_action = QAction("🗓️ 스케줄", self) schedule_action.triggered.connect(lambda: self._call_parent('show_schedule')) menu.addAction(schedule_action) help_action = QAction("📖 " + tr('menu.help'), self) help_action.triggered.connect(lambda: self._call_parent('show_help')) menu.addAction(help_action) menu.addSeparator() quit_action = QAction(tr('tray.quit'), self) quit_action.triggered.connect(self.quit_app) menu.addAction(quit_action) self.setContextMenu(menu) def _call_parent(self, method_name: str): if self.parent_window and hasattr(self.parent_window, method_name): getattr(self.parent_window, method_name)() def _toggle_lunch(self): if self.parent_window and hasattr(self.parent_window, 'lunch_button'): self.parent_window.lunch_button.click() def _break_out(self): if self.parent_window and hasattr(self.parent_window, 'break_out'): self.parent_window.break_out() def _break_in(self): if self.parent_window and hasattr(self.parent_window, 'break_in'): self.parent_window.break_in() def _open_mini_widget(self): self._call_parent('show_mini_widget') def on_tray_activated(self, reason): """트레이 아이콘 클릭 시""" if reason == QSystemTrayIcon.DoubleClick: self.show_window() def show_window(self): """메인 윈도우 표시""" if self.parent_window: self.parent_window.show() self.parent_window.activateWindow() def quick_clock_out(self): """빠른 퇴근""" if self.parent_window and hasattr(self.parent_window, 'clock_out'): self.parent_window.clock_out() def quit_app(self): """앱 종료""" from PyQt5.QtWidgets import QApplication QApplication.quit() def update_time_display(self, remaining_str: str): """ 남은 시간 표시 업데이트 Args: remaining_str: "HH:MM" 형식의 시간 """ # 간단한 시간 표시로 아이콘 업데이트 if remaining_str.startswith('+'): icon = self.create_icon("🔥") self.setToolTip(tr('tray.tooltip_overtime', time=remaining_str)) elif remaining_str.startswith('-'): icon = self.create_icon("⏰") self.setToolTip(tr('tray.tooltip_remaining', time='--')) else: parts = remaining_str.split(':') display_time = f"{parts[0]}:{parts[1]}" if len(parts) >= 2 else remaining_str icon = self.create_icon("⏰") self.setToolTip(tr('tray.tooltip_remaining', time=display_time)) self.setIcon(icon) # 테스트 코드 if __name__ == "__main__": from PyQt5.QtWidgets import QApplication, QMainWindow import sys app = QApplication(sys.argv) window = QMainWindow() window.setWindowTitle("Main Window") tray = SystemTrayIcon(window) tray.show() window.show() sys.exit(app.exec_())