summaryrefslogtreecommitdiff
path: root/calendar_gui.py
diff options
context:
space:
mode:
Diffstat (limited to 'calendar_gui.py')
-rw-r--r--calendar_gui.py117
1 files changed, 56 insertions, 61 deletions
diff --git a/calendar_gui.py b/calendar_gui.py
index 932d97e..75f77fb 100644
--- a/calendar_gui.py
+++ b/calendar_gui.py
@@ -7,20 +7,21 @@ from PyQt5.QtCore import Qt, QDate, QLocale
from PyQt5.QtGui import QFont, QFontDatabase
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
+
from calendar_manager import CalendarManager
from date_calculator import DateCalculator
from prediction_controller import PredictionController
-import math
-
-DATEFORMAT = "dd.MM.yyyy"
+from event_type_handler import EventTypeHandler
+from date_service import DateService
+from file_service import FileService
+from config import EventConfig
class EventDialog(QDialog):
- def __init__(self, keyword_list, entry=None, parent=None, dateformat: str = DATEFORMAT):
+ def __init__(self, entry=None, parent=None):
super().__init__(parent)
- self.keyword_list = keyword_list
self.entry = entry
- self.dateformat = dateformat
+ self.dateformat = EventConfig.DATE_FORMAT
# Set title based on mode
self.setWindowTitle("Neuer Eintrag" if not entry else "Eintrag editieren")
@@ -74,11 +75,11 @@ class EventDialog(QDialog):
# Keyword selector
self.keyword = QComboBox()
self.keyword.setFont(font)
- self.keyword.addItems(self.keyword_list)
+ self.keyword.addItems(EventConfig.KEYWORDS)
# Set initial keyword based on mode
- if self.entry and self.entry.keyword in self.keyword_list:
- current_index = self.keyword_list.index(self.entry.keyword)
+ if self.entry and self.entry.keyword in EventConfig.KEYWORDS:
+ current_index = EventConfig.KEYWORDS.index(self.entry.keyword)
self.keyword.setCurrentIndex(current_index)
self.keyword.currentTextChanged.connect(self.on_keyword_changed)
@@ -121,14 +122,14 @@ class EventDialog(QDialog):
end_date_label = self.layout.itemAt(self.end_date_row, QFormLayout.LabelRole).widget()
end_date_field = self.layout.itemAt(self.end_date_row, QFormLayout.FieldRole).widget()
- if keyword == "EZ pauschal":
- # Hide end date field for EZ pauschals since they have fixed 4-week duration
+ if EventTypeHandler.should_hide_end_date_input(keyword):
+ # Hide end date field for EZ pauschals since they have fixed duration
end_date_label.setVisible(False)
end_date_field.setVisible(False)
# Update end date automatically if changing to EZ pauschal
start_dt = self.start_date.date().toPyDate()
- end_dt = start_dt + relativedelta(years = 2, days = -1)
+ end_dt = EventTypeHandler.get_duration_for_type(keyword, start_dt)
self.end_date.setDate(QDate(end_dt.year, end_dt.month, end_dt.day))
else:
# Show end date field for other event types
@@ -140,17 +141,17 @@ class EventDialog(QDialog):
if self.end_date.date() < self.start_date.date():
self.end_date.setDate(self.start_date.date())
def get_data(self):
- start_date = self.start_date.date().toString("yyyy-MM-dd")
+ start_date = DateService.format_date_for_iso(self.start_date.date())
keyword = self.keyword.currentText()
commentary = self.commentary_input.toPlainText().strip()
- if keyword == "EZ pauschal":
- # For EZ pauschals, calculate end date as start + 4 weeks
- start_dt = datetime.fromisoformat(start_date)
- end_dt = start_dt + relativedelta(years = 2, days = -1)
- end_date = end_dt.strftime("%Y-%m-%d")
+ if EventTypeHandler.should_hide_end_date_input(keyword):
+ # For EZ pauschals, calculate end date automatically
+ start_dt = DateService.parse_date_from_string(start_date)
+ end_dt = EventTypeHandler.get_duration_for_type(keyword, start_dt)
+ end_date = DateService.format_date_for_iso(end_dt)
else:
- end_date = self.end_date.date().toString("yyyy-MM-dd")
+ end_date = DateService.format_date_for_iso(self.end_date.date())
return start_date, end_date, keyword, commentary
@@ -166,16 +167,14 @@ class CalendarManagerGUI(QMainWindow):
# Get system locale for consistent date formatting
self.locale = QLocale.system()
- self.dateformat = DATEFORMAT
+ self.dateformat = EventConfig.DATE_FORMAT
# Initialize backend components
- self.keyword_list = ["EZ 100%", "EZ 50%", "EZ pauschal", "Sonstige"]
self.calendar_manager = CalendarManager()
self.date_calculator = DateCalculator()
self.prediction_controller = PredictionController(
self.calendar_manager,
- self.date_calculator,
- self.keyword_list
+ self.date_calculator
)
self.init_ui()
@@ -314,10 +313,16 @@ class CalendarManagerGUI(QMainWindow):
print(f"Error calculating prediction: {str(e)}")
def add_event(self):
- dialog = EventDialog(self.keyword_list, parent=self, dateformat=self.dateformat)
+ dialog = EventDialog(parent=self)
if dialog.exec_():
start_date, end_date, keyword, commentary = dialog.get_data()
try:
+ # Validate data before adding
+ errors = self.calendar_manager.validate_entry_data(start_date, end_date, keyword)
+ if errors:
+ QMessageBox.warning(self, "Validation Error", "\n".join(errors))
+ return
+
self.calendar_manager.add_entry(start_date, end_date, keyword, commentary)
self.update_events_table()
self.update_prediction() # Auto-update prediction
@@ -327,15 +332,17 @@ class CalendarManagerGUI(QMainWindow):
def modify_event(self, event_id):
entry = self.calendar_manager.get_entry_by_id(event_id)
if entry:
- dialog = EventDialog(self.keyword_list, entry=entry, parent=self, dateformat=self.dateformat)
+ dialog = EventDialog(entry=entry, parent=self)
if dialog.exec_():
start_date, end_date, keyword, commentary = dialog.get_data()
try:
- self.calendar_manager.modify_entry(event_id,
- datetime.fromisoformat(start_date),
- datetime.fromisoformat(end_date),
- keyword,
- commentary)
+ # Validate data before modifying
+ errors = self.calendar_manager.validate_entry_data(start_date, end_date, keyword)
+ if errors:
+ QMessageBox.warning(self, "Validation Error", "\n".join(errors))
+ return
+
+ self.calendar_manager.modify_entry(event_id, start_date, end_date, keyword, commentary)
self.update_events_table()
self.update_prediction() # Auto-update prediction
except Exception as e:
@@ -366,32 +373,14 @@ class CalendarManagerGUI(QMainWindow):
self.events_table.setItem(i, 0, QTableWidgetItem(entry.id))
# Format dates using unified display format
- start_date_qdate = QDate(entry.start_date.year, entry.start_date.month, entry.start_date.day)
- end_date_qdate = QDate(entry.end_date.year, entry.end_date.month, entry.end_date.day)
-
- start_date_text = start_date_qdate.toString(self.dateformat)
- end_date_text = end_date_qdate.toString(self.dateformat)
+ start_date_text = DateService.format_date_for_display(entry.start_date, self.dateformat)
+ end_date_text = DateService.format_date_for_display(entry.end_date, self.dateformat)
self.events_table.setItem(i, 1, QTableWidgetItem(start_date_text))
self.events_table.setItem(i, 2, QTableWidgetItem(end_date_text))
self.events_table.setItem(i, 3, QTableWidgetItem(entry.keyword))
- # Relevant accounted time based on corrected dates
- relevant_text = ""
- if entry.corrected_start_date and entry.corrected_end_date:
- start_dt = entry.corrected_start_date
- end_dt = entry.corrected_end_date
- if end_dt < start_dt:
- continue
- delta_days = (end_dt.date() - start_dt.date()).days + 1
- # Determine if less than 3 months using relativedelta
- rd = relativedelta(end_dt.date(), start_dt.date())
- total_months = rd.years * 12 + rd.months + 1
- if entry.keyword == "Sonstige":
- relevant_text = f"{delta_days} Tage"
- else:
- if entry.keyword == "EZ 50%":
- total_months = math.ceil(total_months / 2)
- relevant_text = f"{total_months} Monate"
+ # Relevant accounted time from stored time_period
+ relevant_text = getattr(entry, 'time_period', "") or ""
self.events_table.setItem(i, 4, QTableWidgetItem(relevant_text))
# Commentary
@@ -420,29 +409,35 @@ class CalendarManagerGUI(QMainWindow):
def save_file(self):
"""Save calendar entries to a JSON file"""
- # if not self.calendar_manager.filename:
- file_path, _ = QFileDialog.getSaveFileName(self, "Einträge speichern", "", "JSON Files (*.json)")
+ file_path, _ = QFileDialog.getSaveFileName(self, "Einträge speichern", "", EventConfig.FILE_FILTER)
if not file_path:
return
+
+ # Ensure .json extension
+ file_path = FileService.ensure_json_extension(file_path)
self.calendar_manager.switch_file(file_path)
try:
- self.calendar_manager.save_entries()
- QMessageBox.information(self, "Speichern erfolgreich", f"Einträge gespeichert in {self.calendar_manager.filename}")
+ if self.calendar_manager.save_entries():
+ QMessageBox.information(self, "Speichern erfolgreich", f"Einträge gespeichert in {self.calendar_manager.filename}")
+ else:
+ QMessageBox.critical(self, "Error", "Failed to save calendar entries")
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to save calendar: {str(e)}")
def load_file(self):
"""Load calendar entries from a JSON file"""
- file_path, _ = QFileDialog.getOpenFileName(self, "Einträge laden", "", "JSON Files (*.json)")
+ file_path, _ = QFileDialog.getOpenFileName(self, "Einträge laden", "", EventConfig.FILE_FILTER)
if not file_path:
return
try:
- self.calendar_manager.load_file(file_path)
- self.update_events_table()
- self.update_prediction() # Auto-update prediction
- QMessageBox.information(self, "Laden erfolgreich", f"Einträge erfolgreich von {file_path} geladen")
+ if self.calendar_manager.load_file(file_path):
+ self.update_events_table()
+ self.update_prediction() # Auto-update prediction
+ QMessageBox.information(self, "Laden erfolgreich", f"Einträge erfolgreich von {file_path} geladen")
+ else:
+ QMessageBox.warning(self, "Warning", "No entries loaded from file")
except Exception as e:
QMessageBox.critical(self, "Error", f"Failed to load calendar: {str(e)}")