From 6fbfb10d643f0e3e6f507d2dd6fd421364bfc5a1 Mon Sep 17 00:00:00 2001 From: Lea Laux Date: Mon, 1 Mar 2021 13:16:28 +0100 Subject: [PATCH] Check for unsaved content in editor before closing Check for unsaved content in the editor widget/query input editor before closing the editor and the main window, still todo: Documentation in main window/mdi area --- pygadmin/widgets/editor.py | 67 ++++++++++++++++++++++++++++++++- pygadmin/widgets/main_window.py | 17 +++++---- pygadmin/widgets/mdi_area.py | 21 +++++++++++ 3 files changed, 97 insertions(+), 8 deletions(-) diff --git a/pygadmin/widgets/editor.py b/pygadmin/widgets/editor.py index b2f2b57..33c80d3 100644 --- a/pygadmin/widgets/editor.py +++ b/pygadmin/widgets/editor.py @@ -1124,15 +1124,80 @@ class EditorWidget(QWidget, SearchReplaceParent, metaclass=MetaEditor): # Execute the query with the database query executor and the editor execution process. self.execute_current_query(query) + def check_for_unsaved_changes(self): + """ + Check for unsaved changes in the query input editor. + """ + + # Check for a text in the editor. If the text is an empty string, nothing happened. + if self.query_input_editor.text() == "": + # Return False, because there are no unsaved changes. + return False + + # Check for existence the corresponding saved file. At this point, there is a text in the editor. + if self.corresponding_saved_file is None: + # Return True, because the text in the editor is not saved in the file. + return True + + # Get the file save status. If the status is not empty, there is an unsaved change. + if self.get_file_save_status_string_for_window_title() != "": + # Return True for an unsaved change. + return True + + # If this point is reached, there are no unsaved changes. + return False + + def warn_about_unsaved_changes(self): + """ + Warn the user about unsaved changes in the editor. The function is normally called before a closing event is + processed. + """ + + # Warn the user about unsaved content and ask how to proceed. + question_message_box = QMessageBox.question(self, "Unsaved Content", "The content in the editor is not saved in" + "a file. Do you still want to close the " + "editor and loose the current content? " + "(Ignore for ignoring these warnings in " + "the future)", + QMessageBox.Yes | QMessageBox.No | QMessageBox.Ignore) + + # Proceed normally for a yes. + if question_message_box == QMessageBox.Yes: + return True + + # Stop the process for a no. + elif question_message_box == QMessageBox.No: + return False + + # Proceed with setting the configuration and normally for an ignore. + elif question_message_box == QMessageBox.Ignore: + global_app_configurator.set_single_configuration("check_unsaved_files", False) + global_app_configurator.save_configuration_data() + return True + def closeEvent(self, a0: QtGui.QCloseEvent) -> None: """ Overwrite the close event: If the configuration for opening the previous is set and the corresponding save file exists, delete it from the file manager, because it does not have to be opened after a restart of the program. + a0 is the event, which can be accepted or ignored. """ + # Check for an existing file, which should be opened at the next start. if self.corresponding_saved_file is not None \ and global_app_configurator.get_single_configuration("open_previous_files") is True: global_file_manager.delete_file(self.corresponding_saved_file) global_file_manager.commit_current_files_to_yaml() - self.close() + # Check for unsaved changes and the current configuration for processing them. + if self.check_for_unsaved_changes() and global_app_configurator.get_single_configuration("check_unsaved_files")\ + is not False: + # Get the user's opinion about the closing process. + close_anyway = self.warn_about_unsaved_changes() + + # If the user does not want to close the editor, ignore the event and end the function. + if close_anyway is not True: + a0.ignore() + return + + # Accept the close event and close the widget. + a0.accept() diff --git a/pygadmin/widgets/main_window.py b/pygadmin/widgets/main_window.py index 54cecd6..72e8fa0 100644 --- a/pygadmin/widgets/main_window.py +++ b/pygadmin/widgets/main_window.py @@ -1,7 +1,7 @@ import os import logging -from PyQt5 import QtCore +from PyQt5 import QtCore, QtGui from PyQt5.QtGui import QIcon, QPixmap, QKeySequence from PyQt5.QtWidgets import QMainWindow, QAction, QToolBar, QMessageBox, QMenu, QFileDialog, QShortcut from PyQt5.QtCore import Qt, pyqtSlot @@ -159,7 +159,7 @@ class MainWindow(QMainWindow): alternate_menu=settings_menu) # Add an action for leaving the application. - self.add_action_to_menu_bar("Exit", self.close_program) + self.add_action_to_menu_bar("Exit", self.close) # Create a new menu bar point: An editor menu. editor_menu = self.menu_bar.addMenu("Editor") @@ -554,9 +554,12 @@ class MainWindow(QMainWindow): # empty editor with this command. self.command_history_dialog.get_double_click_command.connect(self.load_empty_editor_with_command) - def close_program(self): - """ - Define a wrapper function for closing the application. - """ + def closeEvent(self, a0: QtGui.QCloseEvent) -> None: + # TODO: Docu + if global_app_configurator.get_single_configuration("check_unsaved_files") is not False \ + and self.mdi_area.check_for_unsaved_editor_tabs() is True: + a0.ignore() + return + + a0.accept() - self.close() diff --git a/pygadmin/widgets/mdi_area.py b/pygadmin/widgets/mdi_area.py index 83886d9..e005851 100644 --- a/pygadmin/widgets/mdi_area.py +++ b/pygadmin/widgets/mdi_area.py @@ -304,3 +304,24 @@ class MdiArea(QMdiArea): # None will be returned, if the search for a currently existing empty editor widget is unsuccessful. return None + + def check_for_unsaved_editor_tabs(self): + # TODO: Docu + unsaved_changes = False + + editor_widget_list = [sub_window.widget() for sub_window in self.subWindowList() + if isinstance(sub_window.widget(), EditorWidget)] + + for editor_widget in editor_widget_list: + if editor_widget.check_for_unsaved_changes() is True: + close_anyway = editor_widget.warn_about_unsaved_changes() + + if close_anyway is True: + unsaved_changes = False + + else: + unsaved_changes = True + + break + + return unsaved_changes