handOver2/utils/common_methods.py

192 lines
5.2 KiB
Python

# -*- coding: utf-8 -*-
"""
공통 메서드 모듈
여러 모듈에서 반복 사용되는 공통 기능을 제공합니다.
"""
from typing import List, Optional
from datetime import date
from PySide6.QtCore import QPoint
from database.crud import CRUDManager
from database.models import Fault
from core.signals import GlobalSignals
from core.logger import get_logger
logger = get_logger(__name__)
class TrainInfoMixin:
"""
편성 정보 관련 공통 기능을 제공하는 Mixin 클래스
편성번호 필드가 있는 위젯에서 사용합니다.
마우스 호버 시 최근 고장 목록 팝업을 표시합니다.
Examples:
>>> class MyTable(QTableWidget, TrainInfoMixin):
... def __init__(self):
... super().__init__()
... self.setup_train_info()
"""
def setup_train_info(self):
"""편성 정보 기능 초기화"""
self.crud = CRUDManager()
self.signals = GlobalSignals()
self._train_popup = None
def get_recent_faults(self, train_number: str, limit: int = 10) -> List[Fault]:
"""
특정 편성의 최근 고장 목록 조회
Args:
train_number: 편성번호
limit: 최대 개수
Returns:
고장 리스트
"""
if not hasattr(self, 'crud'):
self.crud = CRUDManager()
return self.crud.get_faults_by_train(train_number, limit)
def show_train_popup(self, train_number: str, position: QPoint):
"""
편성 정보 팝업 표시
Args:
train_number: 편성번호
position: 표시 위치
"""
if not train_number:
return
# 팝업이 없으면 생성
if self._train_popup is None:
from ui.components.train_info_popup import TrainInfoPopup
self._train_popup = TrainInfoPopup()
self._train_popup.detail_requested.connect(self.open_train_detail)
self._train_popup.show_train_info(train_number, position)
def hide_train_popup(self):
"""편성 팝업 숨기기"""
if self._train_popup:
self._train_popup.hide_popup()
def open_train_detail(self, train_number: str):
"""
편성 상세 정보 다이얼로그 열기
Args:
train_number: 편성번호
"""
logger.info(f"편성 상세 정보 요청: {train_number}")
# TODO: 편성 상세 다이얼로그 구현
def check_train_has_work(self, train_number: str, target_date: date = None) -> bool:
"""
해당 편성에 작업이 있는지 확인
Args:
train_number: 편성번호
target_date: 확인 날짜 (기본: 오늘)
Returns:
작업 존재 여부
"""
if not hasattr(self, 'crud'):
self.crud = CRUDManager()
if target_date is None:
target_date = date.today()
return self.crud.check_train_has_work(train_number, target_date)
def on_train_hover(self, train_number: str, x: int, y: int):
"""
편성 필드 위에 마우스 호버 시 호출
시그널을 통해 팝업 표시를 요청합니다.
Args:
train_number: 편성번호
x: 마우스 X 좌표
y: 마우스 Y 좌표
"""
if not hasattr(self, 'signals'):
self.signals = GlobalSignals()
self.signals.show_train_popup.emit(train_number, x, y)
def on_train_leave(self):
"""편성 필드에서 마우스가 벗어났을 때 호출"""
if not hasattr(self, 'signals'):
self.signals = GlobalSignals()
self.signals.hide_train_popup.emit()
def format_fault_summary(fault: Fault) -> str:
"""
고장 요약 문자열 생성
Args:
fault: 고장 객체
Returns:
요약 문자열
"""
parts = []
if fault.occurrence_date:
if isinstance(fault.occurrence_date, date):
parts.append(fault.occurrence_date.strftime("%m/%d"))
else:
parts.append(str(fault.occurrence_date)[:5])
if fault.car_number:
parts.append(f"{fault.car_number}호차")
if fault.device_category:
parts.append(fault.device_category)
content = fault.fault_content or ""
if len(content) > 30:
content = content[:30] + "..."
parts.append(content)
return " | ".join(parts)
def create_fault_popup_content(faults: List[Fault]) -> str:
"""
팝업에 표시할 고장 목록 HTML 생성
Args:
faults: 고장 리스트
Returns:
HTML 문자열
"""
if not faults:
return "<p>최근 고장 기록이 없습니다.</p>"
html_parts = ["<ul>"]
for fault in faults[:5]: # 최대 5개
summary = format_fault_summary(fault)
html_parts.append(f"<li>{summary}</li>")
html_parts.append("</ul>")
if len(faults) > 5:
html_parts.append(f"<p>... 외 {len(faults) - 5}건</p>")
return "\n".join(html_parts)