handOver2/ui/widgets/memo_widget.py

222 lines
7.1 KiB
Python

# -*- coding: utf-8 -*-
"""
메모 위젯 모듈
메모를 표시하고 관리하는 위젯입니다.
"""
from datetime import date
from PySide6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QFrame, QTextEdit, QDialog
)
from PySide6.QtCore import Qt, Signal, QTimer
from PySide6.QtGui import QFont
from ui.base.base_widget import BaseWidget, CardWidget
from ui.components.custom_button import IconButton
from ui.components.custom_input import CustomTextEdit
from ui.dialogs.memo_input_dialog import MemoInputDialog
from database.crud import CRUDManager
from database.models import Memo
from core.config import ConfigManager
from core.signals import GlobalSignals
from core.constants import AUTO_SAVE_INTERVAL
from core.logger import get_logger
logger = get_logger(__name__)
class MemoWidget(CardWidget):
"""
메모 위젯
메모를 표시하고 관리합니다.
더블클릭으로 편집 모드로 전환됩니다.
Examples:
>>> widget = MemoWidget()
>>> widget.load_data()
"""
memo_changed = Signal()
def __init__(self, parent=None):
super().__init__(parent, padding=12, radius=12)
self.crud = CRUDManager()
self._current_date = date.today()
self._current_memo: Memo = None
self._is_editing = False
# 자동 저장 타이머
self._save_timer = QTimer()
self._save_timer.setSingleShot(True)
self._save_timer.timeout.connect(self._auto_save)
self._setup_ui()
self._connect_signals()
logger.info("메모 위젯 초기화 완료")
def _setup_ui(self):
"""UI 설정"""
# 헤더
header = QWidget()
header_layout = QHBoxLayout(header)
header_layout.setContentsMargins(0, 0, 0, 0)
title = QLabel("📝 메모")
title.setFont(QFont("GmarketSans", 14, QFont.Bold))
theme = self.config.theme
text_color = "#f8fafc" if theme == 'dark' else "#1e293b"
title.setStyleSheet(f"color: {text_color};")
header_layout.addWidget(title)
header_layout.addStretch()
# 편집 버튼
self.edit_btn = IconButton("✏️", size=28, tooltip="메모 편집")
self.edit_btn.clicked.connect(self._on_edit_clicked)
header_layout.addWidget(self.edit_btn)
self.layout.addWidget(header)
# 구분선
separator = QFrame()
separator.setFrameShape(QFrame.HLine)
separator.setStyleSheet("color: #334155;" if theme == 'dark' else "color: #e2e8f0;")
self.layout.addWidget(separator)
# 메모 내용 (표시 모드)
self.memo_display = QLabel("메모가 없습니다. 더블클릭하여 추가하세요.")
self.memo_display.setFont(QFont("GmarketSans", 12))
self.memo_display.setWordWrap(True)
self.memo_display.setAlignment(Qt.AlignTop | Qt.AlignLeft)
self.memo_display.setMinimumHeight(100)
self.memo_display.setCursor(Qt.PointingHandCursor)
self.memo_display.mouseDoubleClickEvent = lambda e: self._on_edit_clicked()
if theme == 'dark':
self.memo_display.setStyleSheet("color: #e2e8f0;")
else:
self.memo_display.setStyleSheet("color: #374151;")
self.layout.addWidget(self.memo_display, 1)
# 메모 내용 (편집 모드)
self.memo_edit = CustomTextEdit(
placeholder="메모를 입력하세요...",
min_height=100
)
self.memo_edit.text_changed_signal.connect(self._on_text_changed)
self.memo_edit.hide()
self.layout.addWidget(self.memo_edit, 1)
# 저장/취소 버튼 (편집 모드)
self.button_widget = QWidget()
button_layout = QHBoxLayout(self.button_widget)
button_layout.setContentsMargins(0, 8, 0, 0)
button_layout.setSpacing(8)
button_layout.addStretch()
self.cancel_btn = IconButton("", size=28, tooltip="취소")
self.cancel_btn.clicked.connect(self._on_cancel_clicked)
button_layout.addWidget(self.cancel_btn)
self.save_btn = IconButton("", size=28, tooltip="저장")
self.save_btn.clicked.connect(self._on_save_clicked)
button_layout.addWidget(self.save_btn)
self.button_widget.hide()
self.layout.addWidget(self.button_widget)
def _connect_signals(self):
"""시그널 연결"""
self.signals.memo_changed.connect(self._on_memo_signal_changed)
def load_data(self):
"""데이터 로드"""
self._current_memo = self.crud.get_latest_memo(self._current_date)
if self._current_memo and self._current_memo.content:
self.memo_display.setText(self._current_memo.content)
else:
theme = self.config.theme
placeholder_color = "#64748b" if theme == 'dark' else "#94a3b8"
self.memo_display.setText("메모가 없습니다. 더블클릭하여 추가하세요.")
self.memo_display.setStyleSheet(f"color: {placeholder_color};")
def _on_edit_clicked(self):
"""편집 버튼 클릭"""
self._is_editing = True
# 표시 모드 숨기기
self.memo_display.hide()
self.edit_btn.hide()
# 편집 모드 표시
self.memo_edit.show()
self.button_widget.show()
# 현재 내용 설정
if self._current_memo and self._current_memo.content:
self.memo_edit.set_text(self._current_memo.content)
else:
self.memo_edit.set_text("")
self.memo_edit.setFocus()
def _on_save_clicked(self):
"""저장 버튼 클릭"""
content = self.memo_edit.get_text()
self.crud.upsert_memo(
memo_date=self._current_date,
content=content
)
self._exit_edit_mode()
self.load_data()
self.memo_changed.emit()
def _on_cancel_clicked(self):
"""취소 버튼 클릭"""
self._exit_edit_mode()
def _exit_edit_mode(self):
"""편집 모드 종료"""
self._is_editing = False
self._save_timer.stop()
# 편집 모드 숨기기
self.memo_edit.hide()
self.button_widget.hide()
# 표시 모드 표시
self.memo_display.show()
self.edit_btn.show()
def _on_text_changed(self, text: str):
"""텍스트 변경 시 자동 저장 타이머 시작"""
if self._is_editing:
self._save_timer.start(AUTO_SAVE_INTERVAL * 1000)
def _auto_save(self):
"""자동 저장"""
if self._is_editing:
content = self.memo_edit.get_text()
self.crud.upsert_memo(
memo_date=self._current_date,
content=content
)
logger.debug("메모 자동 저장")
def _on_memo_signal_changed(self, memo_id: int):
"""메모 변경 시그널"""
self.load_data()