diff libgui/src/m-editor/file-editor-tab.cc @ 19714:21015ca26566

Restructure shutdown flow and behavior for improved robustness * file-editor-interface.h (file_editor_interface::check_closing): Remove closing_state argument from input. * file-editor-tab.cc (file_editor_tab::_cancelled): New static variable for managing chain of file closes. (file_editor_tab::file_editor_tab): Discard _app_closing and _modal_dialog initializations. (file_editor_tab::closeEvent): Upon accepting the close event, als request tab removal. (file_editor_tab::check_modified_file): New simple routine checking for modified file if there hasn't been cancellation yet. (file_editor_tab::run_file): Remove use of _modal_dialog. (file_editor_tab::show_dialog): Add modal input setting. Remove use of _app_closing and _modal_dialog. (file_editor_tab::check_file_modified): Remove situational message for just one. If modified, call show_dialog with modal true, return QMessageBox::Cancel if anything cancelled, otherwise the user decision. (file_editor_tab::handle_file_modified_answer): Do not remove file editor tab in any case. If user cancelled, set _cancelled true. (file_editor_tab::save_file): Add "false" (non-modal) to show_dialog() call. (file_editor_tab::save_file_as): Add "false" (non-modal) to show_dialog() call. (file_editor_tab::conditional_close): Remove input argument and use of variable _app_closing. * file-editor-tab.h (file_editor_tab::conditional_close): Remove input argument. (file_editor_tab::reset_cancel): New member function declaration for managing cancellation of tab chain saves. (file_editor_tab::was_cancel): New member function for indicating any cancellation when saving modified files. (file_editor_tab::check_modified_file): New slot declaration for checking and saving file modifications. (file_editor_tab::show_dialog): Add modal option input argument. (file_editor_tab::_app_closing, file_editor_tab::_modal_dialog): Remove. (file_editor_tab::_cancelled): Add. * file-editor.cc (file_editor::file_editor): Remove _check_closing_done initialization. (file_editor::~file_editor): Remove use of _check_closing_done and check_closing(). (file_editor::check_closing): Clear cancellation history and check all files for modifications, without closing. Close all tabs and delete associated widgets if no cancellation. Remove use of _check_closing_done. (file_editor::request_close_file): Remove argument from conditional_close() function call. (file_editor::request_close_all_files): Ditto. (file_editor::request_close_other_files): Ditto. (file_editor::handle_tab_close_request): Ditto. (file_editor::handle_tab_remove_request): Add comment about deleting sender. (file_editor::add_file_editor_tab): Connect fetab_check_modified_file signal to check_modified_file slot. * file-editor.h (file_editor::fetab_check_modified_file): New signal. (file_editor::check_closing): Remove input argument. (file_editor::_check_closing_done): Remove. * main-window.cc (main_window::confirm_shutdown_octave): Rename of member function main_window::confirm_exit_octave(). Change return type to void. Set octave/qt link confirmation result then awake worker process. (main_window::exit_app): Rename of member function main_window::exit(). (main_window::closeEvent): Rather than post callback event, queue "exit" in the command buffer. (main_window::construct_octave_qt_link): Connect confirm_shutdown_signal to confirm_shutdown_octave slot. Connect exit_app_signal to exit_app slot. (main_window::exit_callback): Remove. (main_window::confirm_exit_octave): Renamed as confirm_shutdown_octave(). * main-window.h (main_window::confirm_shutdown_octave): Rename of slot confirm_exit_octave(). (main_window::exit): Renamed exit_app(). (main_window::exit_callback): Removed declaration. (main_window::confirm_exit_octave): Renamed confirm_shutdown_octave(). * octave-qt-link.cc (octave_qt_link::do_confirm_shutdown): New virtual function definition for initiating GUI shutdown and confirm exit. Worker process goes into sleep mode after issuing cross-thread signal. Return confirmation result. (octave_qt_link::do_exit): Change exit_signal to exit_app_signal. octave-qt-link.h (octave_qt_link::do_confirm_shutdown): New virtual function declaration for qt GUI. (octave_qt_link::mutex): Added. A QMutex for communicating with Qt GUI. (octave_qt_link::waitcondition): Added. For process wait. (octave_qt_link::shutdown_confirmation): Added. Store confirmation result. (octave_qt_link::_shutdown_confirm_result): Added. Confirmation result. (octave_qt_link::exit_signal): Signal renamed exit_app_signal. (octave_qt_link::confirm_shutdown_signal): Added. (octave_qt_link::exit_app_signal): Renamed of exit_signal. octave-link.h (octave_link::confirm_shutdown): Added. Access virtual function do_confirm_shutdown. (octave_link::do_confirm_shutdown): Added. Virtual function for GUI link. toplev.cc (clean_up_and_exit): Change 'retval' to 'status', as header file uses argument name 'status'. (quit): First initiate GUI shutdown via octave_link::confirm_shutdown() and if not confirmed, immediately return thereby avoiding exit sequence.
author Daniel J Sebald <daniel.sebald@ieee.org>
date Sat, 14 Feb 2015 11:27:10 -0600
parents 4197fc428c7d
children 95a94c98c884
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-tab.cc	Sat Feb 14 09:32:57 2015 -0800
+++ b/libgui/src/m-editor/file-editor-tab.cc	Sat Feb 14 11:27:10 2015 -0600
@@ -63,15 +63,15 @@
 #include "defaults.h"
 #include <oct-map.h>
 
+bool file_editor_tab::_cancelled = false;
+
 // Make parent null for the file editor tab so that warning
 // WindowModal messages don't affect grandparents.
 file_editor_tab::file_editor_tab (const QString& directory_arg)
 {
   QString directory = directory_arg;
   _lexer_apis = 0;
-  _app_closing = 0;   // app is not closing
   _is_octave_file = true;
-  _modal_dialog = false;
 
   // Make sure there is a slash at the end of the directory name
   // for identification when saved later.
@@ -193,7 +193,10 @@
   if (check_file_modified () == QMessageBox::Cancel)
     e->ignore ();
   else
-    e->accept ();
+    {
+      e->accept ();
+      emit tab_remove_request ();
+    }
 }
 
 void
@@ -628,6 +631,16 @@
 }
 
 void
+file_editor_tab::check_modified_file (void)
+{
+  if (_cancelled)
+    return;
+
+  if (check_file_modified () == QMessageBox::Cancel)
+    _cancelled = true;
+}
+
+void
 file_editor_tab::save_file (const QWidget *ID)
 {
   if (ID != this)
@@ -635,8 +648,8 @@
 
   save_file (_file_name);
 }
+
 void
-
 file_editor_tab::save_file (const QWidget *ID, const QString& fileName,
                             bool remove_on_success)
 {
@@ -678,11 +691,7 @@
     return;
 
   if (_edit_area->isModified () | ! valid_file_name ())
-    {
-      _modal_dialog = true;    // force modal dialog if the file is a new one
-      save_file (_file_name);  // save file dialog
-      _modal_dialog = false;   // back to non-modal dialogs
-    }
+    save_file (_file_name);  // save file dialog
 
   QFileInfo info (_file_name);
   emit run_file_signal (info);
@@ -1208,13 +1217,12 @@
                              _is_octave_file);
 }
 
-// show_dialog: shows a modal or non modal dialog depeding on the closing
-//              of the app and the flag _modal_dialog
+// show_dialog: shows a modal or non modal dialog depending on input arg
 void
-file_editor_tab::show_dialog (QDialog *dlg)
+file_editor_tab::show_dialog (QDialog *dlg, bool modal)
 {
   dlg->setAttribute (Qt::WA_DeleteOnClose);
-  if (_app_closing | _modal_dialog)
+  if (modal)
     dlg->exec ();
   else
     {
@@ -1231,32 +1239,19 @@
     {
       activateWindow ();
       raise ();
+      setFocus ();
       // File is modified but not saved, ask user what to do.  The file
       // editor tab can't be made parent because it may be deleted depending
       // upon the response.  Instead, change the _edit_area to read only.
       QMessageBox::StandardButtons buttons = QMessageBox::Save |
-                                             QMessageBox::Discard;
-      QString available_actions;
-
-      switch (_app_closing)
-        {
-          case -1:  // octave is exiting and so does the gui
-            available_actions =
-              tr ("Do you want to save or discard the changes?");
-            break;
+                                             QMessageBox::Discard |
+                                             QMessageBox::Cancel;
 
-          case 1:   // gui is exiting
-            available_actions =
-              tr ("Do you want to cancel exiting octave, save or discard the changes?");
-            buttons = buttons | QMessageBox::Cancel;
-            break;
-
-          case 0:   // tab is closing
-            available_actions =
-              tr ("Do you want to cancel closing, save or discard the changes?");
-            buttons = buttons | QMessageBox::Cancel;
-            break;
-        }
+      // For now, just a warning message about closing a tab that has been
+      // modified seems sufficient.  Exit-condition-specific messages could
+      // be achieved by making 'available_actions' a function input string.
+      QString available_actions =
+          tr ("Do you want to cancel closing, save or discard the changes?");
 
       QString file;
       if (valid_file_name ())
@@ -1266,9 +1261,9 @@
 
       QMessageBox* msgBox
         = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"),
-                           tr ("The file\n"
-                               "%1\n"
-                               "is about to be closed but has been modified.\n"
+                           tr ("The file\n\n"
+                               "  %1\n\n"
+                               "is about to be closed but has been modified.  "
                                "%2").
                            arg (file). arg (available_actions),
                            buttons, qobject_cast<QWidget *> (parent ()));
@@ -1278,14 +1273,17 @@
       connect (msgBox, SIGNAL (finished (int)),
                this, SLOT (handle_file_modified_answer (int)));
 
-      show_dialog (msgBox);
+      show_dialog (msgBox, true);
 
-      return QMessageBox::Cancel;
+      if (_cancelled)
+        return QMessageBox::Cancel;
+      else
+        return decision;
     }
   else
     {
-      // Nothing was modified, just remove from editor.
-      emit tab_remove_request ();
+      // Nothing was modified.  Leave tab present in case user
+      // decides to cancel some point further along.
     }
 
   return decision;
@@ -1296,18 +1294,18 @@
 {
   if (decision == QMessageBox::Save)
     {
-      // Save file, then remove from editor.
-      save_file (_file_name, true);
+      // Save file, but do not remove from editor.
+      save_file (_file_name, false);
     }
   else if (decision == QMessageBox::Discard)
     {
-      // User doesn't want to save, just remove from editor.
-      emit tab_remove_request ();
+      // User doesn't want to save, leave tab and remove subsequently.
     }
   else
     {
       // User canceled, allow editing again.
       _edit_area->setReadOnly (false);
+      _cancelled = true;
     }
 }
 
@@ -1497,7 +1495,7 @@
                            tr ("Could not open file %1 for write:\n%2.").
                            arg (file_to_save).arg (file.errorString ()),
                            QMessageBox::Ok, 0);
-      show_dialog (msgBox);
+      show_dialog (msgBox, false);
 
       return;
     }
@@ -1646,7 +1644,7 @@
                this, SLOT (handle_save_file_as_answer (const QString&)));
     }
 
-  show_dialog (fileDialog);
+  show_dialog (fileDialog, false);
 }
 
 void
@@ -1934,9 +1932,8 @@
 // When emitting a signal, only the return value from the last slot
 // goes back to the sender
 bool
-file_editor_tab::conditional_close (int app_closing)
+file_editor_tab::conditional_close (void)
 {
-  _app_closing = app_closing;
   return close ();
 }