changeset 29613:9367cba2a6d5

allow most dock widgets to be used from command line This change is an initial attempt to allow the documentation, file, history, variable editor, and workspace widgets to be opened from the command line. While running in command line mode, some connections between those widgets and the interpreter or between two widgets may be missing. The aim is to eventually make those work but this is a good start. These dock widgets are now owned by the base_qobject object and shared with the main_window object. If they exist when the main_window is created (possible if using the new terminal widget) then a pointer to the main_window object is passed to the dock_widget so that they may be docked there. If the desktop is closed and control returns to the command line, undocked widgets remain available. * octave-qobject.h, octave-qobject.cc (base_qobject::m_documentation_widget, base_qobject::m_file_browser_widget, base_qobject::m_history_widget, base_qobject::m_workspace_widget, base_qobject::m_editor_widget, base_qobject::m_variable_editor_widget): New data members. (base_qobject::documentation_widget, base_qobject::file_browser_widget, base_qobject::history_widget, base_qobject::workspace_widget, base_qobject::editor_widget, base_qobject::variable_editor_widget): New functions to create dock widgets as needed. (base_qobject::show_documentation_window, base_qobject::show_file_browser_window, base_qobject::show_command_history_window, base_qobject::show_workspace_window, base_qobject::edit_variable, base_qobject::handle_variable_editor_update): New functions. Make signal slot connections that do not require the main window here, not in main_window::construct_octave_qt_link. * files-dock-widget.cc (files_dock_widget::files_dock_widget): If no parent, call make_window. * documentation-dock-widget.cc (documentation_dock_widget::documentation_dock_widget): Likewise. * history-dock-widget.cc (history_dock_widget::history_dock_widget): Likewise. * workspace-view.cc (workspace_view::workspace_view): Likewise. * doc.m: Always give the event manager a chance to display the documentation, not just if the GUI is running. * documentation.cc (documentation::documentation): Make sub-objects children of the documentation object, not children of the parent of the documentation object. * main-window.h, main-window.cc (main_window::m_command_window, main_window::m_history_window, main_window::m_file_browser_window, main_window::m_doc_browser_window, main_window::m_editor_window, main_window::m_workspace_window, main_window::m_variable_editor_window): Manage objects with QPointer. (main_window::main_window): Acquire m_doc_browser_window, m_history_window, m_workspace_window, and m_variable_editor_window from octave_qobj. * octave-dock-widget.cc (octave_dock_widget::octave_dock_widget): Don't reference m_parent if it is nullptr. (octave_dock_widget::handle_settings): Likewise. Return immediately if settings is nullptr. (octave_dock_widget::set_main_window): New function. * variable-editor.h, variable-editor.cc (variable_editor::~variable_editor): Explicitly delete m_tool_bar and set it to nullptr. (variable_editor::edit_variable, variable_editor::notice_settings, variable_editor::variable_destroyed): Avoid referencing m_tool_bar if it is nullptr. * qt-interpreter-events.h, qt-interpreter-events.cc (qt_interpreter_events::show_documentation): Rename from show_doc. Change all uses. (qt_interpreter_events::register_documentation): Rename from register_doc. Change all uses. (qt_interpreter_events::unregister_documentation): Rename from unregister_doc. Change all uses. (qt_interpreter_events::show_file_browser, qt_interpreter_events::show_command_history, qt_interpreter_events::show_workspace): New functions. (qt_interpreter_events::show_documentation_signal): Rename from show_doc_signal. Change all uses. qt_interpreter_events::register_documentation_signal): Rename from register_doc_signal. Change all uses. qt_interpreter_events::unregister_documentation_signal): Rename from unregister_doc_signal. Change all uses. (qt_interpreter_events::show_file_browser_signal, qt_interpreter_events::show_command_history_signal, qt_interpreter_events::show_workspace_signal): New signals. * event-manager.h, event-manager.cc (F__event_manager_show_file_browser__, F__event_manager_show_command_history__, F__event_manager_show_workspace__): New functions. (F__event_manager_show_documentation__): Rename from __event_manager_show_doc__. Change all uses. (F__event_manager_register_documentation__): Rename from F__event_manager_register_doc__. Change all uses. (F__event_manager_unregister_documentation__): Rename from F__event_manager_unregister_doc__. Change all uses. (Fopenvar): Don't require GUI to be running. (interpreter_events::show_documentation): Rename from show_doc. Change all uses. (interpreter_events::register_documentation): Rename from register_doc. Change all uses. (interpreter_events::unregister_documentation): Rename from unregister_doc. Change all uses. (interpreter_events::show_file_browser, interpreter_events::show_command_history, interpreter_events::show_workspace): New functions. (event_manager::show_documentation): Rename from show_doc. Change all uses. (event_manager::register_documentation): Rename from register_doc. Change all uses. (event_manager::register_documentation): Rename from unregister_doc. Change all uses.
author John W. Eaton <jwe@octave.org>
date Thu, 29 Apr 2021 11:12:40 -0400
parents 9c04fea333ca
children f6151f915e3c
files libgui/src/documentation-dock-widget.cc libgui/src/documentation.cc libgui/src/files-dock-widget.cc libgui/src/history-dock-widget.cc libgui/src/m-editor/file-editor-interface.h libgui/src/m-editor/octave-qscintilla.cc libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-dock-widget.cc libgui/src/octave-dock-widget.h libgui/src/octave-qobject.cc libgui/src/octave-qobject.h libgui/src/qt-interpreter-events.cc libgui/src/qt-interpreter-events.h libgui/src/variable-editor.cc libgui/src/variable-editor.h libgui/src/workspace-view.cc libinterp/corefcn/event-manager.cc libinterp/corefcn/event-manager.h scripts/help/doc.m
diffstat 20 files changed, 666 insertions(+), 208 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/documentation-dock-widget.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/documentation-dock-widget.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -43,6 +43,9 @@
     setStatusTip (tr ("See the documentation for help."));
 
     setWidget (m_docs);
+
+    if (! p)
+      make_window ();
   }
 
   void documentation_dock_widget::notice_settings (const gui_settings *settings)
--- a/libgui/src/documentation.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/documentation.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -66,15 +66,15 @@
   // of the doc dock widget
   documentation::documentation (QWidget *p, base_qobject& oct_qobj)
     : QSplitter (Qt::Horizontal, p),
-      m_octave_qobj (oct_qobj), m_doc_widget (p),
-      m_tool_bar (new QToolBar (p)),
+      m_octave_qobj (oct_qobj), m_doc_widget (this),
+      m_tool_bar (new QToolBar (this)),
       m_query_string (QString ()),
-      m_prev_pages_menu (new QMenu (p)),
-      m_next_pages_menu (new QMenu (p)),
+      m_prev_pages_menu (new QMenu (this)),
+      m_next_pages_menu (new QMenu (this)),
       m_prev_pages_count (0),
       m_next_pages_count (0),
-      m_findnext_shortcut (new QShortcut (p)),
-      m_findprev_shortcut (new QShortcut (p))
+      m_findnext_shortcut (new QShortcut (this)),
+      m_findprev_shortcut (new QShortcut (this))
   {
     // Get original collection
     QString collection = getenv ("OCTAVE_QTHELP_COLLECTION");
@@ -351,6 +351,7 @@
     m_action_go_home
       = add_action (rmgr.icon ("go-home"), tr ("Go home"), SLOT (home (void)),
                     m_doc_browser, m_tool_bar);
+
     m_action_go_prev
       = add_action (rmgr.icon ("go-previous"), tr ("Go back"),
                     SLOT (backward (void)), m_doc_browser, m_tool_bar);
@@ -365,6 +366,7 @@
     popdown_button_prev_pages->setCheckable (false);
     popdown_button_prev_pages->setArrowType(Qt::DownArrow);
     m_tool_bar->addWidget (popdown_button_prev_pages);
+
     m_action_go_next
       = add_action (rmgr.icon ("go-next"), tr ("Go forward"),
                     SLOT (forward (void)), m_doc_browser, m_tool_bar);
--- a/libgui/src/files-dock-widget.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/files-dock-widget.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -298,6 +298,9 @@
 
     m_sync_octave_dir = true;   // default, overwritten with notice_settings ()
     m_octave_dir = "";
+
+    if (! p)
+      make_window ();
   }
 
   void files_dock_widget::save_settings (void)
--- a/libgui/src/history-dock-widget.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/history-dock-widget.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -53,6 +53,9 @@
     setStatusTip (tr ("Browse and search the command history."));
 
     construct ();
+
+    if (! p)
+      make_window ();
   }
 
   void history_dock_widget::set_history (const QStringList& hist)
--- a/libgui/src/m-editor/file-editor-interface.h	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/m-editor/file-editor-interface.h	Thu Apr 29 11:12:40 2021 -0400
@@ -27,6 +27,7 @@
 #define octave_file_editor_interface_h 1
 
 #include <QMenu>
+#include <QMenuBar>
 #include <QToolBar>
 
 #include "gui-settings.h"
--- a/libgui/src/m-editor/octave-qscintilla.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -59,6 +59,7 @@
 #include "octave-qobject.h"
 #include "octave-qscintilla.h"
 #include "shortcut-manager.h"
+#include "workspace-model.h"
 
 #include "builtin-defun-decls.h"
 #include "cmd-edit.h"
--- a/libgui/src/main-window.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/main-window.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -97,11 +97,12 @@
 {
   main_window::main_window (base_qobject& oct_qobj)
     : QMainWindow (), m_octave_qobj (oct_qobj),
-      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_status_bar (nullptr),
+      m_command_window (nullptr),
+      m_history_window (nullptr),
+      m_file_browser_window (nullptr),
+      m_editor_window (nullptr),
+      m_workspace_window (nullptr),
       m_external_editor (new external_editor_interface (this, m_octave_qobj)),
       m_active_editor (m_external_editor), m_settings_dlg (nullptr),
       m_find_files_dlg (nullptr), m_set_path_dlg (nullptr),
@@ -154,8 +155,6 @@
     shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
     scmgr.init_data ();
 
-    m_workspace_model = m_octave_qobj.get_workspace_model ();
-
     construct_central_widget ();
 
     m_status_bar = new QStatusBar (this);
@@ -171,20 +170,11 @@
     connect (this, &main_window::settings_changed,
              m_command_window, &terminal_dock_widget::notice_settings);
 
-    m_history_window = new history_dock_widget (this, m_octave_qobj);
-
-    make_dock_widget_connections (m_history_window);
-
-    connect (m_history_window, &history_dock_widget::command_create_script,
-             this, &main_window::new_file_signal);
-
-    connect (m_history_window, &history_dock_widget::information,
-             this, &main_window::report_status_message);
-
-    connect (m_history_window, &history_dock_widget::command_double_clicked,
-             this, &main_window::execute_command_in_terminal);
-
-    m_file_browser_window = new files_dock_widget (this, m_octave_qobj);
+    m_doc_browser_window = m_octave_qobj.documentation_widget (this);
+
+    make_dock_widget_connections (m_doc_browser_window);
+
+    m_file_browser_window = m_octave_qobj.file_browser_widget (this);
 
     make_dock_widget_connections (m_file_browser_window);
 
@@ -198,9 +188,28 @@
     connect (m_file_browser_window, &files_dock_widget::run_file_signal,
              this, &main_window::run_file_in_terminal);
 
-    m_doc_browser_window = new documentation_dock_widget (this, m_octave_qobj);
-
-    make_dock_widget_connections (m_doc_browser_window);
+    m_history_window = m_octave_qobj.history_widget (this);
+
+    make_dock_widget_connections (m_history_window);
+
+    connect (m_history_window, &history_dock_widget::command_create_script,
+             this, &main_window::new_file_signal);
+
+    connect (m_history_window, &history_dock_widget::information,
+             this, &main_window::report_status_message);
+
+    connect (m_history_window, &history_dock_widget::command_double_clicked,
+             this, &main_window::execute_command_in_terminal);
+
+    m_workspace_window = m_octave_qobj.workspace_widget (this);
+
+    make_dock_widget_connections (m_workspace_window);
+
+    connect (m_workspace_window, &workspace_view::command_requested,
+             this, &main_window::execute_command_in_terminal);
+
+    connect (m_workspace_window, &workspace_view::edit_variable_signal,
+             this, &main_window::edit_variable);
 
 #if defined (HAVE_QSCINTILLA)
     file_editor *editor = new file_editor (this, m_octave_qobj);
@@ -236,23 +245,13 @@
     m_editor_window = nullptr;
 #endif
 
-    m_variable_editor_window = new variable_editor (this, m_octave_qobj);
+    m_variable_editor_window = m_octave_qobj.variable_editor_widget (this);
 
     make_dock_widget_connections (m_variable_editor_window);
 
     connect (m_variable_editor_window, &variable_editor::command_signal,
              this, &main_window::execute_command_in_terminal);
 
-    m_workspace_window = new workspace_view (this, m_octave_qobj);
-
-    make_dock_widget_connections (m_workspace_window);
-
-    connect (m_workspace_window, &workspace_view::command_requested,
-             this, &main_window::execute_command_in_terminal);
-
-    connect (m_workspace_window, &workspace_view::edit_variable_signal,
-             this, &main_window::edit_variable);
-
     m_previous_dock = m_command_window;
 
     // Set active editor depending on editor window.  If the latter is
@@ -322,6 +321,31 @@
     focus_command_window ();
   }
 
+  main_window::~main_window (void)
+  {
+    // Prevent floating dock widgets from being deleted.
+
+    if (m_history_window->isFloating ())
+      m_history_window.clear ();
+
+    if (m_file_browser_window->isFloating ())
+      m_file_browser_window.clear ();
+
+    if (m_doc_browser_window->isFloating ())
+      m_doc_browser_window.clear ();
+
+#if 0
+    if (m_editor_window->isFloating ())
+      m_editor_window.clear ();
+#endif
+
+    if (m_workspace_window->isFloating ())
+      m_workspace_window.clear ();
+
+    if (m_variable_editor_window->isFloating ())
+      m_variable_editor_window.clear ();
+  }
+
   void main_window::make_dock_widget_connections (octave_dock_widget *dw)
   {
     connect (this, &main_window::init_window_menu,
@@ -1943,7 +1967,6 @@
         m_variable_editor_window->show ();
         m_variable_editor_window->raise ();
       }
-
   }
 
   void main_window::refresh_variable_editor (void)
@@ -2075,11 +2098,6 @@
   {
     setWindowIcon (QIcon (":/actions/icons/logo.png"));
 
-    m_workspace_window->setModel (m_workspace_model);
-
-    connect (m_workspace_model, &workspace_model::model_changed,
-             m_workspace_window, &workspace_view::handle_model_changed);
-
     interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
 
     qt_interpreter_events *qt_link = interp_qobj->qt_link ();
@@ -2245,12 +2263,6 @@
                  m_command_window, &terminal_dock_widget::update_prompt);
       }
 
-    connect (qt_link, &qt_interpreter_events::set_workspace_signal,
-             m_workspace_model, &workspace_model::set_workspace);
-
-    connect (qt_link, &qt_interpreter_events::clear_workspace_signal,
-             m_workspace_model, &workspace_model::clear_workspace);
-
     connect (qt_link, &qt_interpreter_events::directory_changed_signal,
              this, &main_window::update_octave_directory);
 
@@ -2263,15 +2275,6 @@
     connect (qt_link, &qt_interpreter_events::execute_command_in_terminal_signal,
              this, &main_window::execute_command_in_terminal);
 
-    connect (qt_link, &qt_interpreter_events::set_history_signal,
-             m_history_window, &history_dock_widget::set_history);
-
-    connect (qt_link, &qt_interpreter_events::append_history_signal,
-             m_history_window, &history_dock_widget::append_history);
-
-    connect (qt_link, &qt_interpreter_events::clear_history_signal,
-             m_history_window, &history_dock_widget::clear_history);
-
     connect (qt_link, &qt_interpreter_events::enter_debugger_signal,
              this, &main_window::handle_enter_debugger);
 
@@ -2295,15 +2298,6 @@
     connect (qt_link, &qt_interpreter_events::update_breakpoint_marker_signal,
              this, &main_window::handle_update_breakpoint_marker_request);
 
-    connect (qt_link, &qt_interpreter_events::show_doc_signal,
-             m_doc_browser_window, &documentation_dock_widget::showDoc);
-
-    connect (qt_link, &qt_interpreter_events::register_doc_signal,
-             m_doc_browser_window, &documentation_dock_widget::registerDoc);
-
-    connect (qt_link, &qt_interpreter_events::unregister_doc_signal,
-             m_doc_browser_window, &documentation_dock_widget::unregisterDoc);
-
     connect (qt_link, &qt_interpreter_events::gui_status_update_signal,
              this, &main_window::handle_gui_status_update);
 
--- a/libgui/src/main-window.h	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/main-window.h	Thu Apr 29 11:12:40 2021 -0400
@@ -60,7 +60,6 @@
 #include "set-path-dialog.h"
 #include "terminal-dock-widget.h"
 #include "variable-editor.h"
-#include "workspace-model.h"
 #include "workspace-view.h"
 
 class octave_value;
@@ -84,7 +83,7 @@
 
     main_window (base_qobject& oct_qobj);
 
-    ~main_window (void) = default;
+    ~main_window (void);
 
     void make_dock_widget_connections (octave_dock_widget *dw);
 
@@ -308,8 +307,6 @@
 
     base_qobject& m_octave_qobj;
 
-    workspace_model *m_workspace_model;
-
     QHash<QMenu*, QStringList> m_hash_menu_text;
 
     QString m_default_encoding;
@@ -323,13 +320,14 @@
 
     //! Dock widgets.
     //!@{
-    terminal_dock_widget *m_command_window;
-    history_dock_widget *m_history_window;
-    files_dock_widget *m_file_browser_window;
-    documentation_dock_widget *m_doc_browser_window;
-    file_editor_interface *m_editor_window;
-    workspace_view *m_workspace_window;
-    variable_editor *m_variable_editor_window;
+    QPointer<terminal_dock_widget> m_command_window;
+
+    QPointer<history_dock_widget> m_history_window;
+    QPointer<files_dock_widget> m_file_browser_window;
+    QPointer<documentation_dock_widget> m_doc_browser_window;
+    QPointer<file_editor_interface> m_editor_window;
+    QPointer<workspace_view> m_workspace_window;
+    QPointer<variable_editor> m_variable_editor_window;
     //!@}
 
     external_editor_interface *m_external_editor;
--- a/libgui/src/octave-dock-widget.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/octave-dock-widget.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -41,6 +41,7 @@
 #include "gui-preferences-mw.h"
 #include "gui-preferences-sc.h"
 #include "gui-settings.h"
+#include "main-window.h"
 #include "octave-dock-widget.h"
 #include "octave-qobject.h"
 
@@ -189,7 +190,9 @@
   {
     setObjectName (obj_name);
 
-    m_parent = static_cast<QMainWindow *> (p);     // store main window
+    // FIXME: Can we avoid the cast here?
+    m_main_window = dynamic_cast<main_window *> (p);
+
     m_predecessor_widget = nullptr;
 
     connect (this, &octave_dock_widget::topLevelChanged,
@@ -278,10 +281,14 @@
     if (isFloating ())
       setFloating (false);
 
-    // Before making it a separate (no more parent) floating widget, remove
-    // the dock widget from the main window. This ensures that tabbed widgets
-    // keep their focus when it is re-docked later
-    m_parent->removeDockWidget (this);
+    if (m_main_window)
+      {
+        // Before making it a separate (no more parent) floating widget,
+        // remove the dock widget from the main window. This ensures
+        // that tabbed widgets keep their focus when it is re-docked
+        // later
+        m_main_window->removeDockWidget (this);
+      }
 
     setParent (0, Qt::CustomizeWindowHint | Qt::WindowTitleHint |
                Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::Window);
@@ -335,18 +342,22 @@
     resource_manager& rmgr = m_octave_qobj.get_resource_manager ();
     gui_settings *settings = rmgr.get_settings ();
 
-    settings->setValue (mw_state.key, m_parent->saveState ());
-    // Stay window, otherwise will bounce back to window by default because
-    // there is no layout information for this widget in the saved settings.
-    setParent (m_parent, Qt::Window);
-    m_parent->addDockWidget (Qt::BottomDockWidgetArea, this);
-    // recover old window states, hide and re-show new added widget
-    m_parent->restoreState (settings->value (mw_state.key).toByteArray ());
-    setFloating (false);
-    // restore size using setGeometry instead of restoreGeometry following
-    // this post:
-    // https://forum.qt.io/topic/79326/qdockwidget-restoregeometry-not-working-correctly-when-qmainwindow-is-maximized/5
-    setGeometry (m_recent_dock_geom);
+    if (m_main_window)
+      {
+        settings->setValue (mw_state.key, m_main_window->saveState ());
+        // Stay window, otherwise will bounce back to window by default
+        // because there is no layout information for this widget in the
+        // saved settings.
+        setParent (m_main_window, Qt::Window);
+        m_main_window->addDockWidget (Qt::BottomDockWidgetArea, this);
+        // recover old window states, hide and re-show new added widget
+        m_main_window->restoreState (settings->value (mw_state.key).toByteArray ());
+        setFloating (false);
+        // restore size using setGeometry instead of restoreGeometry
+        // following this post:
+        // https://forum.qt.io/topic/79326/qdockwidget-restoregeometry-not-working-correctly-when-qmainwindow-is-maximized/5
+        setGeometry (m_recent_dock_geom);
+      }
 
     // adjust the (un)dock icon
     connect (m_dock_action, &QAction::triggered,
@@ -389,6 +400,27 @@
     m_predecessor_widget = prev_widget;
   }
 
+  void
+  octave_dock_widget::set_main_window (main_window *mw)
+  {
+    m_main_window = mw;
+
+    if (m_main_window)
+      {
+        connect (m_main_window, &main_window::copyClipboard_signal,
+                 this, &octave_dock_widget::copyClipboard);
+
+        connect (m_main_window, &main_window::pasteClipboard_signal,
+                 this, &octave_dock_widget::pasteClipboard);
+
+        connect (m_main_window, &main_window::selectAll_signal,
+                 this, &octave_dock_widget::selectAll);
+
+        connect (m_main_window, &main_window::undo_signal,
+                 this, &octave_dock_widget::do_undo);
+      }
+  }
+
   // close event
   void
   octave_dock_widget::closeEvent (QCloseEvent *e)
@@ -433,6 +465,9 @@
   void
   octave_dock_widget::handle_settings (const gui_settings *settings)
   {
+    if (! settings)
+      return;
+
     m_focus_follows_mouse = settings->value (dw_focus_follows_mouse).toBool ();
 
     m_custom_style
@@ -473,33 +508,38 @@
     else
       m_icon_color_active = "";
 
-    QRect available_size = QApplication::desktop ()->availableGeometry (m_parent);
-    int x, y, w, h;
-    available_size.getRect (&x, &y, &w, &h);
-    QRect default_floating_size = QRect (x+16, y+32, w/3, h/2);
-    m_parent->geometry ().getRect (&x, &y, &w, &h);
-    QRect default_dock_size = QRect (x+16, y+32, w/3, h/3);
+    if (m_main_window)
+      {
+        QRect available_size
+          = QApplication::desktop ()->availableGeometry (m_main_window);
 
-    m_recent_float_geom
-      = settings->value (dw_float_geometry.key.arg (objectName ()),
-                         default_floating_size).toRect ();
+        int x, y, w, h;
+        available_size.getRect (&x, &y, &w, &h);
+        QRect default_floating_size = QRect (x+16, y+32, w/3, h/2);
+        m_main_window->geometry ().getRect (&x, &y, &w, &h);
+        QRect default_dock_size = QRect (x+16, y+32, w/3, h/3);
 
-    QWidget dummy;
-    dummy.setGeometry (m_recent_float_geom);
+        m_recent_float_geom
+          = settings->value (dw_float_geometry.key.arg (objectName ()),
+                             default_floating_size).toRect ();
 
-    if (QApplication::desktop ()->screenNumber (&dummy) == -1)
-      m_recent_float_geom = default_floating_size;
+        QWidget dummy;
+        dummy.setGeometry (m_recent_float_geom);
+
+        if (QApplication::desktop ()->screenNumber (&dummy) == -1)
+          m_recent_float_geom = default_floating_size;
 
-    // The following is required for ensure smooth transition from old
-    // saveGeomety to new QRect setting (see comment for restoring size
-    // of docked widgets)
-    QVariant dock_geom
-      = settings->value (dw_dock_geometry.key.arg (objectName ()),
-                         default_dock_size);
-    if (dock_geom.canConvert (QMetaType::QRect))
-      m_recent_dock_geom = dock_geom.toRect ();
-    else
-      m_recent_dock_geom = dw_dock_geometry.def.toRect ();
+        // The following is required for ensure smooth transition from old
+        // saveGeomety to new QRect setting (see comment for restoring size
+        // of docked widgets)
+        QVariant dock_geom
+          = settings->value (dw_dock_geometry.key.arg (objectName ()),
+                             default_dock_size);
+        if (dock_geom.canConvert (QMetaType::QRect))
+          m_recent_dock_geom = dock_geom.toRect ();
+        else
+          m_recent_dock_geom = dw_dock_geometry.def.toRect ();
+      }
 
     notice_settings (settings);  // call individual handler
 
--- a/libgui/src/octave-dock-widget.h	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/octave-dock-widget.h	Thu Apr 29 11:12:40 2021 -0400
@@ -28,7 +28,6 @@
 
 #include <QDockWidget>
 #include <QIcon>
-#include <QMainWindow>
 #include <QMouseEvent>
 #include <QToolButton>
 
@@ -38,6 +37,7 @@
 namespace octave
 {
   class base_qobject;
+  class main_window;
 
   // The few decoration items common to both main window and variable editor.
 
@@ -49,6 +49,8 @@
 
     label_dock_widget (QWidget *p, base_qobject& oct_qobj);
 
+    ~label_dock_widget (void) = default;
+
     // set_title() uses the custom title bar while setWindowTitle() uses
     // the default title bar (with style sheets)
     void set_title (const QString&);
@@ -90,10 +92,12 @@
     octave_dock_widget (const QString& obj_name, QWidget *p,
                         base_qobject& oct_qobj);
 
-    virtual ~octave_dock_widget (void) = default;
+    ~octave_dock_widget (void) = default;
 
     void set_predecessor_widget (octave_dock_widget *prev_widget);
 
+    void set_main_window (main_window *mw);
+
   signals:
 
     //! Custom signal that tells whether a user has clicked away that dock
@@ -162,7 +166,7 @@
 
     //! Stores the parent, since we are reparenting to 0.
 
-    QMainWindow *m_parent;
+    main_window *m_main_window;
 
     bool m_custom_style;
     bool m_focus_follows_mouse;
--- a/libgui/src/octave-qobject.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/octave-qobject.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -37,6 +37,9 @@
 #include <QTimer>
 #include <QTranslator>
 
+#include "documentation-dock-widget.h"
+#include "files-dock-widget.h"
+#include "history-dock-widget.h"
 #include "interpreter-qobject.h"
 #include "main-window.h"
 #include "octave-qobject.h"
@@ -44,6 +47,9 @@
 #include "qt-interpreter-events.h"
 #include "resource-manager.h"
 #include "shortcut-manager.h"
+#include "variable-editor.h"
+#include "workspace-model.h"
+#include "workspace-view.h"
 
 // Bug #55940 (Disable App Nap on Mac)
 #if defined (Q_OS_MAC)
@@ -162,7 +168,6 @@
       m_qapplication (new octave_qapplication (m_argc, m_argv)),
       m_resource_manager (),
       m_shortcut_manager (*this),
-      m_workspace_model (new workspace_model (*this)),
       m_qt_tr (new QTranslator ()),
       m_gui_tr (new QTranslator ()),
       m_qsci_tr (new QTranslator ()),
@@ -172,6 +177,13 @@
       m_main_thread (new QThread ()),
       m_gui_app (gui_app),
       m_interpreter_ready (false),
+      m_workspace_model (new workspace_model (*this)),
+      m_documentation_widget (),
+      m_file_browser_widget (),
+      m_history_widget (),
+      m_workspace_widget (),
+      m_editor_widget (),
+      m_variable_editor_widget (),
       m_main_window (nullptr)
   {
     std::string show_gui_msgs =
@@ -231,14 +243,29 @@
     connect (qt_link (), &qt_interpreter_events::copy_image_to_clipboard_signal,
              this, &base_qobject::copy_image_to_clipboard);
 
+    // Get settings file.
+    m_resource_manager.reload_settings ();
+
+    // After settings.
+    config_translators ();
+
+    connect (qt_link (), &qt_interpreter_events::show_documentation_signal,
+             this, &base_qobject::show_documentation_window);
+
+    connect (qt_link (), &qt_interpreter_events::show_file_browser_signal,
+             this, &base_qobject::show_file_browser_window);
+
+    connect (qt_link (), &qt_interpreter_events::show_command_history_signal,
+             this, &base_qobject::show_command_history_window);
+
+    connect (qt_link (), &qt_interpreter_events::show_workspace_signal,
+             this, &base_qobject::show_workspace_window);
+
+    connect (qt_link (), &qt_interpreter_events::edit_variable_signal,
+             this, &base_qobject::edit_variable);
+
     if (m_app_context.experimental_terminal_widget ())
       {
-        // Get settings file.
-        m_resource_manager.reload_settings ();
-
-        // After settings.
-        config_translators ();
-
         m_qapplication->setQuitOnLastWindowClosed (false);
       }
     else
@@ -349,6 +376,107 @@
     return m_app_context.gui_running ();
   }
 
+  QPointer<documentation_dock_widget>
+  base_qobject::documentation_widget (main_window *mw)
+  {
+    if (m_documentation_widget)
+      m_documentation_widget->set_main_window (mw);
+    else
+      m_documentation_widget
+        = QPointer<documentation_dock_widget> (new documentation_dock_widget (mw, *this));
+
+    connect (qt_link (), &qt_interpreter_events::register_documentation_signal,
+             m_documentation_widget, &documentation_dock_widget::registerDoc);
+
+    connect (qt_link (), &qt_interpreter_events::unregister_documentation_signal,
+             m_documentation_widget, &documentation_dock_widget::unregisterDoc);
+
+    return m_documentation_widget;
+  }
+
+  QPointer<files_dock_widget>
+  base_qobject::file_browser_widget (main_window *mw)
+  {
+    if (m_file_browser_widget)
+      m_file_browser_widget->set_main_window (mw);
+    else
+      m_file_browser_widget
+        = QPointer<files_dock_widget> (new files_dock_widget (mw, *this));
+
+    return m_file_browser_widget;
+  }
+
+  QPointer<history_dock_widget>
+  base_qobject::history_widget (main_window *mw)
+  {
+    if (m_history_widget)
+      m_history_widget->set_main_window (mw);
+    else
+      m_history_widget
+        = QPointer<history_dock_widget> (new history_dock_widget (mw, *this));
+
+    connect (qt_link (), &qt_interpreter_events::set_history_signal,
+             m_history_widget, &history_dock_widget::set_history);
+
+    connect (qt_link (), &qt_interpreter_events::append_history_signal,
+             m_history_widget, &history_dock_widget::append_history);
+
+    connect (qt_link (), &qt_interpreter_events::clear_history_signal,
+             m_history_widget, &history_dock_widget::clear_history);
+
+    qt_link()->set_history (octave::command_history::list ());
+
+    return m_history_widget;
+  }
+
+  QPointer<workspace_view>
+  base_qobject::workspace_widget (main_window *mw)
+  {
+    if (m_workspace_widget)
+      m_workspace_widget->set_main_window (mw);
+    else
+      m_workspace_widget
+        = QPointer<workspace_view> (new workspace_view (mw, *this));
+
+    m_workspace_widget->setModel (m_workspace_model);
+
+    connect (m_workspace_model, &workspace_model::model_changed,
+             m_workspace_widget, &workspace_view::handle_model_changed);
+
+    connect (qt_link (), &qt_interpreter_events::set_workspace_signal,
+             m_workspace_model, &workspace_model::set_workspace);
+
+    connect (qt_link (), &qt_interpreter_events::clear_workspace_signal,
+             m_workspace_model, &workspace_model::clear_workspace);
+
+    return m_workspace_widget;
+  }
+
+  QPointer<file_editor_interface>
+  base_qobject::editor_widget (main_window */*mw*/)
+  {
+#if 0
+    if (m_editor_widget)
+      m_editor_widget->set_main_window (mw);
+    else
+      m_editor_widget = new file_editor (mw, *this);
+#endif
+
+    return m_editor_widget;
+  }
+
+  QPointer<variable_editor>
+  base_qobject::variable_editor_widget (main_window *mw)
+  {
+    if (m_variable_editor_widget)
+      m_variable_editor_widget->set_main_window (mw);
+    else
+      m_variable_editor_widget
+        = QPointer<variable_editor> (new variable_editor (mw, *this));
+
+    return m_variable_editor_widget;
+  }
+
   bool base_qobject::confirm_shutdown (void)
   {
     // Currently, we forward to main_window::confirm_shutdown instead of
@@ -396,6 +524,96 @@
       }
   }
 
+  void base_qobject::show_documentation_window (const QString& file)
+  {
+    documentation_dock_widget *widget = documentation_widget ();
+
+    widget->showDoc (file);
+
+    if (! widget->isVisible ())
+      {
+        widget->show ();
+        widget->raise ();
+      }
+  }
+
+  void base_qobject::show_file_browser_window (void)
+  {
+    files_dock_widget *widget = file_browser_widget ();
+
+    if (! widget->isVisible ())
+      {
+        widget->show ();
+        widget->raise ();
+      }
+  }
+
+  void base_qobject::show_command_history_window (void)
+  {
+    history_dock_widget *widget = history_widget ();
+
+    if (! widget->isVisible ())
+      {
+        widget->show ();
+        widget->raise ();
+      }
+  }
+
+  void base_qobject::show_workspace_window (void)
+  {
+    workspace_view *widget = workspace_widget ();
+
+    if (! widget->isVisible ())
+      {
+        widget->show ();
+        widget->raise ();
+      }
+  }
+
+  void base_qobject::edit_variable (const QString& expr,
+                                    const octave_value& val)
+  {
+    variable_editor *widget = variable_editor_widget ();
+
+#if 0
+    // FIXME: This connection needs to be made whether running with the
+    // GUI main window or not, but only needs to be made once.
+    // Currently we have handle_variable_editor_update methods here and
+    // in the main_window object.
+
+    connect (widget, &variable_editor::updated,
+             this, &base_qobject::handle_variable_editor_update);
+#endif
+
+    widget->edit_variable (expr, val);
+
+    if (! widget->isVisible ())
+      {
+        widget->show ();
+        widget->raise ();
+      }
+  }
+
+  void base_qobject::handle_variable_editor_update (void)
+  {
+    // Called when the variable editor emits the updated signal.  The size
+    // of a variable may have changed, so we refresh the workspace in the
+    // interpreter.  That will eventually cause the workspace view in the
+    // GUI to be updated.
+
+    interpreter_event
+      ([] (interpreter& interp)
+       {
+         // INTERPRETER THREAD
+
+         tree_evaluator& tw = interp.get_evaluator ();
+
+         event_manager& xevmgr = interp.get_event_manager ();
+
+         xevmgr.set_workspace (true, tw.get_symbol_info (), false);
+       });
+  }
+
   void base_qobject::close_gui (void)
   {
     if (m_app_context.experimental_terminal_widget ())
--- a/libgui/src/octave-qobject.h	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/octave-qobject.h	Thu Apr 29 11:12:40 2021 -0400
@@ -37,7 +37,6 @@
 #include "interpreter-qobject.h"
 #include "resource-manager.h"
 #include "shortcut-manager.h"
-#include "workspace-model.h"
 
 namespace octave
 {
@@ -72,6 +71,22 @@
     void interpreter_event (const meth_callback& meth);
   };
 
+  //! Container for windows that may be created from the command line or
+  //! docked with the main GUI window.  Any of these windows that are
+  //! created in command line mode will be adopted by the main window if
+  //! it is opened from the command line.  Any that are undocked from
+  //! the main window will remain open if control returns to the command
+  //! line.
+
+  class base_qobject;
+  class documentation_dock_widget;
+  class file_editor_interface;
+  class files_dock_widget;
+  class history_dock_widget;
+  class variable_editor;
+  class workspace_model;
+  class workspace_view;
+
   //! Base class for Octave interfaces that use Qt.  There are two
   //! classes derived from this one.  One provides a command-line
   //! interface that may use Qt graphics and another provides the
@@ -118,11 +133,6 @@
       return m_shortcut_manager;
     }
 
-    workspace_model * get_workspace_model (void)
-    {
-      return m_workspace_model;
-    }
-
     std::shared_ptr<qt_interpreter_events> get_qt_interpreter_events (void)
     {
       return m_qt_interpreter_events;
@@ -138,6 +148,32 @@
       return m_interpreter_qobj;
     }
 
+    workspace_model * get_workspace_model (void)
+    {
+      return m_workspace_model;
+    }
+
+    QPointer<documentation_dock_widget>
+    documentation_widget (main_window *mw = nullptr);
+
+    QPointer<files_dock_widget>
+    file_browser_widget (main_window *mw = nullptr);
+
+    QPointer<history_dock_widget>
+    history_widget (main_window *mw = nullptr);
+
+    QPointer<workspace_view>
+    workspace_widget (main_window *mw = nullptr);
+
+    // FIXME: The file_editor_interface needs to be a proper generic
+    // interface for all editors (internal and external) for this to
+    // work properly.
+    QPointer<file_editor_interface>
+    editor_widget (main_window *mw = nullptr);
+
+    QPointer<variable_editor>
+    variable_editor_widget (main_window *mw = nullptr);
+
     QThread *main_thread (void) { return m_main_thread; }
 
     // Declared virtual so that a derived class may redefine this
@@ -152,6 +188,18 @@
     void start_gui (bool gui_app);
     void close_gui (void);
 
+    void show_documentation_window (const QString& file);
+
+    void show_file_browser_window (void);
+
+    void show_command_history_window (void);
+
+    void show_workspace_window (void);
+
+    void edit_variable (const QString& expr, const octave_value& val);
+
+    void handle_variable_editor_update (void);
+
     void interpreter_ready (void);
 
     void interpreter_event (const fcn_callback& fcn);
@@ -184,8 +232,6 @@
 
     shortcut_manager m_shortcut_manager;
 
-    workspace_model *m_workspace_model;
-
     QTranslator *m_qt_tr;
     QTranslator *m_gui_tr;
     QTranslator *m_qsci_tr;
@@ -202,6 +248,24 @@
 
     bool m_interpreter_ready;
 
+    workspace_model *m_workspace_model;
+
+    // Dock widgets that may be used from the command line.  They are
+    // adopted by the desktop (main window) if it is also started from
+    // the command line.
+
+    QPointer<documentation_dock_widget> m_documentation_widget;
+
+    QPointer<files_dock_widget> m_file_browser_widget;
+
+    QPointer<history_dock_widget> m_history_widget;
+
+    QPointer<workspace_view> m_workspace_widget;
+
+    QPointer<file_editor_interface> m_editor_widget;
+
+    QPointer<variable_editor> m_variable_editor_widget;
+
     main_window *m_main_window;
   };
 }
--- a/libgui/src/qt-interpreter-events.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/qt-interpreter-events.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -259,9 +259,26 @@
     emit apply_new_settings ();
   }
 
-  void qt_interpreter_events::show_doc (const std::string& file)
+  bool qt_interpreter_events::show_documentation (const std::string& file)
+  {
+    emit show_documentation_signal (QString::fromStdString (file));
+
+    return true;
+  }
+
+  void qt_interpreter_events::show_file_browser (void)
   {
-    emit show_doc_signal (QString::fromStdString (file));
+    emit show_file_browser_signal ();
+  }
+
+  void qt_interpreter_events::show_command_history (void)
+  {
+    emit show_command_history_signal ();
+  }
+
+  void qt_interpreter_events::show_workspace (void)
+  {
+    emit show_workspace_signal ();
   }
 
   bool qt_interpreter_events::edit_file (const std::string& file)
@@ -450,14 +467,14 @@
     emit execute_command_in_terminal_signal (QString::fromStdString (command));
   }
 
-  void qt_interpreter_events::register_doc (const std::string& file)
+  void qt_interpreter_events::register_documentation (const std::string& file)
   {
-    emit register_doc_signal (QString::fromStdString (file));
+    emit register_documentation_signal (QString::fromStdString (file));
   }
 
-  void qt_interpreter_events::unregister_doc (const std::string& file)
+  void qt_interpreter_events::unregister_documentation (const std::string& file)
   {
-    emit unregister_doc_signal (QString::fromStdString (file));
+    emit unregister_documentation_signal (QString::fromStdString (file));
   }
 
   void qt_interpreter_events::interpreter_output (const std::string& msg)
--- a/libgui/src/qt-interpreter-events.h	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/qt-interpreter-events.h	Thu Apr 29 11:12:40 2021 -0400
@@ -117,7 +117,13 @@
 
     void apply_preferences (void);
 
-    void show_doc (const std::string& file);
+    bool show_documentation (const std::string& file);
+
+    void show_file_browser (void);
+
+    void show_command_history (void);
+
+    void show_workspace (void);
 
     bool edit_file (const std::string& file);
 
@@ -142,9 +148,9 @@
 
     void execute_command_in_terminal (const std::string& command);
 
-    void register_doc (const std::string& file);
+    void register_documentation (const std::string& file);
 
-    void unregister_doc (const std::string& file);
+    void unregister_documentation (const std::string& file);
 
     // Note: this function currently does nothing with the old terminal
     // widget.
@@ -257,11 +263,17 @@
 
     void gui_preference_signal (const QString& key, const QString& value);
 
-    void show_doc_signal (const QString& file);
+    void show_documentation_signal (const QString& file);
+
+    void register_documentation_signal (const QString& file);
+
+    void unregister_documentation_signal (const QString& file);
 
-    void register_doc_signal (const QString& file);
+    void show_file_browser_signal (void);
 
-    void unregister_doc_signal (const QString& file);
+    void show_command_history_signal (void);
+
+    void show_workspace_signal (void);
 
     // Note: this signal currently not used by the old terminal widget.
     void interpreter_output_signal (const QString& msg);
--- a/libgui/src/variable-editor.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/variable-editor.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -1183,6 +1183,18 @@
       }
   }
 
+  variable_editor::~variable_editor (void)
+  {
+    // FIXME: Maybe toolbar actions could be handled with signals and
+    // slots so that deleting the toolbar here would disconnect all
+    // toolbar actions and any other slots that might try to access the
+    // toolbar would work properly (I'm looking at you,
+    // handle_focus_change).
+
+    delete m_tool_bar;
+    m_tool_bar = nullptr;
+  }
+
   void
   variable_editor::edit_variable (const QString& name, const octave_value& val)
   {
@@ -1231,11 +1243,13 @@
     connect (this, &variable_editor::visibilityChanged,
              page, &variable_dock_widget::setVisible);
 
+    // Notify the variable editor for page actions.
     connect (page, &variable_dock_widget::destroyed,
              this, &variable_editor::variable_destroyed);
     connect (page, &variable_dock_widget::variable_focused_signal,
              this, &variable_editor::variable_focused);
-// See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
+
+    // See  Octave bug #53807 and https://bugreports.qt.io/browse/QTBUG-44813
 #if (QT_VERSION >= 0x050302) && (QT_VERSION <= QTBUG_44813_FIX_VERSION)
     connect (page, SIGNAL (queue_unfloat_float ()),
              page, SLOT (unfloat_float ()), Qt::QueuedConnection);
@@ -1345,11 +1359,16 @@
 
     model->update_data (val);
 
-    QList<QTableView *> viewlist = findChildren<QTableView *> ();
-    if (viewlist.size () == 1)
-      m_tool_bar->setEnabled (true);
+    if (m_tool_bar)
+      {
+        QList<QTableView *> viewlist = findChildren<QTableView *> ();
+        if (viewlist.size () == 1 && m_tool_bar)
+          m_tool_bar->setEnabled (true);
+      }
 
-    m_main->parentWidget ()->show ();
+    make_window ();
+
+    show ();
     page->show ();
     page->raise ();
     page->activateWindow ();
@@ -1440,12 +1459,15 @@
 
     // Icon size in the toolbar.
 
-    int size_idx = settings->value (global_icon_size).toInt ();
-    size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
+    if (m_tool_bar)
+      {
+        int size_idx = settings->value (global_icon_size).toInt ();
+        size_idx = (size_idx > 0) - (size_idx < 0) + 1;  // Make valid index from 0 to 2
 
-    QStyle *st = style ();
-    int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
-    m_tool_bar->setIconSize (QSize (icon_size, icon_size));
+        QStyle *st = style ();
+        int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
+        m_tool_bar->setIconSize (QSize (icon_size, icon_size));
+      }
 
     // Shortcuts (same as file editor)
     shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager ();
@@ -1470,10 +1492,13 @@
         m_focus_widget_vdw = nullptr;
       }
 
-    // If no variable pages remain, deactivate the tool bar.
-    QList<variable_dock_widget *> vdwlist = findChildren<variable_dock_widget *> ();
-    if (vdwlist.isEmpty ())
-      m_tool_bar->setEnabled (false);
+    if (m_tool_bar)
+      {
+        // If no variable pages remain, deactivate the tool bar.
+        QList<variable_dock_widget *> vdwlist = findChildren<variable_dock_widget *> ();
+        if (vdwlist.isEmpty ())
+          m_tool_bar->setEnabled (false);
+      }
 
     QFocusEvent ev (QEvent::FocusIn);
     focusInEvent (&ev);
--- a/libgui/src/variable-editor.h	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/variable-editor.h	Thu Apr 29 11:12:40 2021 -0400
@@ -60,6 +60,8 @@
 
     variable_dock_widget (QWidget *p, base_qobject& oct_qobj);
 
+    ~variable_dock_widget (void) = default;
+
   signals:
 
     void variable_focused_signal (const QString& name);
@@ -131,6 +133,8 @@
 
     variable_editor_stack (QWidget *p, base_qobject& oct_qobj);
 
+    ~variable_editor_stack (void) = default;
+
     variable_editor_view *edit_view (void) {return m_edit_view;};
 
     QTextEdit *disp_view (void) {return m_disp_view;};
@@ -174,6 +178,8 @@
 
     variable_editor_view (QWidget *p, base_qobject& oct_qobj);
 
+    ~variable_editor_view (void) = default;
+
     void setModel (QAbstractItemModel *model);
 
   signals:
@@ -232,6 +238,8 @@
 
     HoverToolButton (QWidget *parent = nullptr);
 
+    ~HoverToolButton (void) = default;
+
   signals:
 
     void hovered_signal (void);
@@ -251,6 +259,8 @@
 
     ReturnFocusToolButton (QWidget *parent = nullptr);
 
+    ~ReturnFocusToolButton (void) = default;
+
   signals:
 
     void about_to_activate (void);
@@ -268,6 +278,8 @@
 
     ReturnFocusMenu (QWidget *parent = nullptr);
 
+    ~ReturnFocusMenu (void) = default;
+
   signals:
 
     void about_to_activate (void);
@@ -287,7 +299,7 @@
 
     variable_editor (QWidget *parent, base_qobject& oct_qobj);
 
-    ~variable_editor (void) = default;
+    ~variable_editor (void);
 
     // No copying!
 
--- a/libgui/src/workspace-view.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libgui/src/workspace-view.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -159,6 +159,9 @@
 
     connect (m_view, &QTableView::activated,
              this, &workspace_view::handle_contextmenu_edit);
+
+    if (! p)
+      make_window ();
   }
 
   void workspace_view::setModel (workspace_model *model)
--- a/libinterp/corefcn/event-manager.cc	Tue May 04 15:33:58 2021 -0400
+++ b/libinterp/corefcn/event-manager.cc	Thu Apr 29 11:12:40 2021 -0400
@@ -31,6 +31,7 @@
 
 #include "builtin-defun-decls.h"
 #include "cmd-edit.h"
+#include "cmd-hist.h"
 #include "defun.h"
 #include "event-manager.h"
 #include "interpreter.h"
@@ -593,19 +594,14 @@
 
   std::string name = args(0).string_value ();
 
-  if (! (Fisguirunning ())(0).is_true ())
-    warning ("openvar: GUI is not running, can't start Variable Editor");
-  else
-    {
-      octave_value val = interp.varval (name);
+  octave_value val = interp.varval (name);
 
-      if (val.is_undefined ())
-        error ("openvar: '%s' is not a variable", name.c_str ());
+  if (val.is_undefined ())
+    error ("openvar: '%s' is not a variable", name.c_str ());
 
-      octave::event_manager& evmgr = interp.get_event_manager ();
+  octave::event_manager& evmgr = interp.get_event_manager ();
 
-      evmgr.edit_variable (name, val);
-    }
+  evmgr.edit_variable (name, val);
 
   return ovl ();
 }
@@ -616,9 +612,25 @@
 %!error <NAME must be a string> openvar (1:10)
 */
 
-DEFMETHOD (__event_manager_show_doc__, interp, args, ,
+DEFMETHOD (__event_manager_show_documentation__, interp, args, ,
            doc: /* -*- texinfo -*-
-@deftypefn {} {} __event_manager_show_doc__ (@var{filename})
+@deftypefn {} {} __event_manager_show_documentation__ (@var{filename})
+Undocumented internal function.
+@end deftypefn */)
+{
+  std::string file;
+
+  if (args.length () >= 1)
+    file = args(0).string_value();
+
+  octave::event_manager& evmgr = interp.get_event_manager ();
+
+  return ovl (evmgr.show_documentation (file));
+}
+
+DEFMETHOD (__event_manager_register_documentation__, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __event_manager_register_documentation__ (@var{filename})
 Undocumented internal function.
 @end deftypefn */)
 {
@@ -629,12 +641,12 @@
 
   octave::event_manager& evmgr = interp.get_event_manager ();
 
-  return ovl (evmgr.show_doc (file));
+  return ovl (evmgr.register_documentation (file));
 }
 
-DEFMETHOD (__event_manager_register_doc__, interp, args, ,
+DEFMETHOD (__event_manager_unregister_documentation__, interp, args, ,
            doc: /* -*- texinfo -*-
-@deftypefn {} {} __event_manager_register_doc__ (@var{filename})
+@deftypefn {} {} __event_manager_unregister_documentation__ (@var{filename})
 Undocumented internal function.
 @end deftypefn */)
 {
@@ -645,23 +657,46 @@
 
   octave::event_manager& evmgr = interp.get_event_manager ();
 
-  return ovl (evmgr.register_doc (file));
+  return ovl (evmgr.unregister_documentation (file));
 }
 
-DEFMETHOD (__event_manager_unregister_doc__, interp, args, ,
+DEFMETHOD (__event_manager_show_file_browser__, interp, , ,
            doc: /* -*- texinfo -*-
-@deftypefn {} {} __event_manager_unregister_doc__ (@var{filename})
+@deftypefn {} {} __event_manager_show_file_browser__ ()
 Undocumented internal function.
 @end deftypefn */)
 {
-  std::string file;
+  octave::event_manager& evmgr = interp.get_event_manager ();
+
+  evmgr.show_file_browser ();
+
+  return ovl ();
+}
 
-  if (args.length () >= 1)
-    file = args(0).string_value();
-
+DEFMETHOD (__event_manager_show_command_history__, interp, , ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __event_manager_show_command_history__ ()
+Undocumented internal function.
+@end deftypefn */)
+{
   octave::event_manager& evmgr = interp.get_event_manager ();
 
-  return ovl (evmgr.unregister_doc (file));
+  evmgr.show_command_history ();
+
+  return ovl ();
+}
+
+DEFMETHOD (__event_manager_show_workspace__, interp, , ,
+           doc: /* -*- texinfo -*-
+@deftypefn {} {} __event_manager_show_workspace__ ()
+Undocumented internal function.
+@end deftypefn */)
+{
+  octave::event_manager& evmgr = interp.get_event_manager ();
+
+  evmgr.show_workspace ();
+
+  return ovl ();
 }
 
 DEFMETHOD (__event_manager_gui_status_update__, interp, args, ,
--- a/libinterp/corefcn/event-manager.h	Tue May 04 15:33:58 2021 -0400
+++ b/libinterp/corefcn/event-manager.h	Thu Apr 29 11:12:40 2021 -0400
@@ -148,7 +148,16 @@
 
     virtual void apply_preferences (void) { }
 
-    virtual void show_doc (const std::string& /*file*/) { }
+    virtual bool show_documentation (const std::string& /*file*/)
+    {
+      return false;
+    }
+
+    virtual void show_file_browser (void) { }
+
+    virtual void show_command_history (void) { }
+
+    virtual void show_workspace (void) { }
 
     virtual bool edit_file (const std::string& /*file*/) { return false; }
 
@@ -204,9 +213,9 @@
     virtual void
     execute_command_in_terminal (const std::string& /*command*/) { }
 
-    virtual void register_doc (const std::string& /*file*/) { }
+    virtual void register_documentation (const std::string& /*file*/) { }
 
-    virtual void unregister_doc (const std::string& /*file*/) { }
+    virtual void unregister_documentation (const std::string& /*file*/) { }
 
     virtual void interpreter_output (const std::string& /*msg*/) { }
 
@@ -432,15 +441,27 @@
         return false;
     }
 
-    bool show_doc (const std::string& file)
+    bool show_documentation (const std::string& file)
+    {
+      return enabled () ? instance->show_documentation (file) : false;
+    }
+
+    void show_file_browser (void)
     {
       if (enabled ())
-        {
-          instance->show_doc (file);
-          return true;
-        }
-      else
-        return false;
+        instance->show_file_browser ();
+    }
+
+    void show_command_history (void)
+    {
+      if (enabled ())
+        instance->show_command_history ();
+    }
+
+    void show_workspace (void)
+    {
+      if (enabled ())
+        instance->show_workspace ();
     }
 
     bool edit_file (const std::string& file)
@@ -512,22 +533,22 @@
         instance->execute_command_in_terminal (command);
     }
 
-    bool register_doc (const std::string& file)
+    bool register_documentation (const std::string& file)
     {
       if (enabled ())
         {
-          instance->register_doc (file);
+          instance->register_documentation (file);
           return true;
         }
       else
         return false;
     }
 
-    bool unregister_doc (const std::string& file)
+    bool unregister_documentation (const std::string& file)
     {
       if (enabled ())
         {
-          instance->unregister_doc (file);
+          instance->unregister_documentation (file);
           return true;
         }
       else
--- a/scripts/help/doc.m	Tue May 04 15:33:58 2021 -0400
+++ b/scripts/help/doc.m	Thu Apr 29 11:12:40 2021 -0400
@@ -51,10 +51,12 @@
     ftype = 0;
   endif
 
-  ## if GUI is running, let it display the function
-  if (isguirunning ())
-    status = ! __event_manager_show_doc__ (function_name);
-  else
+  ## Give event manager the first shot.
+
+  status = ! __event_manager_show_documentation__ (function_name);
+
+  if (status)
+
     if (ftype == 2 || ftype == 3)
       ffile = which (function_name);
     else