206 lines
6.6 KiB
Python
206 lines
6.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
할일 입력 다이얼로그 모듈
|
|
할일 입력을 위한 다이얼로그입니다.
|
|
"""
|
|
|
|
from datetime import date, datetime, time
|
|
from typing import List, Optional
|
|
|
|
from PySide6.QtWidgets import (
|
|
QWidget, QHBoxLayout, QVBoxLayout, QLabel, QPushButton
|
|
)
|
|
from PySide6.QtCore import Qt, Signal
|
|
from PySide6.QtGui import QFont
|
|
|
|
from ui.base.base_dialog import BaseDialog
|
|
from ui.components.custom_input import CustomLineEdit, CustomTextEdit, LabeledInput
|
|
from database.models import Todo, TodoCategory
|
|
from core.config import ConfigManager
|
|
from core.logger import get_logger
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
class CategoryChip(QPushButton):
|
|
"""카테고리 선택 칩"""
|
|
|
|
chip_selected = Signal(str) # category
|
|
|
|
def __init__(self, category: str, icon: str = "", parent=None):
|
|
super().__init__(parent)
|
|
|
|
self.config = ConfigManager()
|
|
self.category = category
|
|
self._is_selected = False
|
|
|
|
if category == TodoCategory.ARRIVAL_INSPECTION:
|
|
self.setText(f"🚃 {category}")
|
|
self.icon_color = "#8b5cf6"
|
|
elif category == TodoCategory.TASK:
|
|
self.setText(f"🔧 {category}")
|
|
self.icon_color = "#f59e0b"
|
|
else:
|
|
self.setText(f"📝 {category}")
|
|
self.icon_color = "#3b82f6"
|
|
|
|
self.setMinimumWidth(90)
|
|
self.setFixedHeight(36)
|
|
self.setCursor(Qt.PointingHandCursor)
|
|
self.setFont(QFont("GmarketSans", 11, QFont.Bold))
|
|
|
|
self.clicked.connect(self._on_clicked)
|
|
self._apply_style()
|
|
|
|
def _on_clicked(self):
|
|
"""클릭 이벤트"""
|
|
self.chip_selected.emit(self.category)
|
|
|
|
def set_selected(self, selected: bool):
|
|
"""선택 상태 설정"""
|
|
self._is_selected = selected
|
|
self._apply_style()
|
|
|
|
def _apply_style(self):
|
|
"""스타일 적용"""
|
|
theme = self.config.theme
|
|
|
|
if self._is_selected:
|
|
self.setStyleSheet(f"""
|
|
QPushButton {{
|
|
background-color: {self.icon_color};
|
|
color: white;
|
|
border: 3px solid {self.icon_color};
|
|
border-radius: 8px;
|
|
padding: 0 12px;
|
|
font-weight: bold;
|
|
}}
|
|
""")
|
|
else:
|
|
if theme == 'dark':
|
|
bg = "#334155"
|
|
text = "#94a3b8"
|
|
else:
|
|
bg = "#e2e8f0"
|
|
text = "#64748b"
|
|
|
|
self.setStyleSheet(f"""
|
|
QPushButton {{
|
|
background-color: {bg};
|
|
color: {text};
|
|
border: 2px solid transparent;
|
|
border-radius: 8px;
|
|
padding: 0 12px;
|
|
}}
|
|
QPushButton:hover {{
|
|
background-color: {self.icon_color};
|
|
color: white;
|
|
}}
|
|
""")
|
|
|
|
|
|
class TodoInputDialog(BaseDialog):
|
|
"""할일 입력 다이얼로그"""
|
|
|
|
def __init__(
|
|
self,
|
|
parent=None,
|
|
todo_date: date = None,
|
|
todo: Todo = None
|
|
):
|
|
title = "할일 추가" if todo is None else "할일 편집"
|
|
super().__init__(parent, title=title, width=450, height=500)
|
|
|
|
self.todo_date = todo_date or date.today()
|
|
self.todo = todo
|
|
|
|
self._selected_category: str = TodoCategory.GENERAL
|
|
self._category_chips: List[CategoryChip] = []
|
|
|
|
self._setup_fields()
|
|
self.add_confirm_cancel_buttons()
|
|
|
|
if todo:
|
|
self._load_todo(todo)
|
|
|
|
def _setup_fields(self):
|
|
"""필드 설정"""
|
|
theme = self.config.theme
|
|
text_color = "#f8fafc" if theme == 'dark' else "#1e293b"
|
|
|
|
# 카테고리 섹션
|
|
category_label = QLabel("카테고리")
|
|
category_label.setFont(QFont("GmarketSans", 12, QFont.Bold))
|
|
category_label.setStyleSheet(f"color: {text_color};")
|
|
self.content_layout.addWidget(category_label)
|
|
|
|
# 카테고리 칩 컨테이너
|
|
category_container = QWidget()
|
|
category_layout = QHBoxLayout(category_container)
|
|
category_layout.setContentsMargins(0, 0, 0, 0)
|
|
category_layout.setSpacing(8)
|
|
|
|
categories = [TodoCategory.GENERAL, TodoCategory.ARRIVAL_INSPECTION, TodoCategory.TASK]
|
|
for cat in categories:
|
|
chip = CategoryChip(cat)
|
|
chip.chip_selected.connect(self._on_category_selected)
|
|
self._category_chips.append(chip)
|
|
category_layout.addWidget(chip)
|
|
|
|
# 기본 선택: 일반
|
|
self._category_chips[0].set_selected(True)
|
|
|
|
category_layout.addStretch()
|
|
self.content_layout.addWidget(category_container)
|
|
|
|
# 내용
|
|
self.content_input = CustomTextEdit(
|
|
placeholder="할일 내용을 입력하세요",
|
|
min_height=80
|
|
)
|
|
self.content_layout.addWidget(
|
|
LabeledInput("내용", self.content_input, required=True)
|
|
)
|
|
|
|
# 대상편성
|
|
self.train_input = CustomLineEdit(placeholder="예: 151A (선택)")
|
|
self.content_layout.addWidget(
|
|
LabeledInput("대상편성", self.train_input)
|
|
)
|
|
|
|
# 일정
|
|
self.schedule_input = CustomLineEdit(placeholder="예: 오전 10시 (선택)")
|
|
self.content_layout.addWidget(
|
|
LabeledInput("일정", self.schedule_input)
|
|
)
|
|
|
|
self.content_layout.addStretch()
|
|
|
|
def _on_category_selected(self, category: str):
|
|
"""카테고리 선택"""
|
|
for chip in self._category_chips:
|
|
chip.set_selected(chip.category == category)
|
|
|
|
self._selected_category = category
|
|
|
|
def _load_todo(self, todo: Todo):
|
|
"""할일 데이터 로드"""
|
|
self.content_input.set_text(todo.content or "")
|
|
self.train_input.setText(todo.target_train or "")
|
|
self.schedule_input.setText(todo.schedule or "")
|
|
|
|
# 카테고리 선택
|
|
category = todo.category or TodoCategory.GENERAL
|
|
self._on_category_selected(category)
|
|
|
|
def get_data(self) -> dict:
|
|
"""입력 데이터 반환"""
|
|
return {
|
|
"todo_date": self.todo_date.isoformat(),
|
|
"category": self._selected_category,
|
|
"content": self.content_input.get_text(),
|
|
"target_train": self.train_input.text(),
|
|
"schedule": self.schedule_input.text(),
|
|
"is_completed": False,
|
|
}
|