handOver2/ui/panels/status_bar.py

344 lines
10 KiB
Python

# -*- coding: utf-8 -*-
"""
상태바 모듈
화면 하단의 상태 표시 바입니다.
접속자 정보, DB 상태, 동기화 상태, 버전 정보 등을 표시합니다.
"""
from datetime import datetime
from PySide6.QtWidgets import (
QWidget, QHBoxLayout, QLabel, QFrame,
QProgressBar
)
from PySide6.QtCore import Qt, Signal, QTimer
from PySide6.QtGui import QFont
from ui.base.base_widget import BaseWidget
from core.config import ConfigManager
from core.signals import GlobalSignals
from core.constants import APP_VERSION
from core.logger import get_logger
logger = get_logger(__name__)
class StatusBar(BaseWidget):
"""
상태바 위젯
화면 하단 10% 영역에 표시되는 상태 바입니다.
접속자, DB 상태, 마지막 동기화, 버전 정보 등을 포함합니다.
Examples:
>>> status_bar = StatusBar()
>>> status_bar.set_user_info("홍길동", "검수팀")
"""
def __init__(self, parent=None):
super().__init__(parent)
self._user_name = ""
self._user_department = ""
self._db_status = "정상"
self._sync_time = None
self._message = ""
self._message_timer = QTimer()
self._message_timer.setSingleShot(True)
self._message_timer.timeout.connect(self._clear_message)
self._setup_ui()
self._connect_signals()
logger.info("상태바 초기화 완료")
def _setup_ui(self):
"""UI 설정"""
layout = QHBoxLayout(self)
layout.setContentsMargins(24, 8, 24, 8)
layout.setSpacing(16)
# 사용자 정보
self._create_user_section(layout)
# 구분선
self._add_separator(layout)
# DB 상태
self._create_db_section(layout)
# 구분선
self._add_separator(layout)
# 동기화 상태
self._create_sync_section(layout)
# 늘어남 영역
layout.addStretch()
# 상태 메시지
self._create_message_section(layout)
# 늘어남 영역
layout.addStretch()
# 프로그레스바 (숨김)
self._create_progress_section(layout)
# 구분선
self._add_separator(layout)
# 버전 정보
self._create_version_section(layout)
# 스타일 적용
self._apply_style()
def _create_user_section(self, layout: QHBoxLayout):
"""사용자 섹션 생성"""
self.user_icon = QLabel("👤")
self.user_icon.setFont(QFont("Segoe UI Emoji", 14))
self.user_label = QLabel("로그인 필요")
self.user_label.setObjectName("userLabel")
self.user_label.setFont(QFont("GmarketSans", 12))
layout.addWidget(self.user_icon)
layout.addWidget(self.user_label)
def _create_db_section(self, layout: QHBoxLayout):
"""DB 상태 섹션 생성"""
self.db_icon = QLabel("🗄️")
self.db_icon.setFont(QFont("Segoe UI Emoji", 14))
self.db_label = QLabel("DB 상태: 정상")
self.db_label.setObjectName("dbLabel")
self.db_label.setFont(QFont("GmarketSans", 12))
layout.addWidget(self.db_icon)
layout.addWidget(self.db_label)
def _create_sync_section(self, layout: QHBoxLayout):
"""동기화 상태 섹션 생성"""
self.sync_icon = QLabel("🔄")
self.sync_icon.setFont(QFont("Segoe UI Emoji", 14))
self.sync_label = QLabel("동기화: 로컬 전용")
self.sync_label.setObjectName("syncLabel")
self.sync_label.setFont(QFont("GmarketSans", 12))
layout.addWidget(self.sync_icon)
layout.addWidget(self.sync_label)
def _create_message_section(self, layout: QHBoxLayout):
"""상태 메시지 섹션 생성"""
self.message_label = QLabel("")
self.message_label.setObjectName("messageLabel")
self.message_label.setFont(QFont("GmarketSans", 12))
self.message_label.setAlignment(Qt.AlignCenter)
layout.addWidget(self.message_label)
def _create_progress_section(self, layout: QHBoxLayout):
"""프로그레스바 섹션 생성"""
self.progress_bar = QProgressBar()
self.progress_bar.setObjectName("progressBar")
self.progress_bar.setFixedWidth(150)
self.progress_bar.setFixedHeight(6)
self.progress_bar.setTextVisible(False)
self.progress_bar.hide()
layout.addWidget(self.progress_bar)
def _create_version_section(self, layout: QHBoxLayout):
"""버전 섹션 생성"""
self.version_label = QLabel(f"v{APP_VERSION}")
self.version_label.setObjectName("versionLabel")
self.version_label.setFont(QFont("GmarketSans", 11))
layout.addWidget(self.version_label)
def _add_separator(self, layout: QHBoxLayout):
"""구분선 추가"""
separator = QFrame()
separator.setFrameShape(QFrame.VLine)
separator.setObjectName("separator")
layout.addWidget(separator)
def _apply_style(self):
"""스타일 적용"""
theme = self.config.theme
if theme == 'dark':
bg = "#0f172a"
text = "#94a3b8"
separator = "#334155"
success = "#22c55e"
warning = "#f59e0b"
error = "#ef4444"
progress_bg = "#334155"
progress_fill = "#3b82f6"
else:
bg = "#f8fafc"
text = "#64748b"
separator = "#e2e8f0"
success = "#22c55e"
warning = "#f59e0b"
error = "#ef4444"
progress_bg = "#e2e8f0"
progress_fill = "#3b82f6"
self.setStyleSheet(f"""
StatusBar {{
background-color: {bg};
border-top: 1px solid {separator};
}}
QLabel {{
color: {text};
}}
#separator {{
color: {separator};
}}
#progressBar {{
background-color: {progress_bg};
border: none;
border-radius: 3px;
}}
#progressBar::chunk {{
background-color: {progress_fill};
border-radius: 3px;
}}
""")
def _connect_signals(self):
"""시그널 연결"""
self.signals.user_logged_in.connect(self._on_user_logged_in)
self.signals.user_logged_out.connect(self._on_user_logged_out)
self.signals.sync_completed.connect(self._on_sync_completed)
self.signals.sync_error.connect(self._on_sync_error)
self.signals.status_message.connect(self.show_message)
self.signals.update_progress.connect(self._on_update_progress)
# ========================================================================
# 공개 메서드
# ========================================================================
def set_user_info(self, name: str, department: str):
"""
사용자 정보 설정
Args:
name: 사용자 이름
department: 부서명
"""
self._user_name = name
self._user_department = department
self.user_label.setText(f"{name} ({department})")
def set_db_status(self, status: str, is_error: bool = False):
"""
DB 상태 설정
Args:
status: 상태 텍스트
is_error: 오류 여부
"""
self._db_status = status
self.db_label.setText(f"DB 상태: {status}")
if is_error:
self.db_icon.setText("⚠️")
else:
self.db_icon.setText("🗄️")
def set_sync_time(self, sync_time: datetime = None):
"""
동기화 시간 설정
Args:
sync_time: 동기화 시간
"""
self._sync_time = sync_time
if sync_time:
time_str = sync_time.strftime("%H:%M")
self.sync_label.setText(f"마지막 동기화: {time_str}")
else:
self.sync_label.setText("동기화: 로컬 전용")
def show_message(self, message: str, timeout: int = 3000):
"""
상태 메시지 표시
Args:
message: 메시지 텍스트
timeout: 표시 시간 (ms)
"""
self._message = message
self.message_label.setText(message)
if timeout > 0:
self._message_timer.start(timeout)
def _clear_message(self):
"""메시지 지우기"""
self._message = ""
self.message_label.setText("")
def show_progress(self, value: int = -1):
"""
프로그레스바 표시
Args:
value: 진행률 (0-100), -1이면 무한
"""
self.progress_bar.show()
if value < 0:
self.progress_bar.setRange(0, 0) # 무한 프로그레스
else:
self.progress_bar.setRange(0, 100)
self.progress_bar.setValue(value)
def hide_progress(self):
"""프로그레스바 숨기기"""
self.progress_bar.hide()
# ========================================================================
# 시그널 핸들러
# ========================================================================
def _on_user_logged_in(self, user_id: int, username: str):
"""사용자 로그인"""
# TODO: DB에서 사용자 정보 조회
self.set_user_info(username, "")
def _on_user_logged_out(self):
"""사용자 로그아웃"""
self._user_name = ""
self._user_department = ""
self.user_label.setText("로그인 필요")
def _on_sync_completed(self):
"""동기화 완료"""
self.set_sync_time(datetime.now())
self.show_message("동기화 완료", 2000)
def _on_sync_error(self, error_msg: str):
"""동기화 오류"""
self.sync_icon.setText("⚠️")
self.show_message(f"동기화 오류: {error_msg}", 5000)
def _on_update_progress(self, value: int):
"""업데이트 진행률"""
if value >= 100:
self.hide_progress()
else:
self.show_progress(value)