# HG changeset patch
# User Daniel J Sebald <daniel.sebald@ieee.org>
# Date 1434873590 18000
# Node ID 6c178e2b4496882f53b478eef070f7c83dfc5d50
# Parent  f357e076776f7f09a56acf1ecc4d5ba7ec763a20
Save settings in Qt convention, delete all children in destructors (bug #45366)

* QUnixTerminalImpl.cpp (QUnixTerminalImpl::~QUnixTerminalImpl): Delete
dynamic objects pointed to by m_terminal (TerminalModel), m_kpty (KPty) and
m_terminalView (TerminalView).  (bug fix)

* files-dock-widget.cc: (files_dock_widget::~files_dock_widget): Rename to
save_settings().  Return if variable 'settings' is not valid object pointer.
(files_dock_widget::save_settings): Added.  Similar code as destructor was.
Call base class octave_dock_widget::save_settings() at end of routine.

* files-dock-widget.h: (files_dock_widget::~files_dock_widget): Provide empty
destructor.
(files_dock_widget::save_settings): Added, public slot.

* find-files-dialog.cc: (find_files_dialog::~find_files_dialog): Moved most
of the code, except the statement deleting the directory iterator, to
new routine save_settings().
(find_files_dialog::save_settings): Added.  Large portion of the code that was
in the destructor.  Return immediately if variable 'settings' is not valid
object pointer.

* find-files-dialog.h: (find_files_dialog::save_settings): Added, public slot.

* history-dock-widget.cc: (history_dock_widget::~history_dock_widget): Rename
to save_settings().  Return if variable 'settings' is not valid object pointer.
(history_dock_widget::save_settings): Similar code as destructor was.  Call
base class octave_dock_widget::save_settings() at end of routine.

* history-dock-widget.h: (history_dock_widget::~history_dock_widget): Provide
empty destructor.
(history_dock_widget::save_settings): Added, public slot.

* main-window.cc (main_window::prepare_to_exit): If find_files_dlg is valid,
call the object's save_settings() routine.
(main_window::construct): Connect appropriate slot of all objects that must
save_settings information to the qApp aboutToQuit() signal.  (Except for
find_files_dlg, see above.)  At end of this sequence, connect aboutToQuit() to
the shortcut_manager and resource_manager function that deletes instance.

* octave-dock-widget.cc: (octave_dock_widget::~octave_dock_widget): Rename to
save_settings().  Return if variable 'settings' is not valid object pointer.
(octave_dock_widget::save_settings): Similar code as destructor was.

* octave-dock-widget.h: (octave_dock_widget::~octave_dock_widget): Provide
empty destructor.
(octave_dock_widget::save_settings): Added, public slot.

* octave-qt-link.cc (octave_qt_link::do_prompt_new_edit_file): Check that
'settings' pointer is valid before using.

* resource-manager.cc: Remove "singleton-cleanup.h" header reference.
(resource_manager::instance_ok): Do not add cleanup_instance() to worker
thread's exit cleanup procedure.

* resource-manager.h (resource_manager::instance) Change variable to public for
connecting.
(resource_manager::cleanup_instance) Change to a public slot for connecting to
qApp aboutToQuit() signal.
(resource_manager::resource_manager): Remove an unused variation of the
constructor.
(resource_manager::operator =) Removed.

* settings-dialog.cc: Add QMessageBox to header file list.
(settings_dialog::settings_dialog): If QSettings pointer settings is not valid
return immediately.
(settings_dialog::show_tab): Condition setting the current index on pointer
'settings' being valid.
(settings_dialog::write_changed_settings): Remove FIXME comment.  If the
settings are not valid, display a dialog about missing file and return.

* shortcut-manager.cc: Remove "singleton-cleanup.h" header reference.
(shortcut_manager::instance_ok): Do not add cleanup_instance() to worker
thread's exit cleanup procedure.

* shortcut-manager.h (shortcut_manager::instance) Change variable to public for
connecting.
(shortcut_manager::cleanup_instance) Change to a public slot for connecting to
qApp aboutToQuit() signal.
(shortcut_manager::shortcut_manager): Remove an unused variation of the
constructor.
(shortcut_manager::operator =) Removed.

* terminal-dock-widget.cc (terminal_dock_widget::~terminal_dock_widget): Added.
Delete QTerminal terminal.  (bug fix)

* terminal-dock-widget.h (terminal_dock_widget::~terminal_dock_widget): Added.

* workspace-view.cc: (workspace_view::workspace_view): Place code hunk using
QSettings pointer 'settings' within a conditional block.
(workspace_view::~workspace_view): Rename to save_settings().  Return if
variable 'settings' is not valid object pointer.
(workspace_view::save_settings): Almost same code as destructor was.  Call base
class octave_dock_widget::save_settings() at end of routine.

* workspace-view.h: (workspace_view::~workspace_view): Provide empty
destructor.
(workspace_view::save_settings): Added, public slot.

diff --git a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp
@@ -114,6 +114,10 @@ void QUnixTerminalImpl::connectToPty()
 
 QUnixTerminalImpl::~QUnixTerminalImpl()
 {
+    delete m_terminalModel;
+    delete m_kpty;
+    delete m_terminalView;
+
     // Restore stderr so that any errors at exit might appear somewhere.
     dup2 (fdstderr, STDERR_FILENO);
 
diff --git a/libgui/src/files-dock-widget.cc b/libgui/src/files-dock-widget.cc
--- a/libgui/src/files-dock-widget.cc
+++ b/libgui/src/files-dock-widget.cc
@@ -265,9 +265,14 @@ files_dock_widget::files_dock_widget (QW
   _octave_dir = "";
 }
 
-files_dock_widget::~files_dock_widget ()
+void
+files_dock_widget::save_settings (void)
 {
   QSettings *settings = resource_manager::get_settings ();
+
+  if (! settings)
+    return;
+
   int sort_column = _file_tree_view->header ()->sortIndicatorSection ();
   Qt::SortOrder sort_order = _file_tree_view->header ()->sortIndicatorOrder ();
   settings->setValue ("filesdockwidget/sort_files_by_column", sort_column);
@@ -283,6 +288,8 @@ files_dock_widget::~files_dock_widget ()
   settings->setValue ("filesdockwidget/mru_dir_list", dirs);
 
   settings->sync ();
+
+  octave_dock_widget::save_settings ();
 }
 
 void
diff --git a/libgui/src/files-dock-widget.h b/libgui/src/files-dock-widget.h
--- a/libgui/src/files-dock-widget.h
+++ b/libgui/src/files-dock-widget.h
@@ -51,7 +51,7 @@ public:
 
   files_dock_widget (QWidget *parent = 0);
 
-  ~files_dock_widget ();
+  ~files_dock_widget () {}
 
 public slots:
 
@@ -79,6 +79,8 @@ public slots:
   /** Tells the widget to react on changed settings. */
   void notice_settings (const QSettings *settings);
 
+  void save_settings (void);
+
 private slots:
   /** context menu wanted */
   void contextmenu_requested (const QPoint& pos);
diff --git a/libgui/src/find-files-dialog.cc b/libgui/src/find-files-dialog.cc
--- a/libgui/src/find-files-dialog.cc
+++ b/libgui/src/find-files-dialog.cc
@@ -199,10 +199,14 @@ find_files_dialog::find_files_dialog (QW
   connect (this, SIGNAL (finished (int)), this, SLOT (handle_done (int)));
 }
 
-find_files_dialog::~find_files_dialog ()
+void
+find_files_dialog::save_settings (void)
 {
   QSettings *settings = resource_manager::get_settings ();
 
+  if (! settings)
+    return;
+
   int sort_column = _file_list->horizontalHeader ()->sortIndicatorSection ();
   Qt::SortOrder sort_order
     = _file_list->horizontalHeader ()->sortIndicatorOrder ();
@@ -226,7 +230,10 @@ find_files_dialog::~find_files_dialog ()
                       _content_case_check->isChecked ());
 
   settings->sync ();
+}
 
+find_files_dialog::~find_files_dialog ()
+{
   if (_dir_iterator)
     delete _dir_iterator;
 }
diff --git a/libgui/src/find-files-dialog.h b/libgui/src/find-files-dialog.h
--- a/libgui/src/find-files-dialog.h
+++ b/libgui/src/find-files-dialog.h
@@ -40,6 +40,7 @@ class find_files_dialog : public QDialog
 public:
   find_files_dialog (QWidget * parent=0);
   virtual ~find_files_dialog ();
+  void save_settings (void);
 
 signals:
   void file_selected (const QString &fileName);
diff --git a/libgui/src/history-dock-widget.cc b/libgui/src/history-dock-widget.cc
--- a/libgui/src/history-dock-widget.cc
+++ b/libgui/src/history-dock-widget.cc
@@ -136,10 +136,14 @@ history_dock_widget::construct ()
   _history_list_view->setTextElideMode (Qt::ElideRight);
 }
 
-history_dock_widget::~history_dock_widget ()
+void
+history_dock_widget::save_settings (void)
 {
   QSettings *settings = resource_manager::get_settings ();
 
+  if (! settings)
+    return;
+
   settings->setValue ("history_dock_widget/filter_active",
                       _filter_checkbox->isChecked ());
 
@@ -149,6 +153,8 @@ history_dock_widget::~history_dock_widge
   settings->setValue ("history_dock_widget/mru_list", mru);
 
   settings->sync ();
+
+  octave_dock_widget::save_settings ();
 }
 
 void
diff --git a/libgui/src/history-dock-widget.h b/libgui/src/history-dock-widget.h
--- a/libgui/src/history-dock-widget.h
+++ b/libgui/src/history-dock-widget.h
@@ -39,13 +39,14 @@ class history_dock_widget : public octav
 public:
 
   history_dock_widget (QWidget *parent = 0);
-  ~history_dock_widget ();
+  ~history_dock_widget () {}
 
 public slots:
 
   void set_history (const QStringList& hist);
   void append_history (const QString& hist_entry);
   void clear_history (void);
+  void save_settings (void);
 
 signals:
 
diff --git a/libgui/src/main-window.cc b/libgui/src/main-window.cc
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -828,6 +828,12 @@ main_window::confirm_shutdown_octave (vo
 void
 main_window::prepare_to_exit (void)
 {
+  // Find files dialog is constructed dynamically, not at time of main_window
+  // construction.  Connecting it to qApp aboutToQuit() signal would have
+  // caused it to run after QSettings deleted.
+  if (find_files_dlg)
+    find_files_dlg->save_settings ();
+
   write_settings ();
 }
 
@@ -1355,8 +1361,24 @@ main_window::construct (void)
 
       construct_tool_bar ();
 
+      // Order is important.  Deleting QSettings must be last.
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               command_window, SLOT (save_settings ()));
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               history_window, SLOT (save_settings ()));
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               file_browser_window, SLOT (save_settings ()));
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               doc_browser_window, SLOT (save_settings ()));
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               workspace_window, SLOT (save_settings ()));
       connect (qApp, SIGNAL (aboutToQuit ()),
                this, SLOT (prepare_to_exit ()));
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               shortcut_manager::instance, SLOT (cleanup_instance ()));
+      // QSettings are saved upon deletion (i.e., cleanup_instance)
+      connect (qApp, SIGNAL (aboutToQuit ()),
+               resource_manager::instance, SLOT (cleanup_instance ()));
 
       connect (qApp, SIGNAL (focusChanged (QWidget*, QWidget*)),
                this, SLOT(focus_changed (QWidget*, QWidget*)));
diff --git a/libgui/src/octave-dock-widget.cc b/libgui/src/octave-dock-widget.cc
--- a/libgui/src/octave-dock-widget.cc
+++ b/libgui/src/octave-dock-widget.cc
@@ -126,12 +126,16 @@ octave_dock_widget::octave_dock_widget (
 
 }
 
-octave_dock_widget::~octave_dock_widget ()
+void
+octave_dock_widget::save_settings (void)
 {
   // save state of this dock-widget
   QString name = objectName ();
   QSettings *settings = resource_manager::get_settings ();
 
+  if (! settings)
+    return;
+
   settings->beginGroup ("DockWidgets");
 
 #if defined (Q_OS_WIN32)
diff --git a/libgui/src/octave-dock-widget.h b/libgui/src/octave-dock-widget.h
--- a/libgui/src/octave-dock-widget.h
+++ b/libgui/src/octave-dock-widget.h
@@ -37,7 +37,7 @@ class octave_dock_widget : public QDockW
 public:
 
   octave_dock_widget (QWidget *p = 0);
-  virtual ~octave_dock_widget ();
+  virtual ~octave_dock_widget () {}
 
   virtual void connect_visibility_changed (void);
   void make_window (void);
@@ -84,6 +84,8 @@ public slots:
 
   QMainWindow *main_win () { return _parent; }
 
+  void save_settings (void);
+
 protected slots:
 
   /** Slot to steer changing visibility from outside. */
diff --git a/libgui/src/octave-qt-link.cc b/libgui/src/octave-qt-link.cc
--- a/libgui/src/octave-qt-link.cc
+++ b/libgui/src/octave-qt-link.cc
@@ -118,7 +118,7 @@ octave_qt_link::do_prompt_new_edit_file 
 {
   QSettings *settings = resource_manager::get_settings ();
 
-  if (settings->value ("editor/create_new_file",false).toBool ())
+  if (! settings || settings->value ("editor/create_new_file",false).toBool ())
     return true;
 
   QFileInfo file_info (QString::fromStdString (file));
diff --git a/libgui/src/resource-manager.cc b/libgui/src/resource-manager.cc
--- a/libgui/src/resource-manager.cc
+++ b/libgui/src/resource-manager.cc
@@ -36,7 +36,6 @@ along with Octave; see the file COPYING.
 #include "file-ops.h"
 #include "help.h"
 #include "oct-env.h"
-#include "singleton-cleanup.h"
 
 #include "defaults.h"
 
@@ -135,13 +134,8 @@ resource_manager::instance_ok (void)
   bool retval = true;
 
   if (! instance)
-    {
       instance = new resource_manager ();
 
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
   if (! instance)
     {
       ::error ("unable to create resource_manager object!");
diff --git a/libgui/src/resource-manager.h b/libgui/src/resource-manager.h
--- a/libgui/src/resource-manager.h
+++ b/libgui/src/resource-manager.h
@@ -99,18 +99,16 @@ public:
   static QStringList terminal_color_names (void);
   static QList<QColor> terminal_default_colors (void);
 
-private:
+  static resource_manager *instance;
 
-  static resource_manager *instance;
+public slots:
 
   static void cleanup_instance (void) { delete instance; instance = 0; }
 
+private:
+
   // No copying!
 
-  resource_manager (const resource_manager&);
-
-  resource_manager& operator = (const resource_manager&);
-
   static bool instance_ok (void);
 
   QString settings_directory;
diff --git a/libgui/src/settings-dialog.cc b/libgui/src/settings-dialog.cc
--- a/libgui/src/settings-dialog.cc
+++ b/libgui/src/settings-dialog.cc
@@ -34,6 +34,7 @@ along with Octave; see the file COPYING.
 #include <QFileDialog>
 #include <QVector>
 #include <QHash>
+#include <QMessageBox>
 
 #ifdef HAVE_QSCINTILLA
 #include "octave-qscintilla.h"
@@ -62,6 +63,9 @@ settings_dialog::settings_dialog (QWidge
 
   QSettings *settings = resource_manager::get_settings ();
 
+  if (! settings)
+    return;
+
   // restore last geometry
   restoreGeometry (settings->value("settings/geometry").toByteArray ());
 
@@ -419,8 +423,9 @@ settings_dialog::show_tab (const QString
   if (tab.isEmpty ())
     {
       QSettings *settings = resource_manager::get_settings ();
-      ui->tabWidget->setCurrentIndex (settings->value ("settings/last_tab",
-                                      0).toInt ());
+      if (settings)
+        ui->tabWidget->setCurrentIndex (settings->value ("settings/last_tab",
+                                        0).toInt ());
     }
   else
     {
@@ -627,7 +632,15 @@ void
 settings_dialog::write_changed_settings (bool closing)
 {
   QSettings *settings = resource_manager::get_settings ();
-  // FIXME: what should happen if settings is 0?
+
+  if (! settings)
+    {
+      QMessageBox msgBox (QMessageBox::Warning, tr ("Octave Settings"),
+                          tr ("Unable to save settings.  Missing settings "
+                              "file or unknown directory."));
+      msgBox.exec ();
+      return;
+    }
 
   // the icon set
   QString widget_icon_set = "NONE";
diff --git a/libgui/src/shortcut-manager.cc b/libgui/src/shortcut-manager.cc
--- a/libgui/src/shortcut-manager.cc
+++ b/libgui/src/shortcut-manager.cc
@@ -40,7 +40,6 @@ along with Octave; see the file COPYING.
 #include "error.h"
 #include "resource-manager.h"
 #include "shortcut-manager.h"
-#include "singleton-cleanup.h"
 
 shortcut_manager *shortcut_manager::instance = 0;
 
@@ -66,13 +65,8 @@ shortcut_manager::instance_ok (void)
   bool retval = true;
 
   if (! instance)
-    {
       instance = new shortcut_manager ();
 
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
   if (! instance)
     {
       ::error ("unable to create shortcut_manager object!");
diff --git a/libgui/src/shortcut-manager.h b/libgui/src/shortcut-manager.h
--- a/libgui/src/shortcut-manager.h
+++ b/libgui/src/shortcut-manager.h
@@ -54,7 +54,9 @@ class shortcut_manager : public QWidget
   Q_OBJECT
 
 public:
+
   shortcut_manager ();
+
   ~shortcut_manager ();
 
   static void init_data ()
@@ -87,8 +89,12 @@ public:
       instance->do_import_export (import, set);
   }
 
+  static shortcut_manager *instance;
+
 public slots:
 
+  static void cleanup_instance (void) { delete instance; instance = 0; }
+
 signals:
 
 protected:
@@ -101,14 +107,8 @@ protected slots:
 
 private:
 
-  static shortcut_manager *instance;
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
   // No copying!
 
-  shortcut_manager (const shortcut_manager&);
-  shortcut_manager& operator = (const shortcut_manager&);
-
   static bool instance_ok (void);
 
   void init (QString, QString, QKeySequence);
diff --git a/libgui/src/terminal-dock-widget.cc b/libgui/src/terminal-dock-widget.cc
--- a/libgui/src/terminal-dock-widget.cc
+++ b/libgui/src/terminal-dock-widget.cc
@@ -70,3 +70,9 @@ terminal_dock_widget::terminal_interrupt
 {
   emit interrupt_signal ();
 }
+
+terminal_dock_widget::~terminal_dock_widget (void)
+{
+  delete terminal;
+}
+
diff --git a/libgui/src/terminal-dock-widget.h b/libgui/src/terminal-dock-widget.h
--- a/libgui/src/terminal-dock-widget.h
+++ b/libgui/src/terminal-dock-widget.h
@@ -37,6 +37,8 @@ public:
 
   terminal_dock_widget (QWidget *parent = 0);
 
+  ~terminal_dock_widget ();
+
   bool has_focus (void) const;
 
   void focus (void);
diff --git a/libgui/src/workspace-view.cc b/libgui/src/workspace-view.cc
--- a/libgui/src/workspace-view.cc
+++ b/libgui/src/workspace-view.cc
@@ -92,24 +92,27 @@ workspace_view::workspace_view (QWidget 
 
   QSettings *settings = resource_manager::get_settings ();
 
-  //enable sorting as previously configured
-  view->setSortingEnabled (true);
-  view->sortByColumn (
-    settings->value ("workspaceview/sort_by_column",0).toInt (),
-    static_cast<Qt::SortOrder>
-    (settings->value ("workspaceview/sort_order", Qt::AscendingOrder).toUInt ())
-  );
-  // Initialize column order and width of the workspace
-  view->horizontalHeader ()->restoreState (
-    settings->value ("workspaceview/column_state").toByteArray ());
+  if (settings)
+  {
+    //enable sorting as previously configured
+    view->setSortingEnabled (true);
+    view->sortByColumn (
+      settings->value ("workspaceview/sort_by_column",0).toInt (),
+      static_cast<Qt::SortOrder>
+      (settings->value ("workspaceview/sort_order", Qt::AscendingOrder).toUInt ())
+    );
+    // Initialize column order and width of the workspace
+    view->horizontalHeader ()->restoreState (
+      settings->value ("workspaceview/column_state").toByteArray ());
 
-  // Init state of the filter
-  _filter->addItems (settings->value ("workspaceview/mru_list").toStringList ());
+    // Init state of the filter
+    _filter->addItems (settings->value ("workspaceview/mru_list").toStringList ());
 
-  bool filter_state =
-    settings->value ("workspaceview/filter_active", false).toBool ();
-  _filter_checkbox->setChecked (filter_state);
-  filter_activate (filter_state);
+    bool filter_state =
+      settings->value ("workspaceview/filter_active", false).toBool ();
+    _filter_checkbox->setChecked (filter_state);
+    filter_activate (filter_state);
+  }
 
   // Connect signals and slots.
 
@@ -128,10 +131,14 @@ workspace_view::workspace_view (QWidget 
 
 }
 
-workspace_view::~workspace_view (void)
+void
+workspace_view::save_settings (void)
 {
   QSettings *settings = resource_manager::get_settings ();
 
+  if (! settings)
+    return;
+
   settings->setValue ("workspaceview/column_state",
                       view->horizontalHeader ()->saveState ());
 
@@ -149,6 +156,8 @@ workspace_view::~workspace_view (void)
   settings->setValue ("workspaceview/mru_list", mru);
 
   settings->sync ();
+
+  octave_dock_widget::save_settings ();
 }
 
 void workspace_view::setModel (workspace_model *model)
diff --git a/libgui/src/workspace-view.h b/libgui/src/workspace-view.h
--- a/libgui/src/workspace-view.h
+++ b/libgui/src/workspace-view.h
@@ -42,7 +42,7 @@ public:
 
   workspace_view (QWidget *parent = 0);
 
-  ~workspace_view (void);
+  ~workspace_view (void) {}
 
 public slots:
 
@@ -50,6 +50,8 @@ public slots:
 
   void setModel (workspace_model *model);
 
+  void save_settings (void);
+
 signals:
 
   /** signal that user had requested a command on a variable */
exporting patch:
<fdopen>
