diff options
| author | Kaufmann <Kau@avh.de> | 2025-04-02 11:43:00 +0200 |
|---|---|---|
| committer | Kaufmann <Kau@avh.de> | 2025-04-02 11:43:00 +0200 |
| commit | 4bbc79b052dd6edfbf6802e81cf043111ea038cb (patch) | |
| tree | 39a14059ebed6e614ebc28bc2c311eb50f73d80e /calendar_gui.py | |
| parent | ddc6244aa83aa286417af889e2c4ae146be2915c (diff) | |
Initialer Status (neue GUI) 1.4.25
Diffstat (limited to 'calendar_gui.py')
| -rw-r--r-- | calendar_gui.py | 273 |
1 files changed, 103 insertions, 170 deletions
diff --git a/calendar_gui.py b/calendar_gui.py index 7aeb159..c111db5 100644 --- a/calendar_gui.py +++ b/calendar_gui.py @@ -3,93 +3,102 @@ from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QH QLabel, QLineEdit, QPushButton, QDateEdit, QTableWidget, QTableWidgetItem, QHeaderView, QDialog, QFormLayout, QComboBox, QMessageBox, QSpinBox, QAction, QFileDialog, QMenuBar) -from PyQt5.QtCore import Qt, QDate, QLocale -from PyQt5.QtGui import QFont, QFontDatabase +from PyQt5.QtCore import Qt, QDate +from PyQt5.QtGui import QFont 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 -class EventDialog(QDialog): - def __init__(self, keyword_list, entry=None, parent=None): +class AddEventDialog(QDialog): + def __init__(self, keyword_list, parent=None): super().__init__(parent) - + self.setWindowTitle("Add New Event") self.keyword_list = keyword_list - self.entry = entry - - # Set title based on mode - self.setWindowTitle("Neuer Eintrag" if not entry else "Eintrag editieren") self.init_ui() def init_ui(self): layout = QFormLayout() - # Apply Arial font - font = QFont("Arial", 12) - self.setFont(font) - # Start date selector self.start_date = QDateEdit() self.start_date.setCalendarPopup(True) - self.start_date.setFont(font) + self.start_date.setDate(QDate.currentDate()) + layout.addRow("Start Date:", self.start_date) + + # End date selector + self.end_date = QDateEdit() + self.end_date.setCalendarPopup(True) + self.end_date.setDate(QDate.currentDate().addDays(1)) + layout.addRow("End Date:", self.end_date) + + # Keyword selector + self.keyword = QComboBox() + self.keyword.addItems(self.keyword_list) + layout.addRow("Keyword:", self.keyword) + + # Buttons + button_layout = QHBoxLayout() + self.save_button = QPushButton("Save") + self.save_button.clicked.connect(self.accept) + self.cancel_button = QPushButton("Cancel") + self.cancel_button.clicked.connect(self.reject) - # Set initial date based on mode - if self.entry: - entry_start = QDate(self.entry.start_date.year, - self.entry.start_date.month, - self.entry.start_date.day) - self.start_date.setDate(entry_start) - else: - self.start_date.setDate(QDate.currentDate()) - + button_layout.addWidget(self.save_button) + button_layout.addWidget(self.cancel_button) + layout.addRow("", button_layout) - # Connect start date change to validate end date - self.start_date.dateChanged.connect(self.validate_end_date) + self.setLayout(layout) - layout.addRow("Startdatum:", self.start_date) + def get_data(self): + start_date = self.start_date.date().toString("yyyy-MM-dd") + end_date = self.end_date.date().toString("yyyy-MM-dd") + keyword = self.keyword.currentText() + + return start_date, end_date, keyword + + +class ModifyEventDialog(QDialog): + def __init__(self, entry, keyword_list, parent=None): + super().__init__(parent) + self.setWindowTitle("Modify Event") + self.entry = entry + self.keyword_list = keyword_list + self.init_ui() + + def init_ui(self): + layout = QFormLayout() + + # Start date selector + self.start_date = QDateEdit() + self.start_date.setCalendarPopup(True) + entry_start = QDate(self.entry.start_date.year, + self.entry.start_date.month, + self.entry.start_date.day) + self.start_date.setDate(entry_start) + layout.addRow("Start Date:", self.start_date) # End date selector self.end_date = QDateEdit() self.end_date.setCalendarPopup(True) - self.end_date.setFont(font) - - # Set initial date based on mode - if self.entry: - entry_end = QDate(self.entry.end_date.year, - self.entry.end_date.month, - self.entry.end_date.day) - self.end_date.setDate(entry_end) - else: - self.end_date.setDate(QDate.currentDate().addDays(1)) - - layout.addRow("Enddatum:", self.end_date) + entry_end = QDate(self.entry.end_date.year, + self.entry.end_date.month, + self.entry.end_date.day) + self.end_date.setDate(entry_end) + layout.addRow("End Date:", self.end_date) # Keyword selector self.keyword = QComboBox() - self.keyword.setFont(font) self.keyword.addItems(self.keyword_list) - - # 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) - self.keyword.setCurrentIndex(current_index) - - self.keyword.currentTextChanged.connect(self.on_keyword_changed) - layout.addRow("Art:", self.keyword) - - # Store layout for later access - self.layout = layout - self.end_date_row = 1 # Index of end date row in the form layout + current_index = self.keyword_list.index(self.entry.keyword) if self.entry.keyword in self.keyword_list else 0 + self.keyword.setCurrentIndex(current_index) + layout.addRow("Keyword:", self.keyword) # Buttons button_layout = QHBoxLayout() - self.save_button = QPushButton("Speichern") - self.save_button.setFont(font) + self.save_button = QPushButton("Save") self.save_button.clicked.connect(self.accept) - - self.cancel_button = QPushButton("Abbrechen") - self.cancel_button.setFont(font) + self.cancel_button = QPushButton("Cancel") self.cancel_button.clicked.connect(self.reject) button_layout.addWidget(self.save_button) @@ -98,62 +107,22 @@ class EventDialog(QDialog): self.setLayout(layout) - # Handle initial keyword selection - self.on_keyword_changed(self.keyword.currentText()) - - def on_keyword_changed(self, keyword): - """Handle visibility of the end_date field based on keyword""" - # Get the widgets from the form layout - 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 - 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) - self.end_date.setDate(QDate(end_dt.year, end_dt.month, end_dt.day)) - else: - # Show end date field for other event types - end_date_label.setVisible(True) - end_date_field.setVisible(True) - - def validate_end_date(self): - """Ensure end date is not before start date""" - 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") + end_date = self.end_date.date().toString("yyyy-MM-dd") keyword = self.keyword.currentText() - 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") - else: - end_date = self.end_date.date().toString("yyyy-MM-dd") return start_date, end_date, keyword class CalendarManagerGUI(QMainWindow): def __init__(self): super().__init__() - self.setWindowTitle("Ausfallzeitenrechner") + self.setWindowTitle("Calendar Manager") self.setMinimumSize(800, 600) - # Set application font - self.app_font = QFont("Arial", 12) - QApplication.setFont(self.app_font) - - # Get system locale for consistent date formatting - self.locale = QLocale.system() - # Initialize backend components - self.keyword_list = ["EZ 100%", "EZ 50%", "EZ pauschal", "Sonstige"] + self.keyword_list = ["full_project", "half_project", "event"] self.calendar_manager = CalendarManager() self.date_calculator = DateCalculator() self.prediction_controller = PredictionController( @@ -168,7 +137,6 @@ class CalendarManagerGUI(QMainWindow): def create_menus(self): # Create menu bar menubar = self.menuBar() - menubar.setFont(self.app_font) # File menu file_menu = menubar.addMenu('File') @@ -197,7 +165,10 @@ class CalendarManagerGUI(QMainWindow): exit_action.triggered.connect(self.close) file_menu.addAction(exit_action) - def init_ui(self): + def init_ui(self): + self.setWindowTitle('Calendar Manager GUI') + self.setMinimumSize(800, 600) + central_widget = QWidget() main_layout = QVBoxLayout() @@ -205,10 +176,8 @@ class CalendarManagerGUI(QMainWindow): # Launch date input launch_date_layout = QVBoxLayout() - launch_date_label = QLabel("Promotionsdatum:") - launch_date_label.setFont(self.app_font) + launch_date_label = QLabel("Launch Date:") self.launch_date_edit = QDateEdit() - self.launch_date_edit.setFont(self.app_font) self.launch_date_edit.setCalendarPopup(True) # Enable calendar popup self.launch_date_edit.setDate(QDate.currentDate()) self.launch_date_edit.dateChanged.connect(self.update_prediction) # Auto-update on change @@ -218,10 +187,8 @@ class CalendarManagerGUI(QMainWindow): # Duration input duration_layout = QVBoxLayout() - duration_label = QLabel("Bewerbungszeitraum (Jahre):") - duration_label.setFont(self.app_font) + duration_label = QLabel("Duration (years):") self.duration_spin = QSpinBox() - self.duration_spin.setFont(self.app_font) self.duration_spin.setRange(1, 99) self.duration_spin.setValue(1) self.duration_spin.valueChanged.connect(self.update_prediction) # Auto-update on change @@ -231,10 +198,8 @@ class CalendarManagerGUI(QMainWindow): # Prediction result prediction_result_layout = QVBoxLayout() - prediction_result_label = QLabel("Bewerbungsfrist:") - prediction_result_label.setFont(self.app_font) + prediction_result_label = QLabel("Predicted Completion Date:") self.prediction_result = QDateEdit() - self.prediction_result.setFont(self.app_font) self.prediction_result.setReadOnly(True) self.prediction_result.setButtonSymbols(QDateEdit.ButtonSymbols.NoButtons) prediction_result_layout.addWidget(prediction_result_label) @@ -246,23 +211,19 @@ class CalendarManagerGUI(QMainWindow): # Events section events_layout = QVBoxLayout() - events_title = QLabel("<h3>Ausfallzeiten</h3>") - events_title.setFont(self.app_font) + events_title = QLabel("<h3>Calendar Events</h3>") events_layout.addWidget(events_title) # Add event button - add_event_button = QPushButton("Eintrag hinzufügen") - add_event_button.setFont(self.app_font) + add_event_button = QPushButton("Add Event") add_event_button.clicked.connect(self.add_event) events_layout.addWidget(add_event_button) # Events table self.events_table = QTableWidget() - self.events_table.setFont(self.app_font) self.events_table.setColumnCount(7) # ID (hidden), Start, End, Keyword, CorrectedStart, CorrectedEnd, Actions - self.events_table.setHorizontalHeaderLabels(["ID", "Anfangsdatum", "Enddatum", "Art", "Korr. Start", "Korr. Ende", "Aktionen"]) + self.events_table.setHorizontalHeaderLabels(["ID", "Start Date", "End Date", "Keyword", "Corrected Start", "Corrected End", "Actions"]) self.events_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) - self.events_table.horizontalHeader().setFont(self.app_font) self.events_table.setColumnHidden(0, True) # Hide ID column events_layout.addWidget(self.events_table) @@ -296,7 +257,7 @@ class CalendarManagerGUI(QMainWindow): print(f"Error calculating prediction: {str(e)}") def add_event(self): - dialog = EventDialog(self.keyword_list, parent=self) + dialog = AddEventDialog(self.keyword_list, self) if dialog.exec_(): start_date, end_date, keyword = dialog.get_data() try: @@ -309,7 +270,7 @@ 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) + dialog = ModifyEventDialog(entry, self.keyword_list, self) if dialog.exec_(): start_date, end_date, keyword = dialog.get_data() try: @@ -323,8 +284,8 @@ class CalendarManagerGUI(QMainWindow): QMessageBox.critical(self, "Error", f"Error modifying event: {str(e)}") def delete_event(self, event_id): - reply = QMessageBox.question(self, "Eintrag löschen", - "Wollen Sie diesen Eintrag löschen?", + reply = QMessageBox.question(self, "Delete Event", + "Are you sure you want to delete this event?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: try: @@ -345,49 +306,23 @@ class CalendarManagerGUI(QMainWindow): # Set item data self.events_table.setItem(i, 0, QTableWidgetItem(entry.id)) - - # Format dates using system locale for display - 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 = self.locale.toString(start_date_qdate, QLocale.ShortFormat) - end_date_text = self.locale.toString(end_date_qdate, QLocale.ShortFormat) - 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, 1, QTableWidgetItem(entry.start_date.strftime("%Y-%m-%d"))) + self.events_table.setItem(i, 2, QTableWidgetItem(entry.end_date.strftime("%Y-%m-%d"))) self.events_table.setItem(i, 3, QTableWidgetItem(entry.keyword)) - # Corrected dates with system locale formatting - if entry.corrected_start_date: - corrected_start_qdate = QDate( - entry.corrected_start_date.year, - entry.corrected_start_date.month, - entry.corrected_start_date.day - ) - corrected_start_text = self.locale.toString(corrected_start_qdate, QLocale.ShortFormat) - else: - corrected_start_text = "" - - if entry.corrected_end_date: - corrected_end_qdate = QDate( - entry.corrected_end_date.year, - entry.corrected_end_date.month, - entry.corrected_end_date.day - ) - corrected_end_text = self.locale.toString(corrected_end_qdate, QLocale.ShortFormat) - else: - corrected_end_text = "" - self.events_table.setItem(i, 4, QTableWidgetItem(corrected_start_text)) - self.events_table.setItem(i, 5, QTableWidgetItem(corrected_end_text)) + # Corrected dates + corrected_start = entry.corrected_start_date.strftime("%Y-%m-%d") if entry.corrected_start_date else "" + corrected_end = entry.corrected_end_date.strftime("%Y-%m-%d") if entry.corrected_end_date else "" + self.events_table.setItem(i, 4, QTableWidgetItem(corrected_start)) + self.events_table.setItem(i, 5, QTableWidgetItem(corrected_end)) # Action buttons actions_widget = QWidget() actions_layout = QHBoxLayout() actions_layout.setContentsMargins(0, 0, 0, 0) - modify_button = QPushButton("Editieren") - modify_button.setFont(self.app_font) - delete_button = QPushButton("Löschen") - delete_button.setFont(self.app_font) + modify_button = QPushButton("Modify") + delete_button = QPushButton("Delete") # Use lambda with default argument to capture the correct event_id modify_button.clicked.connect(lambda checked, eid=entry.id: self.modify_event(eid)) @@ -401,21 +336,21 @@ 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)") - if not file_path: - return - self.calendar_manager.switch_file(file_path) + if not self.calendar_manager.filename: + file_path, _ = QFileDialog.getSaveFileName(self, "Save Calendar", "", "JSON Files (*.json)") + if not file_path: + return + 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}") + QMessageBox.information(self, "Save Successful", f"Calendar saved to {self.calendar_manager.filename}") 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, "Load Calendar", "", "JSON Files (*.json)") if not file_path: return @@ -423,21 +358,21 @@ class CalendarManagerGUI(QMainWindow): 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") + QMessageBox.information(self, "Load Successful", f"Calendar loaded from {file_path}") except Exception as e: QMessageBox.critical(self, "Error", f"Failed to load calendar: {str(e)}") def clear_entries(self): """Clear all calendar entries""" - reply = QMessageBox.question(self, "Einträge löschen", - "Alle Einträge löschen?", + reply = QMessageBox.question(self, "Clear Calendar", + "Are you sure you want to clear all events?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: try: self.calendar_manager.clear_entries() self.update_events_table() self.update_prediction() # Auto-update prediction - QMessageBox.information(self, "Erfolg", "Alle Einträge gelöscht!") + QMessageBox.information(self, "Success", "Calendar cleared successfully") except Exception as e: QMessageBox.critical(self, "Error", f"Failed to clear calendar: {str(e)}") @@ -445,8 +380,6 @@ class CalendarManagerGUI(QMainWindow): def main(): app = QApplication(sys.argv) app.setStyle('Fusion') - # Ensure Arial is available - QFontDatabase.addApplicationFont("Arial") window = CalendarManagerGUI() window.show() sys.exit(app.exec_()) |
