changeset 25944:ceb508ea92ee

refactor GUI main_window class This change moves Qt application features that are needed for both GUI and Qt-based command-line version of Octave (that is capable of displaying Qt graphics and UI objects) out of the main_window and gui_application classes into a new octave_qt_app class. It also makes the main_window class specific to the main window of the GUI. Although not quite possible yet, we may eventually be able to start Octave and then start/stop the GUI from the command line. This refactoring is a step in that direction. * main-window.h, main-window.cc octave-gui.h, octave-gui.cc (octave_qt_app): New class. Move non-gui Qt application features here from main_window class. Move Qt-specific code here from gui_application class.
author John W. Eaton <jwe@octave.org>
date Thu, 18 Oct 2018 22:17:40 -0400
parents 41f665343437
children a0a8d4dd41e7
files libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-gui.cc libgui/src/octave-gui.h libgui/src/octave-qt-link.cc libinterp/octave.h
diffstat 6 files changed, 770 insertions(+), 727 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/main-window.cc	Fri Oct 19 01:11:17 2018 -0400
+++ b/libgui/src/main-window.cc	Thu Oct 18 22:17:40 2018 -0400
@@ -41,6 +41,7 @@
 #include <QMessageBox>
 #include <QIcon>
 #include <QTextBrowser>
+#include <QTextCodec>
 #include <QTextStream>
 #include <QThread>
 #include <QDateTime>
@@ -55,22 +56,23 @@
 #include "main-window.h"
 #include "settings-dialog.h"
 #include "shortcut-manager.h"
+#include "welcome-wizard.h"
 
 #include "Array.h"
 #include "cmd-edit.h"
+#include "oct-env.h"
 #include "url-transfer.h"
 
 #include "builtin-defun-decls.h"
 #include "defaults.h"
-//#if defined (HAVE_QT_GRAPHICS)
-//#  include "__init_qt__.h"
-//#endif
+#include "defun.h"
 #include "interpreter-private.h"
 #include "interpreter.h"
 #include "oct-map.h"
 #include "octave.h"
 #include "parse.h"
 #include "symscope.h"
+#include "symtab.h"
 #include "utils.h"
 #include "version.h"
 
@@ -86,9 +88,19 @@
 #endif
 }
 
+// Disable all Qt messages by default.
+
+static void
+#if defined (QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT)
+message_handler (QtMsgType, const QMessageLogContext &, const QString &)
+#else
+message_handler (QtMsgType, const char *)
+#endif
+{ }
+
 namespace octave
 {
-  octave_interpreter::octave_interpreter (gui_application *app_context)
+  octave_interpreter::octave_interpreter (gui_application& app_context)
     : QObject (), m_app_context (app_context)
   { }
 
@@ -96,7 +108,7 @@
   {
     // The application context owns the interpreter.
 
-    interpreter& interp = m_app_context->create_interpreter ();
+    interpreter& interp = m_app_context.create_interpreter ();
 
     int exit_status = 0;
 
@@ -106,7 +118,7 @@
 
         interp.initialize ();
 
-        if (m_app_context->start_gui_p ())
+        if (m_app_context.start_gui_p ())
           {
             input_system& input_sys = interp.get_input_system ();
 
@@ -145,54 +157,79 @@
     // Whether or not initialization succeeds we need to clean up the
     // interpreter once we are done with it.
 
-    m_app_context->delete_interpreter ();
+    m_app_context.delete_interpreter ();
 
     emit octave_finished_signal (exit_status);
   }
 
-  main_window::main_window (QWidget *p, gui_application *app_context)
-    : QMainWindow (p), m_app_context (app_context),
-      m_interpreter (new octave_interpreter (app_context)),
-      m_main_thread (new QThread ()), m_workspace_model (nullptr),
+  main_window::main_window (octave_qt_app& oct_qt_app,
+                            octave_qt_link *oct_qt_lnk)
+    : QMainWindow (),
+      m_octave_qt_link (oct_qt_lnk), m_workspace_model (nullptr),
       m_status_bar (nullptr), m_command_window (nullptr),
       m_history_window (nullptr), m_file_browser_window (nullptr),
       m_doc_browser_window (nullptr), m_editor_window (nullptr),
       m_workspace_window (nullptr), m_variable_editor_window (nullptr),
+      m_external_editor (new external_editor_interface (this)),
+      m_active_editor (m_external_editor),
       m_settings_dlg (nullptr), m_find_files_dlg (nullptr),
       m_release_notes_window (nullptr), m_community_news_window (nullptr),
-      m_octave_qt_link (nullptr), m_clipboard (QApplication::clipboard ()),
+      m_clipboard (QApplication::clipboard ()),
       m_prevent_readline_conflicts (true), m_suppress_dbg_location (true),
-      m_start_gui (app_context && app_context->start_gui_p ()),
-      m_file_encoding (QString ())
+      m_closing (false), m_file_encoding (QString ())
   {
-    if (m_start_gui)
+    if (resource_manager::is_first_run ())
       {
-        m_workspace_model = new workspace_model ();
-        m_status_bar = new QStatusBar ();
-        m_command_window = new terminal_dock_widget (this);
-        m_history_window = new history_dock_widget (this);
-        m_file_browser_window = new files_dock_widget (this);
-        m_doc_browser_window = new documentation_dock_widget (this);
-        m_editor_window = create_default_editor (this);
-        m_variable_editor_window = new variable_editor (this);
-        m_workspace_window = new workspace_view (this);
+        // Before wizard.
+        oct_qt_app.config_translators ();
+
+        welcome_wizard welcomeWizard;
+
+        if (welcomeWizard.exec () == QDialog::Rejected)
+          exit (1);
+
+        // Install settings file.
+        resource_manager::reload_settings ();
+      }
+    else
+      {
+        // Get settings file.
+        resource_manager::reload_settings ();
+
+        // After settings.
+        oct_qt_app.config_translators ();
       }
 
-    // Initialize global Qt application metadata
-    QCoreApplication::setApplicationName ("GNU Octave");
-    QCoreApplication::setApplicationVersion (OCTAVE_VERSION);
-#if defined (HAVE_QGUIAPPLICATION_SETDESKTOPFILENAME)
-    if (m_start_gui)
-      QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop");
+    resource_manager::update_network_settings ();
+
+    // We provide specific terminal capabilities, so ensure that
+    // TERM is always set appropriately.
+
+#if defined (OCTAVE_USE_WINDOWS_API)
+    sys::env::putenv ("TERM", "cygwin");
+#else
+    sys::env::putenv ("TERM", "xterm");
 #endif
 
-    // Register octave_value_list for connecting thread crossing signals
-    qRegisterMetaType<octave_value_list> ("octave_value_list");
-
-    m_external_editor = new external_editor_interface (this);
-    m_active_editor = m_editor_window;  // for connecting signals
-    if (! m_editor_window)
-      m_active_editor = m_external_editor;
+    shortcut_manager::init_data ();
+
+    construct_central_widget ();
+
+    m_workspace_model = new workspace_model ();
+    m_status_bar = new QStatusBar ();
+    m_command_window = new terminal_dock_widget (this);
+    m_history_window = new history_dock_widget (this);
+    m_file_browser_window = new files_dock_widget (this);
+    m_doc_browser_window = new documentation_dock_widget (this);
+    m_editor_window = create_default_editor (this);
+    m_variable_editor_window = new variable_editor (this);
+    m_workspace_window = new workspace_view (this);
+
+    m_active_editor = m_editor_window;
+
+#if defined (HAVE_QGUIAPPLICATION_SETDESKTOPFILENAME)
+    QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop");
+#endif
 
     QSettings *settings = resource_manager::get_settings ();
 
@@ -217,28 +254,27 @@
     QDateTime current = QDateTime::currentDateTime ();
     QDateTime one_day_ago = current.addDays (-1);
 
-    if (m_start_gui && connect_to_web
+    if (connect_to_web
         && (! last_checked.isValid () || one_day_ago > last_checked))
       load_and_display_community_news (serial);
 
-    // We have to set up all our windows, before we finally launch octave.
+    construct_octave_qt_link ();
+
+    // We have to set up all our windows, before we finally launch
+    // octave.
+
     construct ();
 
-    connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
-             this, SLOT (handle_octave_ready (void)));
-
-    connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
-             this, SLOT (handle_octave_finished (int)));
-
-    connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
-             m_main_thread, SLOT (quit (void)));
-
-    connect (m_main_thread, SIGNAL (finished (void)),
-             m_main_thread, SLOT (deleteLater (void)));
-
-    m_interpreter->moveToThread (m_main_thread);
-
-    m_main_thread->start ();
+    read_settings ();
+
+    init_terminal_size ();
+
+    // Connect signals for changes in visibility not before window is
+    // shown.
+
+    connect_visibility_changed ();
+
+    focus_command_window ();
   }
 
   main_window::~main_window (void)
@@ -260,28 +296,11 @@
     delete m_status_bar;
     delete m_workspace_model;
     delete m_variable_editor_window;
-    delete m_interpreter;
-
-    if (m_find_files_dlg)
-      {
-        delete m_find_files_dlg;
-        m_find_files_dlg = nullptr;
-      }
-    if (m_release_notes_window)
-      {
-        delete m_release_notes_window;
-        m_release_notes_window = nullptr;
-      }
-    if (m_settings_dlg)
-      {
-        delete m_settings_dlg;
-        m_settings_dlg = nullptr;
-      }
-    if (m_community_news_window)
-      {
-        delete m_community_news_window;
-        m_community_news_window = nullptr;
-      }
+
+    delete m_find_files_dlg;
+    delete m_release_notes_window;
+    delete m_settings_dlg;
+    delete m_community_news_window;
   }
 
   bool main_window::command_window_has_focus (void) const
@@ -676,25 +695,6 @@
     m_settings_dlg->show ();
   }
 
-  void main_window::copy_image_to_clipboard (const QString& file,
-                                             bool remove_file)
-  {
-    QClipboard *clipboard = QApplication::clipboard ();
-
-    QImage img (file);
-
-    if (img.isNull ())
-      {
-        // Report error?
-        return;
-      }
-
-    clipboard->setImage (img);
-
-    if (remove_file)
-      QFile::remove (file);
-  }
-
   void main_window::show_about_octave (void)
   {
     std::string message
@@ -822,41 +822,30 @@
 
   }
 
-  void main_window::confirm_shutdown_octave (void)
+  bool main_window::confirm_shutdown_octave (void)
   {
     bool closenow = true;
 
-    if (m_start_gui)
+    QSettings *settings = resource_manager::get_settings ();
+
+    if (settings->value ("prompt_to_exit", false).toBool ())
       {
-        QSettings *settings = resource_manager::get_settings ();
-
-        if (settings->value ("prompt_to_exit", false).toBool ())
-          {
-            int ans = QMessageBox::question (this, tr ("Octave"),
-                                             tr ("Are you sure you want to exit Octave?"),
-                                             (QMessageBox::Ok
-                                              | QMessageBox::Cancel),
-                                             QMessageBox::Ok);
-
-            if (ans != QMessageBox::Ok)
-              closenow = false;
-          }
+        int ans = QMessageBox::question (this, tr ("Octave"),
+                                         tr ("Are you sure you want to exit Octave?"),
+                                         (QMessageBox::Ok
+                                          | QMessageBox::Cancel),
+                                         QMessageBox::Ok);
+
+        if (ans != QMessageBox::Ok)
+          closenow = false;
+      }
 
 #if defined (HAVE_QSCINTILLA)
-        if (closenow)
-          closenow = m_editor_window->check_closing ();
+    if (closenow)
+      closenow = m_editor_window->check_closing ();
 #endif
-      }
-
-    // Wait for link thread to go to sleep state.
-    m_octave_qt_link->lock ();
-
-    m_octave_qt_link->shutdown_confirmation (closenow);
-
-    m_octave_qt_link->unlock ();
-
-    // Awake the worker thread so that it continues shutting down (or not).
-    m_octave_qt_link->wake_all ();
+
+    return closenow;
   }
 
   void main_window::prepare_to_exit (void)
@@ -1382,121 +1371,6 @@
       emit selectAll_signal ();
   }
 
-  // Connect the signals emitted when the Octave thread wants to create
-  // a dialog box of some sort.  Perhaps a better place for this would be
-  // as part of the QUIWidgetCreator class.  However, mainWindow currently
-  // is not a global variable and not accessible for connecting.
-
-  void main_window::connect_uiwidget_links (void)
-  {
-    connect (&uiwidget_creator,
-             SIGNAL (create_dialog (const QString&, const QString&,
-                                    const QString&, const QStringList&,
-                                    const QString&, const QStringList&)),
-             this,
-             SLOT (handle_create_dialog (const QString&, const QString&,
-                                         const QString&, const QStringList&,
-                                         const QString&, const QStringList&)));
-
-    // Register QIntList so that list of ints may be part of a signal.
-    qRegisterMetaType<QIntList> ("QIntList");
-    connect (&uiwidget_creator,
-             SIGNAL (create_listview (const QStringList&, const QString&,
-                                      int, int, const QIntList&,
-                                      const QString&, const QStringList&,
-                                      const QString&, const QString&)),
-             this,
-             SLOT (handle_create_listview (const QStringList&, const QString&,
-                                           int, int, const QIntList&,
-                                           const QString&, const QStringList&,
-                                           const QString&, const QString&)));
-
-    // Register QFloatList so that list of floats may be part of a signal.
-    qRegisterMetaType<QFloatList> ("QFloatList");
-    connect (&uiwidget_creator,
-             SIGNAL (create_inputlayout (const QStringList&, const QString&,
-                                         const QFloatList&, const QFloatList&,
-                                         const QStringList&)),
-             this,
-             SLOT (handle_create_inputlayout (const QStringList&, const QString&,
-                                              const QFloatList&,
-                                              const QFloatList&,
-                                              const QStringList&)));
-
-    connect (&uiwidget_creator,
-             SIGNAL (create_filedialog (const QStringList &,const QString&,
-                                        const QString&, const QString&,
-                                        const QString&)),
-             this,
-             SLOT (handle_create_filedialog (const QStringList &, const QString&,
-                                             const QString&, const QString&,
-                                             const QString&)));
-  }
-
-  // Create a message dialog with specified string, buttons and decorative
-  // text.
-
-  void main_window::handle_create_dialog (const QString& message,
-                                          const QString& title,
-                                          const QString& icon,
-                                          const QStringList& button,
-                                          const QString& defbutton,
-                                          const QStringList& role)
-  {
-    MessageDialog *message_dialog = new MessageDialog (message, title, icon,
-                                                       button, defbutton, role);
-    message_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    message_dialog->show ();
-  }
-
-  // Create a list dialog with specified list, initially selected, mode,
-  // view size and decorative text.
-
-  void main_window::handle_create_listview (const QStringList& list,
-                                            const QString& mode,
-                                            int wd, int ht,
-                                            const QIntList& initial,
-                                            const QString& name,
-                                            const QStringList& prompt,
-                                            const QString& ok_string,
-                                            const QString& cancel_string)
-  {
-    ListDialog *list_dialog = new ListDialog (list, mode, wd, ht,
-                                              initial, name, prompt,
-                                              ok_string, cancel_string);
-
-    list_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    list_dialog->show ();
-  }
-
-  // Create an input dialog with specified prompts and defaults, title and
-  // row/column size specifications.
-  void main_window::handle_create_inputlayout (const QStringList& prompt,
-                                               const QString& title,
-                                               const QFloatList& nr,
-                                               const QFloatList& nc,
-                                               const QStringList& defaults)
-  {
-    InputDialog *input_dialog = new InputDialog (prompt, title, nr, nc,
-                                                 defaults);
-
-    input_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    input_dialog->show ();
-  }
-
-  void main_window::handle_create_filedialog (const QStringList& filters,
-                                              const QString& title,
-                                              const QString& filename,
-                                              const QString& dirname,
-                                              const QString& multimode)
-  {
-    FileDialog *file_dialog = new FileDialog (filters, title, filename,
-                                              dirname, multimode);
-
-    file_dialog->setAttribute (Qt::WA_DeleteOnClose);
-    file_dialog->show ();
-  }
-
   void main_window::handle_show_doc (const QString& file)
   {
     m_doc_browser_window->setVisible (true);
@@ -1520,33 +1394,30 @@
 
     QDir startup_dir = QDir ();    // current octave dir after startup
 
-    if (m_start_gui)
+    if (settings)
       {
-        if (settings)
+        if (settings->value ("restore_octave_dir").toBool ())
           {
-            if (settings->value ("restore_octave_dir").toBool ())
-              {
-                // restore last dir from previous session
-                QStringList curr_dirs
-                  = settings->value ("MainWindow/current_directory_list").toStringList ();
-                startup_dir
-                  = QDir (curr_dirs.at (0));  // last dir in previous session
-              }
-            else if (! settings->value ("octave_startup_dir").toString ().isEmpty ())
-              {
-                // do not restore but there is a startup dir configured
-                startup_dir
-                  = QDir (settings->value ("octave_startup_dir").toString ());
-              }
+            // restore last dir from previous session
+            QStringList curr_dirs
+              = settings->value ("MainWindow/current_directory_list").toStringList ();
+            startup_dir
+              = QDir (curr_dirs.at (0));  // last dir in previous session
           }
-
-        if (! startup_dir.exists ())
+        else if (! settings->value ("octave_startup_dir").toString ().isEmpty ())
           {
-            // the configured startup dir does not exist, take actual one
-            startup_dir = QDir ();
+            // do not restore but there is a startup dir configured
+            startup_dir
+              = QDir (settings->value ("octave_startup_dir").toString ());
           }
       }
 
+    if (! startup_dir.exists ())
+      {
+        // the configured startup dir does not exist, take actual one
+        startup_dir = QDir ();
+      }
+
     set_current_working_directory (startup_dir.absolutePath ());
 
     if (m_editor_window)
@@ -1560,13 +1431,7 @@
 #endif
       }
 
-    if (m_start_gui)
-      focus_command_window ();  // make sure that the command window has focus
-  }
-
-  void main_window::handle_octave_finished (int exit_status)
-  {
-    qApp->exit (exit_status);
+    focus_command_window ();  // make sure that the command window has focus
   }
 
   void main_window::find_files (const QString& start_dir)
@@ -1747,12 +1612,8 @@
     queue_cmd (cmd);
   }
 
-  // Main subroutine of the constructor
-
-  void main_window::construct (void)
+  void main_window::construct_central_widget (void)
   {
-    m_closing = false;   // flag for editor files when closed
-
     // Create and set the central widget.  QMainWindow takes ownership of
     // the widget (pointer) so there is no need to delete the object upon
     // destroying this main_window.
@@ -1763,294 +1624,274 @@
     dummyWidget->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);
     dummyWidget->hide ();
     setCentralWidget (dummyWidget);
-
-    connect_uiwidget_links ();
-
-    construct_octave_qt_link ();
-
-    if (m_start_gui)
-      {
-        setWindowIcon (QIcon (":/actions/icons/logo.png"));
-
-        m_workspace_window->setModel (m_workspace_model);
-
-        connect (m_workspace_model, SIGNAL (model_changed (void)),
-                 m_workspace_window, SLOT (handle_model_changed (void)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (edit_variable_signal (const QString&,
-                                               const octave_value&)),
-                 this,
-                 SLOT (edit_variable (const QString&, const octave_value&)));
-
-        connect (m_octave_qt_link, SIGNAL (refresh_variable_editor_signal (void)),
-                 this, SLOT (refresh_variable_editor (void)));
-
-        connect (m_workspace_model,
-                 SIGNAL (rename_variable (const QString&, const QString&)),
-                 this,
-                 SLOT (handle_rename_variable_request (const QString&,
-                                                       const QString&)));
-
-        connect (m_variable_editor_window, SIGNAL (updated (void)),
-                 this, SLOT (handle_variable_editor_update (void)));
-
-        construct_menu_bar ();
-
-        construct_tool_bar ();
-
-        // Order is important.  Deleting QSettings must be last.
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_command_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_history_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_file_browser_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_doc_browser_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_workspace_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_editor_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 m_variable_editor_window, SLOT (save_settings (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 this, SLOT (prepare_to_exit (void)));
-
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 shortcut_manager::instance, SLOT (cleanup_instance (void)));
-
-        // QSettings are saved upon deletion (i.e., cleanup_instance)
-        connect (qApp, SIGNAL (aboutToQuit (void)),
-                 resource_manager::instance, SLOT (cleanup_instance (void)));
-
-        connect (qApp, SIGNAL (focusChanged (QWidget*, QWidget*)),
-                 this, SLOT (focus_changed (QWidget*, QWidget*)));
-
-        connect (this, SIGNAL (settings_changed (const QSettings *)),
-                 this, SLOT (notice_settings (const QSettings *)));
-
-        connect (this, SIGNAL (editor_focus_changed (bool)),
-                 this, SLOT (disable_menu_shortcuts (bool)));
-
-        connect (this, SIGNAL (editor_focus_changed (bool)),
-                 m_editor_window, SLOT (enable_menu_shortcuts (bool)));
-
-        connect (m_editor_window,
-                 SIGNAL (request_open_file_external (const QString&, int)),
-                 m_external_editor,
-                 SLOT (call_custom_editor (const QString&, int)));
-
-        connect (m_external_editor,
-                 SIGNAL (request_settings_dialog (const QString&)),
-                 this, SLOT (process_settings_dialog_request (const QString&)));
-
-        connect (m_file_browser_window, SIGNAL (load_file_signal (const QString&)),
-                 this, SLOT (handle_load_workspace_request (const QString&)));
-
-        connect (m_file_browser_window, SIGNAL (open_any_signal (const QString&)),
-                 this, SLOT (handle_open_any_request (const QString&)));
-
-        connect (m_file_browser_window, SIGNAL (find_files_signal (const QString&)),
-                 this, SLOT (find_files (const QString&)));
-
-        setWindowTitle ("Octave");
-
-// See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357
+  }
+
+// Main subroutine of the constructor
+
+  void main_window::construct (void)
+  {
+    setWindowIcon (QIcon (":/actions/icons/logo.png"));
+
+    m_workspace_window->setModel (m_workspace_model);
+
+    connect (m_workspace_model, SIGNAL (model_changed (void)),
+             m_workspace_window, SLOT (handle_model_changed (void)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (edit_variable_signal (const QString&,
+                                           const octave_value&)),
+             this,
+             SLOT (edit_variable (const QString&, const octave_value&)));
+
+    connect (m_octave_qt_link, SIGNAL (refresh_variable_editor_signal (void)),
+             this, SLOT (refresh_variable_editor (void)));
+
+    connect (m_workspace_model,
+             SIGNAL (rename_variable (const QString&, const QString&)),
+             this,
+             SLOT (handle_rename_variable_request (const QString&,
+                                                   const QString&)));
+
+    connect (m_variable_editor_window, SIGNAL (updated (void)),
+             this, SLOT (handle_variable_editor_update (void)));
+
+    construct_menu_bar ();
+
+    construct_tool_bar ();
+
+    // Order is important.  Deleting QSettings must be last.
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_command_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_history_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_file_browser_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_doc_browser_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_workspace_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_editor_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             m_variable_editor_window, SLOT (save_settings (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             this, SLOT (prepare_to_exit (void)));
+
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             shortcut_manager::instance, SLOT (cleanup_instance (void)));
+
+    // QSettings are saved upon deletion (i.e., cleanup_instance)
+    connect (qApp, SIGNAL (aboutToQuit (void)),
+             resource_manager::instance, SLOT (cleanup_instance (void)));
+
+    connect (qApp, SIGNAL (focusChanged (QWidget*, QWidget*)),
+             this, SLOT (focus_changed (QWidget*, QWidget*)));
+
+    connect (this, SIGNAL (settings_changed (const QSettings *)),
+             this, SLOT (notice_settings (const QSettings *)));
+
+    connect (this, SIGNAL (editor_focus_changed (bool)),
+             this, SLOT (disable_menu_shortcuts (bool)));
+
+    connect (this, SIGNAL (editor_focus_changed (bool)),
+             m_editor_window, SLOT (enable_menu_shortcuts (bool)));
+
+    connect (m_editor_window,
+             SIGNAL (request_open_file_external (const QString&, int)),
+             m_external_editor,
+             SLOT (call_custom_editor (const QString&, int)));
+
+    connect (m_external_editor,
+             SIGNAL (request_settings_dialog (const QString&)),
+             this, SLOT (process_settings_dialog_request (const QString&)));
+
+    connect (m_file_browser_window, SIGNAL (load_file_signal (const QString&)),
+             this, SLOT (handle_load_workspace_request (const QString&)));
+
+    connect (m_file_browser_window, SIGNAL (open_any_signal (const QString&)),
+             this, SLOT (handle_open_any_request (const QString&)));
+
+    connect (m_file_browser_window, SIGNAL (find_files_signal (const QString&)),
+             this, SLOT (find_files (const QString&)));
+
+    setWindowTitle ("Octave");
+
+    // See Octave bug #53409 and https://bugreports.qt.io/browse/QTBUG-55357
 #if (QT_VERSION < 0x050601) || (QT_VERSION >= 0x050701)
-        setDockOptions (QMainWindow::AnimatedDocks
-                        | QMainWindow::AllowNestedDocks
-                        | QMainWindow::AllowTabbedDocks);
+    setDockOptions (QMainWindow::AnimatedDocks
+                    | QMainWindow::AllowNestedDocks
+                    | QMainWindow::AllowTabbedDocks);
 #else
-        setDockNestingEnabled (true);
+    setDockNestingEnabled (true);
 #endif
 
-        addDockWidget (Qt::RightDockWidgetArea, m_command_window);
-        addDockWidget (Qt::RightDockWidgetArea, m_doc_browser_window);
-        tabifyDockWidget (m_command_window, m_doc_browser_window);
+    addDockWidget (Qt::RightDockWidgetArea, m_command_window);
+    addDockWidget (Qt::RightDockWidgetArea, m_doc_browser_window);
+    tabifyDockWidget (m_command_window, m_doc_browser_window);
 
 #if defined (HAVE_QSCINTILLA)
-        addDockWidget (Qt::RightDockWidgetArea, m_editor_window);
-        tabifyDockWidget (m_command_window, m_editor_window);
+    addDockWidget (Qt::RightDockWidgetArea, m_editor_window);
+    tabifyDockWidget (m_command_window, m_editor_window);
 #endif
-        addDockWidget (Qt::RightDockWidgetArea, m_variable_editor_window);
-        tabifyDockWidget (m_command_window, m_variable_editor_window);
-
-        addDockWidget (Qt::LeftDockWidgetArea, m_file_browser_window);
-        addDockWidget (Qt::LeftDockWidgetArea, m_workspace_window);
-        addDockWidget (Qt::LeftDockWidgetArea, m_history_window);
-
-        int win_x = QApplication::desktop ()->width ();
-        int win_y = QApplication::desktop ()->height ();
-
-        if (win_x > 960)
-          win_x = 960;
-
-        if (win_y > 720)
-          win_y = 720;
-
-        setGeometry (0, 0, win_x, win_y);
-
-        setStatusBar (m_status_bar);
+    addDockWidget (Qt::RightDockWidgetArea, m_variable_editor_window);
+    tabifyDockWidget (m_command_window, m_variable_editor_window);
+
+    addDockWidget (Qt::LeftDockWidgetArea, m_file_browser_window);
+    addDockWidget (Qt::LeftDockWidgetArea, m_workspace_window);
+    addDockWidget (Qt::LeftDockWidgetArea, m_history_window);
+
+    int win_x = QApplication::desktop ()->width ();
+    int win_y = QApplication::desktop ()->height ();
+
+    if (win_x > 960)
+      win_x = 960;
+
+    if (win_y > 720)
+      win_y = 720;
+
+    setGeometry (0, 0, win_x, win_y);
+
+    setStatusBar (m_status_bar);
 
 #if defined (HAVE_QSCINTILLA)
-        connect (this,
-                 SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
-                 m_editor_window,
-                 SLOT (handle_insert_debugger_pointer_request (const QString&,
-                                                               int)));
-
-        connect (this,
-                 SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
-                 m_editor_window,
-                 SLOT (handle_delete_debugger_pointer_request (const QString&,
-                                                               int)));
-
-        connect (this,
-                 SIGNAL (update_breakpoint_marker_signal (bool, const QString&,
-                                                          int, const QString&)),
-                 m_editor_window,
-                 SLOT (handle_update_breakpoint_marker_request (bool,
-                                                                const QString&,
-                                                                int,
-                                                                const QString&)));
-
-        // Signals for removing/renaming files/dirs in the file browser
-        connect (m_file_browser_window,
-                 SIGNAL (file_remove_signal (const QString&, const QString&)),
-                 m_editor_window,
-                 SLOT (handle_file_remove (const QString&, const QString&)));
-
-        connect (m_file_browser_window, SIGNAL (file_renamed_signal (bool)),
-                 m_editor_window, SLOT (handle_file_renamed (bool)));
-
-        // Signals for removing/renaming files/dirs in the temrinal window
-        connect (m_octave_qt_link,
-                 SIGNAL (file_remove_signal (const QString&, const QString&)),
-                 this, SLOT (file_remove_proxy (const QString&, const QString&)));
-        connect (m_octave_qt_link, SIGNAL (file_renamed_signal (bool)),
-                 m_editor_window, SLOT (handle_file_renamed (bool)));
+    connect (this,
+             SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
+             m_editor_window,
+             SLOT (handle_insert_debugger_pointer_request (const QString&,
+                                                           int)));
+
+    connect (this,
+             SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
+             m_editor_window,
+             SLOT (handle_delete_debugger_pointer_request (const QString&,
+                                                           int)));
+
+    connect (this,
+             SIGNAL (update_breakpoint_marker_signal (bool, const QString&,
+                                                      int, const QString&)),
+             m_editor_window,
+             SLOT (handle_update_breakpoint_marker_request (bool,
+                                                            const QString&,
+                                                            int,
+                                                            const QString&)));
+
+    // Signals for removing/renaming files/dirs in the file browser
+    connect (m_file_browser_window,
+             SIGNAL (file_remove_signal (const QString&, const QString&)),
+             m_editor_window,
+             SLOT (handle_file_remove (const QString&, const QString&)));
+
+    connect (m_file_browser_window, SIGNAL (file_renamed_signal (bool)),
+             m_editor_window, SLOT (handle_file_renamed (bool)));
+
+    // Signals for removing/renaming files/dirs in the temrinal window
+    connect (m_octave_qt_link,
+             SIGNAL (file_remove_signal (const QString&, const QString&)),
+             this, SLOT (file_remove_proxy (const QString&, const QString&)));
+    connect (m_octave_qt_link, SIGNAL (file_renamed_signal (bool)),
+             m_editor_window, SLOT (handle_file_renamed (bool)));
 #endif
 
-        octave_link::post_event (this,
-                                 &main_window::resize_command_window_callback);
-
-        configure_shortcuts ();
-      }
+    octave_link::post_event (this,
+                             &main_window::resize_command_window_callback);
+
+    configure_shortcuts ();
   }
 
   void main_window::construct_octave_qt_link (void)
   {
-    m_octave_qt_link = new octave_qt_link ();
-
-    octave_link::connect_link (m_octave_qt_link);
-
-    connect (m_octave_qt_link, SIGNAL (confirm_shutdown_signal (void)),
-             this, SLOT (confirm_shutdown_octave (void)));
+    connect (m_octave_qt_link,
+             SIGNAL (set_workspace_signal (bool, bool,
+                                           const symbol_scope&)),
+             m_workspace_model,
+             SLOT (set_workspace (bool, bool, const symbol_scope&)));
+
+    connect (m_octave_qt_link, SIGNAL (clear_workspace_signal (void)),
+             m_workspace_model, SLOT (clear_workspace (void)));
+
+    connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
+             this, SLOT (change_directory (QString)));
+
+    connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
+             m_file_browser_window, SLOT (update_octave_directory (QString)));
+
+    connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
+             m_editor_window, SLOT (update_octave_directory (QString)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (execute_command_in_terminal_signal (QString)),
+             this, SLOT (execute_command_in_terminal (QString)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (set_history_signal (const QStringList&)),
+             m_history_window, SLOT (set_history (const QStringList&)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (append_history_signal (const QString&)),
+             m_history_window, SLOT (append_history (const QString&)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (clear_history_signal (void)),
+             m_history_window, SLOT (clear_history (void)));
+
+    connect (m_octave_qt_link, SIGNAL (enter_debugger_signal (void)),
+             this, SLOT (handle_enter_debugger (void)));
+
+    connect (m_octave_qt_link, SIGNAL (exit_debugger_signal (void)),
+             this, SLOT (handle_exit_debugger (void)));
 
     connect (m_octave_qt_link,
-             SIGNAL (copy_image_to_clipboard_signal (const QString&, bool)),
-             this, SLOT (copy_image_to_clipboard (const QString&, bool)));
-
-    if (m_start_gui)
-      {
-        connect (m_octave_qt_link,
-                 SIGNAL (set_workspace_signal (bool, bool,
-                                               const symbol_scope&)),
-                 m_workspace_model,
-                 SLOT (set_workspace (bool, bool, const symbol_scope&)));
-
-        connect (m_octave_qt_link, SIGNAL (clear_workspace_signal (void)),
-                 m_workspace_model, SLOT (clear_workspace (void)));
-
-        connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
-                 this, SLOT (change_directory (QString)));
-
-        connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
-                 m_file_browser_window, SLOT (update_octave_directory (QString)));
-
-        connect (m_octave_qt_link, SIGNAL (change_directory_signal (QString)),
-                 m_editor_window, SLOT (update_octave_directory (QString)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (execute_command_in_terminal_signal (QString)),
-                 this, SLOT (execute_command_in_terminal (QString)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (set_history_signal (const QStringList&)),
-                 m_history_window, SLOT (set_history (const QStringList&)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (append_history_signal (const QString&)),
-                 m_history_window, SLOT (append_history (const QString&)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (clear_history_signal (void)),
-                 m_history_window, SLOT (clear_history (void)));
-
-        connect (m_octave_qt_link, SIGNAL (enter_debugger_signal (void)),
-                 this, SLOT (handle_enter_debugger (void)));
-
-        connect (m_octave_qt_link, SIGNAL (exit_debugger_signal (void)),
-                 this, SLOT (handle_exit_debugger (void)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (show_preferences_signal (void)),
-                 this, SLOT (process_settings_dialog_request (void)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (gui_preference_signal (const QString&, const QString&,
-                                                QString*)),
-                 this, SLOT (gui_preference (const QString&, const QString&,
-                                             QString*)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (edit_file_signal (const QString&)),
-                 m_active_editor,
-                 SLOT (handle_edit_file_request (const QString&)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
-                 this,
-                 SLOT (handle_insert_debugger_pointer_request (const QString&,
-                                                               int)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
-                 this,
-                 SLOT (handle_delete_debugger_pointer_request (const QString&,
-                                                               int)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (update_breakpoint_marker_signal (bool, const QString&,
-                                                          int, const QString&)),
-                 this,
-                 SLOT (handle_update_breakpoint_marker_request (bool, const QString&,
-                                                                int, const QString&)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (show_doc_signal (const QString &)),
-                 this, SLOT (handle_show_doc (const QString &)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (register_doc_signal (const QString &)),
-                 this, SLOT (handle_register_doc (const QString &)));
-
-        connect (m_octave_qt_link,
-                 SIGNAL (unregister_doc_signal (const QString &)),
-                 this, SLOT (handle_unregister_doc (const QString &)));
-      }
-
-    // Defer initializing and executing the interpreter until after the main
-    // window and QApplication are running to prevent race conditions
-    QTimer::singleShot (0, m_interpreter, SLOT (execute (void)));
+             SIGNAL (show_preferences_signal (void)),
+             this, SLOT (process_settings_dialog_request (void)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (gui_preference_signal (const QString&, const QString&,
+                                            QString*)),
+             this, SLOT (gui_preference (const QString&, const QString&,
+                                         QString*)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (edit_file_signal (const QString&)),
+             m_active_editor,
+             SLOT (handle_edit_file_request (const QString&)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
+             this,
+             SLOT (handle_insert_debugger_pointer_request (const QString&,
+                                                           int)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
+             this,
+             SLOT (handle_delete_debugger_pointer_request (const QString&,
+                                                           int)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (update_breakpoint_marker_signal (bool, const QString&,
+                                                      int, const QString&)),
+             this,
+             SLOT (handle_update_breakpoint_marker_request (bool, const QString&,
+                                                            int, const QString&)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (show_doc_signal (const QString &)),
+             this, SLOT (handle_show_doc (const QString &)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (register_doc_signal (const QString &)),
+             this, SLOT (handle_register_doc (const QString &)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (unregister_doc_signal (const QString &)),
+             this, SLOT (handle_unregister_doc (const QString &)));
   }
 
   QAction* main_window::add_action (QMenu *menu, const QIcon& icon,
@@ -2874,4 +2715,297 @@
 
     emit finished ();
   }
+
+  octave_qt_app::octave_qt_app (gui_application& app_context)
+    : QObject (), m_app_context (app_context),
+      m_argc (m_app_context.sys_argc ()),
+      m_argv (m_app_context.sys_argv ()), m_qt_app (nullptr),
+      m_qt_tr (new QTranslator ()), m_gui_tr (new QTranslator ()),
+      m_qsci_tr (new QTranslator ()), m_translators_installed (false),
+      m_octave_qt_link (new octave_qt_link ()),
+      m_interpreter (new octave_interpreter (m_app_context)),
+      m_main_thread (new QThread ()),
+      m_main_window (nullptr)
+  {
+    std::string show_gui_msgs =
+      sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
+
+    // Installing our handler suppresses the messages.
+
+    if (show_gui_msgs.empty ())
+      {
+#if defined (HAVE_QINSTALLMESSAGEHANDLER)
+        qInstallMessageHandler (message_handler);
+#else
+        qInstallMsgHandler (message_handler);
+#endif
+      }
+
+    // Set the codec for all strings (before wizard or any GUI object)
+#if ! defined (Q_OS_WIN32)
+    QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8"));
+#endif
+
+#if defined (HAVE_QT4)
+    QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
+#endif
+
+    // Initialize global Qt application metadata.
+
+    QCoreApplication::setApplicationName ("GNU Octave");
+    QCoreApplication::setApplicationVersion (OCTAVE_VERSION);
+
+    // Register octave_value_list for connecting thread crossing signals.
+
+    qRegisterMetaType<octave_value_list> ("octave_value_list");
+
+    // Even if START_GUI is false, we still set up the QApplication so
+    // that we can use Qt widgets for plot windows.
+
+    m_qt_app = new QApplication (m_argc, m_argv);
+
+    // set windows style for windows
+#if defined (Q_OS_WIN32)
+    m_qt_app->setStyle (QStyleFactory::create ("Windows"));
+#endif
+
+    // Force left-to-right alignment (see bug #46204)
+    m_qt_app->setLayoutDirection (Qt::LeftToRight);
+
+    octave_link::connect_link (m_octave_qt_link);
+
+    connect (m_octave_qt_link, SIGNAL (confirm_shutdown_signal (void)),
+             this, SLOT (confirm_shutdown_octave (void)));
+
+    connect (m_octave_qt_link,
+             SIGNAL (copy_image_to_clipboard_signal (const QString&, bool)),
+             this, SLOT (copy_image_to_clipboard (const QString&, bool)));
+
+    connect_uiwidget_links ();
+
+    connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
+             this, SLOT (handle_octave_finished (int)));
+
+    connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
+             m_main_thread, SLOT (quit (void)));
+
+    connect (m_main_thread, SIGNAL (finished (void)),
+             m_main_thread, SLOT (deleteLater (void)));
+
+    if (m_app_context.start_gui_p ())
+      create_main_window ();
+    else
+      {
+        // Get settings file.
+        resource_manager::reload_settings ();
+
+        // After settings.
+        config_translators ();
+
+        m_qt_app->setQuitOnLastWindowClosed (false);
+      }
+
+    // Defer initializing and executing the interpreter until after the main
+    // window and QApplication are running to prevent race conditions
+    QTimer::singleShot (0, m_interpreter, SLOT (execute (void)));
+
+    m_interpreter->moveToThread (m_main_thread);
+
+    m_main_thread->start ();
+  }
+
+  octave_qt_app::~octave_qt_app (void)
+  {
+    delete m_main_window;
+    delete m_interpreter;
+    delete m_qt_app;
+
+    string_vector::delete_c_str_vec (m_argv);
+  }
+
+  void octave_qt_app::config_translators (void)
+  {
+    if (m_translators_installed)
+      return;
+
+    resource_manager::config_translators (m_qt_tr, m_qsci_tr, m_gui_tr);
+
+    m_qt_app->installTranslator (m_qt_tr);
+    m_qt_app->installTranslator (m_gui_tr);
+    m_qt_app->installTranslator (m_qsci_tr);
+
+    m_translators_installed = true;
+  }
+
+  void octave_qt_app::create_main_window (void)
+  {
+    m_main_window = new main_window (*this, m_octave_qt_link);
+
+    connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
+             m_main_window, SLOT (handle_octave_ready (void)));
+
+    m_app_context.gui_running (true);
+  }
+
+  int octave_qt_app::exec (void)
+  {
+    return m_qt_app->exec ();
+  }
+
+  void octave_qt_app::handle_octave_finished (int exit_status)
+  {
+    qApp->exit (exit_status);
+  }
+
+  void octave_qt_app::confirm_shutdown_octave (void)
+  {
+    bool closenow = true;
+
+    if (m_main_window)
+      closenow = m_main_window->confirm_shutdown_octave ();
+
+    // Wait for link thread to go to sleep state.
+    m_octave_qt_link->lock ();
+
+    m_octave_qt_link->shutdown_confirmation (closenow);
+
+    m_octave_qt_link->unlock ();
+
+    // Awake the worker thread so that it continues shutting down (or not).
+    m_octave_qt_link->wake_all ();
+  }
+
+  void octave_qt_app::copy_image_to_clipboard (const QString& file,
+                                                bool remove_file)
+  {
+    QClipboard *clipboard = QApplication::clipboard ();
+
+    QImage img (file);
+
+    if (img.isNull ())
+      {
+        // Report error?
+        return;
+      }
+
+    clipboard->setImage (img);
+
+    if (remove_file)
+      QFile::remove (file);
+  }
+
+  // Create a message dialog with specified string, buttons and decorative
+  // text.
+
+  void octave_qt_app::handle_create_dialog (const QString& message,
+                                            const QString& title,
+                                            const QString& icon,
+                                            const QStringList& button,
+                                            const QString& defbutton,
+                                            const QStringList& role)
+  {
+    MessageDialog *message_dialog = new MessageDialog (message, title, icon,
+                                                       button, defbutton, role);
+    message_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    message_dialog->show ();
+  }
+
+  // Create a list dialog with specified list, initially selected, mode,
+  // view size and decorative text.
+
+  void octave_qt_app::handle_create_listview (const QStringList& list,
+                                              const QString& mode,
+                                              int wd, int ht,
+                                              const QIntList& initial,
+                                              const QString& name,
+                                              const QStringList& prompt,
+                                              const QString& ok_string,
+                                              const QString& cancel_string)
+  {
+    ListDialog *list_dialog = new ListDialog (list, mode, wd, ht,
+                                              initial, name, prompt,
+                                              ok_string, cancel_string);
+
+    list_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    list_dialog->show ();
+  }
+
+  // Create an input dialog with specified prompts and defaults, title and
+  // row/column size specifications.
+  void octave_qt_app::handle_create_inputlayout (const QStringList& prompt,
+                                                 const QString& title,
+                                                 const QFloatList& nr,
+                                                 const QFloatList& nc,
+                                                 const QStringList& defaults)
+  {
+    InputDialog *input_dialog = new InputDialog (prompt, title, nr, nc,
+                                                 defaults);
+
+    input_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    input_dialog->show ();
+  }
+
+  void octave_qt_app::handle_create_filedialog (const QStringList& filters,
+                                                const QString& title,
+                                                const QString& filename,
+                                                const QString& dirname,
+                                                const QString& multimode)
+  {
+    FileDialog *file_dialog = new FileDialog (filters, title, filename,
+                                              dirname, multimode);
+
+    file_dialog->setAttribute (Qt::WA_DeleteOnClose);
+    file_dialog->show ();
+  }
+
+  // Connect the signals emitted when the Octave thread wants to create
+  // a dialog box of some sort.  Perhaps a better place for this would be
+  // as part of the QUIWidgetCreator class.  However, mainWindow currently
+  // is not a global variable and not accessible for connecting.
+
+  void octave_qt_app::connect_uiwidget_links (void)
+  {
+    connect (&uiwidget_creator,
+             SIGNAL (create_dialog (const QString&, const QString&,
+                                    const QString&, const QStringList&,
+                                    const QString&, const QStringList&)),
+             this,
+             SLOT (handle_create_dialog (const QString&, const QString&,
+                                         const QString&, const QStringList&,
+                                         const QString&, const QStringList&)));
+
+    // Register QIntList so that list of ints may be part of a signal.
+    qRegisterMetaType<QIntList> ("QIntList");
+    connect (&uiwidget_creator,
+             SIGNAL (create_listview (const QStringList&, const QString&,
+                                      int, int, const QIntList&,
+                                      const QString&, const QStringList&,
+                                      const QString&, const QString&)),
+             this,
+             SLOT (handle_create_listview (const QStringList&, const QString&,
+                                           int, int, const QIntList&,
+                                           const QString&, const QStringList&,
+                                           const QString&, const QString&)));
+
+    // Register QFloatList so that list of floats may be part of a signal.
+    qRegisterMetaType<QFloatList> ("QFloatList");
+    connect (&uiwidget_creator,
+             SIGNAL (create_inputlayout (const QStringList&, const QString&,
+                                         const QFloatList&, const QFloatList&,
+                                         const QStringList&)),
+             this,
+             SLOT (handle_create_inputlayout (const QStringList&, const QString&,
+                                              const QFloatList&,
+                                              const QFloatList&,
+                                              const QStringList&)));
+
+    connect (&uiwidget_creator,
+             SIGNAL (create_filedialog (const QStringList &,const QString&,
+                                        const QString&, const QString&,
+                                        const QString&)),
+             this,
+             SLOT (handle_create_filedialog (const QStringList &, const QString&,
+                                             const QString&, const QString&,
+                                             const QString&)));
+  }
 }
--- a/libgui/src/main-window.h	Fri Oct 19 01:11:17 2018 -0400
+++ b/libgui/src/main-window.h	Thu Oct 18 22:17:40 2018 -0400
@@ -33,6 +33,7 @@
 #include <QQueue>
 #include <QCloseEvent>
 #include <QToolButton>
+#include <QTranslator>
 #include <QComboBox>
 #include <QPointer>
 
@@ -71,7 +72,7 @@
 
   public:
 
-    octave_interpreter (gui_application *app_context);
+    octave_interpreter (gui_application& app_context);
 
     ~octave_interpreter (void) = default;
 
@@ -88,9 +89,11 @@
 
   private:
 
-    gui_application *m_app_context;
+    gui_application& m_app_context;
   };
 
+  class octave_qt_app;
+
   //! Represents the main window.
 
   class main_window : public QMainWindow
@@ -102,7 +105,7 @@
     typedef std::pair <std::string, std::string> name_pair;
     typedef std::pair <int, int> int_pair;
 
-    main_window (QWidget *parent, gui_application *app_context);
+    main_window (octave_qt_app& oct_qt_app, octave_qt_link *oct_qt_lnk);
 
     ~main_window (void);
 
@@ -167,11 +170,9 @@
     void process_settings_dialog_request (const QString& desired_tab
                                           = QString ());
 
-    void copy_image_to_clipboard (const QString& file, bool remove_file);
-
     void show_about_octave (void);
     void notice_settings (const QSettings *settings);
-    void confirm_shutdown_octave (void);
+    bool confirm_shutdown_octave (void);
     void prepare_to_exit (void);
     void reset_windows (void);
 
@@ -216,31 +217,6 @@
     void pasteClipboard (void);
     void selectAll (void);
 
-    void connect_uiwidget_links (void);
-
-    void handle_create_dialog (const QString& message, const QString& title,
-                               const QString& icon, const QStringList& button,
-                               const QString& defbutton,
-                               const QStringList& role);
-
-    void handle_create_listview (const QStringList& list, const QString& mode,
-                                 int width, int height,
-                                 const QIntList& initial,
-                                 const QString& name,
-                                 const QStringList& prompt,
-                                 const QString& ok_string,
-                                 const QString& cancel_string);
-
-    void handle_create_inputlayout (const QStringList&, const QString&,
-                                    const QFloatList&, const QFloatList&,
-                                    const QStringList&);
-
-    void handle_create_filedialog (const QStringList& filters,
-                                   const QString& title,
-                                   const QString& filename,
-                                   const QString& dirname,
-                                   const QString& multimode);
-
     void gui_preference (const QString& key, const QString& value,
                          QString* read_value);
     void handle_show_doc (const QString& file);
@@ -248,7 +224,6 @@
     void handle_unregister_doc (const QString& file);
 
     void handle_octave_ready ();
-    void handle_octave_finished (int);
 
     //! Find files dialog.
     //!@{
@@ -275,8 +250,6 @@
       m_cmd_queue.add_cmd (cmd);
     }
 
-
-
     //! Returns a list of dock widgets.
 
     QList<octave_dock_widget *> get_dock_widget_list (void)
@@ -305,6 +278,8 @@
 
   private:
 
+    void construct_central_widget (void);
+
     void construct (void);
 
     void construct_octave_qt_link (void);
@@ -357,11 +332,7 @@
 
     QList<octave_dock_widget *> dock_widget_list (void);
 
-    gui_application *m_app_context;
-
-    octave_interpreter *m_interpreter;
-
-    QThread *m_main_thread;
+    octave_qt_link *m_octave_qt_link;
 
     workspace_model *m_workspace_model;
 
@@ -469,8 +440,6 @@
 
     QWidget *m_community_news_window;
 
-    octave_qt_link *m_octave_qt_link;
-
     QClipboard *m_clipboard;
 
     //! Command queue and semaphore to synchronize execution signals and
@@ -482,7 +451,6 @@
     //!@{
     bool m_prevent_readline_conflicts;
     bool m_suppress_dbg_location;
-    bool m_start_gui;
 
     //! Flag for closing the whole application.
 
@@ -521,6 +489,82 @@
     int m_serial;
     bool m_connect_to_web;
   };
+
+  class octave_qt_app : public QObject
+  {
+    Q_OBJECT
+
+  public:
+
+    octave_qt_app (gui_application& app_context);
+
+    ~octave_qt_app (void);
+
+    void config_translators (void);
+
+    void create_main_window (void);
+
+    int exec (void);
+
+  public slots:
+
+    void handle_octave_finished (int);
+
+    void confirm_shutdown_octave (void);
+
+    void copy_image_to_clipboard (const QString& file, bool remove_file);
+
+    void handle_create_dialog (const QString& message, const QString& title,
+                               const QString& icon, const QStringList& button,
+                               const QString& defbutton,
+                               const QStringList& role);
+
+    void handle_create_listview (const QStringList& list, const QString& mode,
+                                 int width, int height,
+                                 const QIntList& initial,
+                                 const QString& name,
+                                 const QStringList& prompt,
+                                 const QString& ok_string,
+                                 const QString& cancel_string);
+
+    void handle_create_inputlayout (const QStringList&, const QString&,
+                                    const QFloatList&, const QFloatList&,
+                                    const QStringList&);
+
+    void handle_create_filedialog (const QStringList& filters,
+                                   const QString& title,
+                                   const QString& filename,
+                                   const QString& dirname,
+                                   const QString& multimode);
+
+  private:
+
+    gui_application& m_app_context;
+
+    // Use these to ensure that argc and argv exist for as long as the
+    // QApplication object.
+
+    int m_argc;
+    char **m_argv;
+
+    QApplication *m_qt_app;
+
+    QTranslator *m_qt_tr;
+    QTranslator *m_gui_tr;
+    QTranslator *m_qsci_tr;
+
+    bool m_translators_installed;
+
+    octave_qt_link *m_octave_qt_link;
+
+    octave_interpreter *m_interpreter;
+
+    QThread *m_main_thread;
+
+    main_window *m_main_window;
+
+    void connect_uiwidget_links (void);
+  };
 }
 
 #endif
--- a/libgui/src/octave-gui.cc	Fri Oct 19 01:11:17 2018 -0400
+++ b/libgui/src/octave-gui.cc	Thu Oct 18 22:17:40 2018 -0400
@@ -24,21 +24,6 @@
 #  include "config.h"
 #endif
 
-#include <QApplication>
-#include <QTextCodec>
-#include <QThread>
-#include <QTranslator>
-#include <QtGlobal>
-#include <QStyleFactory>
-
-#include <cstdio>
-
-#include <iostream>
-
-#if defined (HAVE_SYS_IOCTL_H)
-#  include <sys/ioctl.h>
-#endif
-
 #include "lo-utils.h"
 #include "oct-env.h"
 #include "oct-syscalls.h"
@@ -48,29 +33,14 @@
 #include "display.h"
 #include "octave.h"
 #include "sysdep.h"
-#include "unistd-wrappers.h"
 
 #include "main-window.h"
 #include "octave-gui.h"
-#include "resource-manager.h"
-#include "shortcut-manager.h"
-#include "welcome-wizard.h"
-
-// Disable all Qt messages by default.
-
-static void
-#if defined (QTMESSAGEHANDLER_ACCEPTS_QMESSAGELOGCONTEXT)
-message_handler (QtMsgType, const QMessageLogContext &, const QString &)
-#else
-message_handler (QtMsgType, const char *)
-#endif
-{ }
 
 namespace octave
 {
   gui_application::gui_application (int argc, char **argv)
-    : application (argc, argv), m_argc (argc), m_argv (argv),
-      m_gui_running (false)
+    : application (argc, argv)
   {
     // This should probably happen early.
     sysdep_init ();
@@ -87,117 +57,10 @@
 
     set_application_id ();
 
-    std::string show_gui_msgs =
-      sys::env::getenv ("OCTAVE_SHOW_GUI_MESSAGES");
-
-    // Installing our handler suppresses the messages.
-
-    if (show_gui_msgs.empty ())
-      {
-#if defined (HAVE_QINSTALLMESSAGEHANDLER)
-        qInstallMessageHandler (message_handler);
-#else
-        qInstallMsgHandler (message_handler);
-#endif
-      }
-
-    // If START_GUI is false, we still set up the QApplication so that
-    // we can use Qt widgets for plot windows.
-
-    QApplication qt_app (m_argc, m_argv);
-    QTranslator gui_tr, qt_tr, qsci_tr;
-
-    // Set the codec for all strings (before wizard or any GUI object)
-#if ! defined (Q_OS_WIN32)
-    QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8"));
-#endif
-
-#if defined (HAVE_QT4)
-    QTextCodec::setCodecForCStrings (QTextCodec::codecForName ("UTF-8"));
-#endif
-
-    // set windows style for windows
-#if defined (Q_OS_WIN32)
-    qt_app.setStyle (QStyleFactory::create ("Windows"));
-#endif
-
-    bool start_gui = start_gui_p ();
-
-    // Show welcome wizard if this is the first run.
-
-    if (resource_manager::is_first_run () && start_gui)
-      {
-        // Before wizard.
-        resource_manager::config_translators (&qt_tr, &qsci_tr, &gui_tr);
-
-        qt_app.installTranslator (&qt_tr);
-        qt_app.installTranslator (&gui_tr);
-        qt_app.installTranslator (&qsci_tr);
-
-        welcome_wizard welcomeWizard;
-
-        if (welcomeWizard.exec () == QDialog::Rejected)
-          exit (1);
-
-        // Install settings file.
-        resource_manager::reload_settings ();
-      }
-    else
-      {
-        // Get settings file.
-        resource_manager::reload_settings ();
-
-        // After settings.
-        resource_manager::config_translators (&qt_tr, &qsci_tr, &gui_tr);
-
-        qt_app.installTranslator (&qt_tr);
-        qt_app.installTranslator (&gui_tr);
-
-        if (start_gui)
-          qt_app.installTranslator (&qsci_tr);
-      }
-
-    if (start_gui)
-      {
-        resource_manager::update_network_settings ();
-
-        // We provide specific terminal capabilities, so ensure that
-        // TERM is always set appropriately.
-
-#if defined (OCTAVE_USE_WINDOWS_API)
-        sys::env::putenv ("TERM", "cygwin");
-#else
-        sys::env::putenv ("TERM", "xterm");
-#endif
-
-        shortcut_manager::init_data ();
-      }
-
-    // Force left-to-right alignment (see bug #46204)
-    qt_app.setLayoutDirection (Qt::LeftToRight);
-
     // Create and show main window.
 
-    main_window w (nullptr, this);
-
-    if (start_gui)
-      {
-        w.read_settings ();
-
-        w.init_terminal_size ();
-
-        // Connect signals for changes in visibility not before w
-        // is shown.
+    octave_qt_app oct_qt_app (*this);
 
-        w.connect_visibility_changed ();
-
-        w.focus_command_window ();
-
-        gui_running (true);
-      }
-    else
-      qt_app.setQuitOnLastWindowClosed (false);
-
-    return qt_app.exec ();
+    return oct_qt_app.exec ();
   }
 }
--- a/libgui/src/octave-gui.h	Fri Oct 19 01:11:17 2018 -0400
+++ b/libgui/src/octave-gui.h	Thu Oct 18 22:17:40 2018 -0400
@@ -39,6 +39,8 @@
 
     gui_application& operator = (const gui_application&) = delete;
 
+    ~gui_application (void) = default;
+
     // Should we start the GUI or fall back to the CLI?
     bool start_gui_p (void) const;
 
@@ -51,7 +53,9 @@
 
     int m_argc;
     char **m_argv;
-    bool m_gui_running;
+
+    // If TRUE, the GUI should be started.
+    bool m_gui_running = false;
   };
 }
 
--- a/libgui/src/octave-qt-link.cc	Fri Oct 19 01:11:17 2018 -0400
+++ b/libgui/src/octave-qt-link.cc	Thu Oct 18 22:17:40 2018 -0400
@@ -409,6 +409,7 @@
   void octave_qt_link::do_file_remove (const std::string& old_name,
                                        const std::string& new_name)
   {
+    return;
     // Lock the mutex before signaling
     lock ();
 
--- a/libinterp/octave.h	Fri Oct 19 01:11:17 2018 -0400
+++ b/libinterp/octave.h	Thu Oct 18 22:17:40 2018 -0400
@@ -358,9 +358,6 @@
     // from eval without persist.
     bool m_is_octave_program = false;
 
-    // If TRUE, the GUI should be started.
-    bool m_gui_running = false;
-
     interpreter *m_interpreter = nullptr;
   };