From 793667291457380a0341f2ce7f3d25934de56b5b Mon Sep 17 00:00:00 2001 From: matin Date: Mon, 21 Apr 2025 18:06:36 +0200 Subject: first try to add commentary and save functionalities by Claude --- calendar_gui.py | 776 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 388 insertions(+), 388 deletions(-) (limited to 'calendar_gui.py') diff --git a/calendar_gui.py b/calendar_gui.py index c111db5..ef2f359 100644 --- a/calendar_gui.py +++ b/calendar_gui.py @@ -1,389 +1,389 @@ -import sys -from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, - QLabel, QLineEdit, QPushButton, QDateEdit, QTableWidget, - QTableWidgetItem, QHeaderView, QDialog, QFormLayout, QComboBox, - QMessageBox, QSpinBox, QAction, QFileDialog, QMenuBar) -from PyQt5.QtCore import Qt, QDate -from PyQt5.QtGui import QFont -from datetime import datetime, timedelta -from calendar_manager import CalendarManager -from date_calculator import DateCalculator -from prediction_controller import PredictionController - -class AddEventDialog(QDialog): - def __init__(self, keyword_list, parent=None): - super().__init__(parent) - self.setWindowTitle("Add New Event") - 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) - 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) - - button_layout.addWidget(self.save_button) - button_layout.addWidget(self.cancel_button) - layout.addRow("", button_layout) - - self.setLayout(layout) - - 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) - 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.addItems(self.keyword_list) - 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("Save") - self.save_button.clicked.connect(self.accept) - self.cancel_button = QPushButton("Cancel") - self.cancel_button.clicked.connect(self.reject) - - button_layout.addWidget(self.save_button) - button_layout.addWidget(self.cancel_button) - layout.addRow("", button_layout) - - self.setLayout(layout) - - 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 CalendarManagerGUI(QMainWindow): - def __init__(self): - super().__init__() - self.setWindowTitle("Calendar Manager") - self.setMinimumSize(800, 600) - - # Initialize backend components - self.keyword_list = ["full_project", "half_project", "event"] - self.calendar_manager = CalendarManager() - self.date_calculator = DateCalculator() - self.prediction_controller = PredictionController( - self.calendar_manager, - self.date_calculator, - self.keyword_list - ) - - self.init_ui() - self.create_menus() - - def create_menus(self): - # Create menu bar - menubar = self.menuBar() - - # File menu - file_menu = menubar.addMenu('File') - - # Save action - save_action = QAction('Save', self) - save_action.setShortcut('Ctrl+S') - save_action.triggered.connect(self.save_file) - file_menu.addAction(save_action) - - # Load action - load_action = QAction('Load', self) - load_action.setShortcut('Ctrl+O') - load_action.triggered.connect(self.load_file) - file_menu.addAction(load_action) - - # Clear action - clear_action = QAction('Clear', self) - clear_action.setShortcut('Ctrl+N') - clear_action.triggered.connect(self.clear_entries) - file_menu.addAction(clear_action) - - # Exit action - exit_action = QAction('Exit', self) - exit_action.setShortcut('Ctrl+Q') - exit_action.triggered.connect(self.close) - file_menu.addAction(exit_action) - - def init_ui(self): - self.setWindowTitle('Calendar Manager GUI') - self.setMinimumSize(800, 600) - - central_widget = QWidget() - main_layout = QVBoxLayout() - - top_layout = QHBoxLayout() - - # Launch date input - launch_date_layout = QVBoxLayout() - launch_date_label = QLabel("Launch Date:") - self.launch_date_edit = QDateEdit() - 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 - launch_date_layout.addWidget(launch_date_label) - launch_date_layout.addWidget(self.launch_date_edit) - top_layout.addLayout(launch_date_layout) - - # Duration input - duration_layout = QVBoxLayout() - duration_label = QLabel("Duration (years):") - self.duration_spin = QSpinBox() - self.duration_spin.setRange(1, 99) - self.duration_spin.setValue(1) - self.duration_spin.valueChanged.connect(self.update_prediction) # Auto-update on change - duration_layout.addWidget(duration_label) - duration_layout.addWidget(self.duration_spin) - top_layout.addLayout(duration_layout) - - # Prediction result - prediction_result_layout = QVBoxLayout() - prediction_result_label = QLabel("Predicted Completion Date:") - self.prediction_result = QDateEdit() - self.prediction_result.setReadOnly(True) - self.prediction_result.setButtonSymbols(QDateEdit.ButtonSymbols.NoButtons) - prediction_result_layout.addWidget(prediction_result_label) - prediction_result_layout.addWidget(self.prediction_result) - - top_layout.addLayout(prediction_result_layout) - - main_layout.addLayout(top_layout) - - # Events section - events_layout = QVBoxLayout() - events_title = QLabel("

Calendar Events

") - events_layout.addWidget(events_title) - - # Add event button - 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.setColumnCount(7) # ID (hidden), Start, End, Keyword, CorrectedStart, CorrectedEnd, Actions - 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.setColumnHidden(0, True) # Hide ID column - events_layout.addWidget(self.events_table) - - main_layout.addLayout(events_layout) - - # Set main layout - central_widget.setLayout(main_layout) - self.setCentralWidget(central_widget) - - # Load initial data - self.update_events_table() - self.update_prediction() # Calculate initial prediction - - def update_prediction(self): - """Update prediction whenever needed""" - try: - launch_date = self.launch_date_edit.date().toString("yyyy-MM-dd") - duration_years = self.duration_spin.value() - - self.prediction_controller.make_prediction(launch_date, duration_years) - prediction_date = self.prediction_controller.get_prediction() - - if prediction_date: - self.prediction_result.setDate(prediction_date) - - # Update table to show corrected dates - self.update_events_table() - - except Exception as e: - self.prediction_result.setText("Error in calculation") - print(f"Error calculating prediction: {str(e)}") - - def add_event(self): - dialog = AddEventDialog(self.keyword_list, self) - if dialog.exec_(): - start_date, end_date, keyword = dialog.get_data() - try: - self.calendar_manager.add_entry(start_date, end_date, keyword) - self.update_events_table() - self.update_prediction() # Auto-update prediction - except Exception as e: - QMessageBox.critical(self, "Error", f"Error adding event: {str(e)}") - - def modify_event(self, event_id): - entry = self.calendar_manager.get_entry_by_id(event_id) - if entry: - dialog = ModifyEventDialog(entry, self.keyword_list, self) - if dialog.exec_(): - start_date, end_date, keyword = dialog.get_data() - try: - self.calendar_manager.modify_entry(event_id, - datetime.fromisoformat(start_date), - datetime.fromisoformat(end_date), - keyword) - self.update_events_table() - self.update_prediction() # Auto-update prediction - except Exception as e: - QMessageBox.critical(self, "Error", f"Error modifying event: {str(e)}") - - def delete_event(self, event_id): - reply = QMessageBox.question(self, "Delete Event", - "Are you sure you want to delete this event?", - QMessageBox.Yes | QMessageBox.No) - if reply == QMessageBox.Yes: - try: - self.calendar_manager.delete_entry(event_id) - self.update_events_table() - self.update_prediction() # Auto-update prediction - except Exception as e: - QMessageBox.critical(self, "Error", f"Error deleting event: {str(e)}") - - def update_events_table(self): - # Clear table - self.events_table.setRowCount(0) - - # Add entries to table - entries = self.calendar_manager.list_entries() - for i, entry in enumerate(entries): - self.events_table.insertRow(i) - - # Set item data - self.events_table.setItem(i, 0, QTableWidgetItem(entry.id)) - 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 - 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("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)) - delete_button.clicked.connect(lambda checked, eid=entry.id: self.delete_event(eid)) - - actions_layout.addWidget(modify_button) - actions_layout.addWidget(delete_button) - actions_widget.setLayout(actions_layout) - - self.events_table.setCellWidget(i, 6, actions_widget) - - def save_file(self): - """Save calendar entries to a JSON file""" - 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, "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, "Load Calendar", "", "JSON Files (*.json)") - 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, "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, "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, "Success", "Calendar cleared successfully") - except Exception as e: - QMessageBox.critical(self, "Error", f"Failed to clear calendar: {str(e)}") - - -def main(): - app = QApplication(sys.argv) - app.setStyle('Fusion') - window = CalendarManagerGUI() - window.show() - sys.exit(app.exec_()) - - -if __name__ == "__main__": +import sys +from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, + QLabel, QLineEdit, QPushButton, QDateEdit, QTableWidget, + QTableWidgetItem, QHeaderView, QDialog, QFormLayout, QComboBox, + QMessageBox, QSpinBox, QAction, QFileDialog, QMenuBar) +from PyQt5.QtCore import Qt, QDate +from PyQt5.QtGui import QFont +from datetime import datetime, timedelta +from calendar_manager import CalendarManager +from date_calculator import DateCalculator +from prediction_controller import PredictionController + +class AddEventDialog(QDialog): + def __init__(self, keyword_list, parent=None): + super().__init__(parent) + self.setWindowTitle("Add New Event") + 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) + 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) + + button_layout.addWidget(self.save_button) + button_layout.addWidget(self.cancel_button) + layout.addRow("", button_layout) + + self.setLayout(layout) + + 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) + 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.addItems(self.keyword_list) + 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("Save") + self.save_button.clicked.connect(self.accept) + self.cancel_button = QPushButton("Cancel") + self.cancel_button.clicked.connect(self.reject) + + button_layout.addWidget(self.save_button) + button_layout.addWidget(self.cancel_button) + layout.addRow("", button_layout) + + self.setLayout(layout) + + 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 CalendarManagerGUI(QMainWindow): + def __init__(self): + super().__init__() + self.setWindowTitle("Calendar Manager") + self.setMinimumSize(800, 600) + + # Initialize backend components + self.keyword_list = ["full_project", "half_project", "event"] + self.calendar_manager = CalendarManager() + self.date_calculator = DateCalculator() + self.prediction_controller = PredictionController( + self.calendar_manager, + self.date_calculator, + self.keyword_list + ) + + self.init_ui() + self.create_menus() + + def create_menus(self): + # Create menu bar + menubar = self.menuBar() + + # File menu + file_menu = menubar.addMenu('File') + + # Save action + save_action = QAction('Save', self) + save_action.setShortcut('Ctrl+S') + save_action.triggered.connect(self.save_file) + file_menu.addAction(save_action) + + # Load action + load_action = QAction('Load', self) + load_action.setShortcut('Ctrl+O') + load_action.triggered.connect(self.load_file) + file_menu.addAction(load_action) + + # Clear action + clear_action = QAction('Clear', self) + clear_action.setShortcut('Ctrl+N') + clear_action.triggered.connect(self.clear_entries) + file_menu.addAction(clear_action) + + # Exit action + exit_action = QAction('Exit', self) + exit_action.setShortcut('Ctrl+Q') + exit_action.triggered.connect(self.close) + file_menu.addAction(exit_action) + + def init_ui(self): + self.setWindowTitle('Calendar Manager GUI') + self.setMinimumSize(800, 600) + + central_widget = QWidget() + main_layout = QVBoxLayout() + + top_layout = QHBoxLayout() + + # Launch date input + launch_date_layout = QVBoxLayout() + launch_date_label = QLabel("Launch Date:") + self.launch_date_edit = QDateEdit() + 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 + launch_date_layout.addWidget(launch_date_label) + launch_date_layout.addWidget(self.launch_date_edit) + top_layout.addLayout(launch_date_layout) + + # Duration input + duration_layout = QVBoxLayout() + duration_label = QLabel("Duration (years):") + self.duration_spin = QSpinBox() + self.duration_spin.setRange(1, 99) + self.duration_spin.setValue(1) + self.duration_spin.valueChanged.connect(self.update_prediction) # Auto-update on change + duration_layout.addWidget(duration_label) + duration_layout.addWidget(self.duration_spin) + top_layout.addLayout(duration_layout) + + # Prediction result + prediction_result_layout = QVBoxLayout() + prediction_result_label = QLabel("Predicted Completion Date:") + self.prediction_result = QDateEdit() + self.prediction_result.setReadOnly(True) + self.prediction_result.setButtonSymbols(QDateEdit.ButtonSymbols.NoButtons) + prediction_result_layout.addWidget(prediction_result_label) + prediction_result_layout.addWidget(self.prediction_result) + + top_layout.addLayout(prediction_result_layout) + + main_layout.addLayout(top_layout) + + # Events section + events_layout = QVBoxLayout() + events_title = QLabel("

Calendar Events

") + events_layout.addWidget(events_title) + + # Add event button + 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.setColumnCount(7) # ID (hidden), Start, End, Keyword, CorrectedStart, CorrectedEnd, Actions + 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.setColumnHidden(0, True) # Hide ID column + events_layout.addWidget(self.events_table) + + main_layout.addLayout(events_layout) + + # Set main layout + central_widget.setLayout(main_layout) + self.setCentralWidget(central_widget) + + # Load initial data + self.update_events_table() + self.update_prediction() # Calculate initial prediction + + def update_prediction(self): + """Update prediction whenever needed""" + try: + launch_date = self.launch_date_edit.date().toString("yyyy-MM-dd") + duration_years = self.duration_spin.value() + + self.prediction_controller.make_prediction(launch_date, duration_years) + prediction_date = self.prediction_controller.get_prediction() + + if prediction_date: + self.prediction_result.setDate(prediction_date) + + # Update table to show corrected dates + self.update_events_table() + + except Exception as e: + self.prediction_result.setText("Error in calculation") + print(f"Error calculating prediction: {str(e)}") + + def add_event(self): + dialog = AddEventDialog(self.keyword_list, self) + if dialog.exec_(): + start_date, end_date, keyword = dialog.get_data() + try: + self.calendar_manager.add_entry(start_date, end_date, keyword) + self.update_events_table() + self.update_prediction() # Auto-update prediction + except Exception as e: + QMessageBox.critical(self, "Error", f"Error adding event: {str(e)}") + + def modify_event(self, event_id): + entry = self.calendar_manager.get_entry_by_id(event_id) + if entry: + dialog = ModifyEventDialog(entry, self.keyword_list, self) + if dialog.exec_(): + start_date, end_date, keyword = dialog.get_data() + try: + self.calendar_manager.modify_entry(event_id, + datetime.fromisoformat(start_date), + datetime.fromisoformat(end_date), + keyword) + self.update_events_table() + self.update_prediction() # Auto-update prediction + except Exception as e: + QMessageBox.critical(self, "Error", f"Error modifying event: {str(e)}") + + def delete_event(self, event_id): + reply = QMessageBox.question(self, "Delete Event", + "Are you sure you want to delete this event?", + QMessageBox.Yes | QMessageBox.No) + if reply == QMessageBox.Yes: + try: + self.calendar_manager.delete_entry(event_id) + self.update_events_table() + self.update_prediction() # Auto-update prediction + except Exception as e: + QMessageBox.critical(self, "Error", f"Error deleting event: {str(e)}") + + def update_events_table(self): + # Clear table + self.events_table.setRowCount(0) + + # Add entries to table + entries = self.calendar_manager.list_entries() + for i, entry in enumerate(entries): + self.events_table.insertRow(i) + + # Set item data + self.events_table.setItem(i, 0, QTableWidgetItem(entry.id)) + 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 + 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("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)) + delete_button.clicked.connect(lambda checked, eid=entry.id: self.delete_event(eid)) + + actions_layout.addWidget(modify_button) + actions_layout.addWidget(delete_button) + actions_widget.setLayout(actions_layout) + + self.events_table.setCellWidget(i, 6, actions_widget) + + def save_file(self): + """Save calendar entries to a JSON file""" + 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, "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, "Load Calendar", "", "JSON Files (*.json)") + 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, "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, "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, "Success", "Calendar cleared successfully") + except Exception as e: + QMessageBox.critical(self, "Error", f"Failed to clear calendar: {str(e)}") + + +def main(): + app = QApplication(sys.argv) + app.setStyle('Fusion') + window = CalendarManagerGUI() + window.show() + sys.exit(app.exec_()) + + +if __name__ == "__main__": main() \ No newline at end of file -- cgit v1.1