""" 미니 위젯 — Always-on-top 컴팩트 디스플레이. 남은 시간만 큰 글씨로 보여주는 작은 창. 메인 창과 동일한 1Hz 갱신을 부모 윈도우의 시그널/직접 호출로 받음. """ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QApplication from PyQt5.QtCore import Qt, QPoint from PyQt5.QtGui import QFont, QMouseEvent from core.i18n import tr from ui.styles import apply_dark_titlebar class MiniWidget(QWidget): """Always-on-top 미니 위젯. 제공 기능: - 남은 시간 큰 글씨 - 마우스 드래그로 이동 - 우클릭 메뉴: 메인 창 열기 / 닫기 """ def __init__(self, parent_window=None): super().__init__() self.parent_window = parent_window self._drag_pos: QPoint = None self.setWindowTitle(tr('window.mini_widget')) self.setWindowFlags( Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.Tool ) self.setAttribute(Qt.WA_TranslucentBackground, False) self.setFixedSize(220, 80) layout = QVBoxLayout() layout.setContentsMargins(12, 8, 12, 8) layout.setSpacing(2) self.title_label = QLabel(tr('label.remaining')) self.title_label.setAlignment(Qt.AlignCenter) self.title_label.setStyleSheet("color: #909296; font-size: 11px;") self.time_label = QLabel("--:--:--") self.time_label.setAlignment(Qt.AlignCenter) self.time_label.setFont(QFont("Consolas", 22, QFont.Bold)) layout.addWidget(self.title_label) layout.addWidget(self.time_label) self.setLayout(layout) # 기본 스타일 (테마 무관 가독성 유지 — 메인 다크 팔레트와 정합) self.setStyleSheet(""" QWidget { background-color: rgba(26, 27, 30, 235); border-radius: 8px; } QLabel { color: #E9ECEF; background: transparent; } """) apply_dark_titlebar(self) def update_remaining(self, remaining_str: str): """메인 윈도우에서 호출 — 남은 시간 동기화.""" self.time_label.setText(remaining_str) if remaining_str.startswith('+'): # 연장근무 진입 = 퇴근 가능 → 그린 (메인 히어로와 동일 피드백) self.title_label.setText(tr('label.overtime_progress')) self.time_label.setStyleSheet("color: #51CF66;") else: self.title_label.setText(tr('label.remaining')) self.time_label.setStyleSheet("color: #E9ECEF;") # 드래그 이동 def mousePressEvent(self, event: QMouseEvent): if event.button() == Qt.LeftButton: self._drag_pos = event.globalPos() - self.frameGeometry().topLeft() event.accept() def mouseMoveEvent(self, event: QMouseEvent): if self._drag_pos and event.buttons() & Qt.LeftButton: self.move(event.globalPos() - self._drag_pos) event.accept() def mouseDoubleClickEvent(self, event: QMouseEvent): """더블클릭 시 메인 창 열기.""" if self.parent_window: self.parent_window.show() self.parent_window.raise_() self.parent_window.activateWindow() def contextMenuEvent(self, event): from PyQt5.QtWidgets import QMenu menu = QMenu(self) # 미니 위젯 자체 QSS에는 QMenu 텍스트색이 없어 기본 검정으로 보인다. # 앱 다크 테마 QSS를 명시 적용해 가독성 확보 (트레이 메뉴와 동일 처리). qss = self.parent_window.styleSheet() if self.parent_window else '' if not qss: try: from ui.styles import get_theme qss = get_theme('dark') except Exception: qss = '' if qss: menu.setStyleSheet(qss) open_main = menu.addAction("메인 창 열기") close_mini = menu.addAction("미니 위젯 닫기") action = menu.exec_(event.globalPos()) if action == open_main and self.parent_window: self.parent_window.show() self.parent_window.raise_() self.parent_window.activateWindow() elif action == close_mini: self.close()