view libgui/src/qt-interpreter-events.h @ 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 3bfec185c9e2
children b4d2fa28d1d4
line wrap: on
line source

////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2011-2021 The Octave Project Developers
//
// See the file COPYRIGHT.md in the top-level directory of this
// distribution or <https://octave.org/copyright/>.
//
// This file is part of Octave.
//
// Octave is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Octave is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Octave; see the file COPYING.  If not, see
// <https://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////

#if ! defined (octave_qt_interpreter_events_h)
#define octave_qt_interpreter_events_h 1

#include <list>
#include <string>

#include <QList>
#include <QMutex>
#include <QObject>
#include <QString>
#include <QWaitCondition>

#include "dialog.h"
#include "gui-settings.h"

#include "event-manager.h"

// Defined for purposes of sending QList<int> as part of signal.
typedef QList<int> QIntList;

class octave_value;

namespace octave
{
  class base_qobject;

  // The functions in this class are not normally called directly, but
  // are invoked from the Octave interpreter thead by methods in the
  // event_manager class.  In most cases, they should only translate
  // data from the types typically used in the interpreter to whatever
  // is required by the GUI (for example, std::string to QString) and
  // emit a Qt signal.
  //
  // The use of Qt signals provides a thread-safe way for the Octave
  // interpreter to notify the GUI of events (directory or workspace has
  // changed, for example) or to request that the GUI perform actions
  // (display a dialog, for example).
  //
  // By using this class as a wrapper around the Qt signals, we maintain
  // a separation between the Octave interpreter and any specific GUI
  // toolkit (no Qt headers are used in the Octave interpreter sources).

  class qt_interpreter_events : public QObject, public interpreter_events
  {
    Q_OBJECT

  public:

    qt_interpreter_events (base_qobject& oct_qobj);

    // No copying!

    qt_interpreter_events (const qt_interpreter_events&) = delete;

    qt_interpreter_events& operator = (const qt_interpreter_events&) = delete;

    ~qt_interpreter_events (void) = default;

    // Note: these functions currently do nothing with the old terminal
    // widget.
    void start_gui (bool gui_app = false);
    void close_gui (void);

    std::list<std::string>
    file_dialog (const filter_list& filter, const std::string& title,
                 const std::string& filename, const std::string& pathname,
                 const std::string& multimode);

    std::list<std::string>
    input_dialog (const std::list<std::string>& prompt,
                  const std::string& title, const std::list<float>& nr,
                  const std::list<float>& nc,
                  const std::list<std::string>& defaults);

    std::pair<std::list<int>, int>
    list_dialog (const std::list<std::string>& list,
                 const std::string& mode, int width, int height,
                 const std::list<int>& initial_value,
                 const std::string& name,
                 const std::list<std::string>& prompt,
                 const std::string& ok_string,
                 const std::string& cancel_string);

    std::string
    question_dialog (const std::string& msg, const std::string& title,
                     const std::string& btn1, const std::string& btn2,
                     const std::string& btn3, const std::string& btndef);

    void update_path_dialog (void);

    void show_preferences (void);

    void apply_preferences (void);

    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);

    void edit_variable (const std::string& name, const octave_value& val);

    bool confirm_shutdown (void);

    bool prompt_new_edit_file (const std::string& file);

    int debug_cd_or_addpath_error (const std::string& file,
                                   const std::string& dir,
                                   bool addpath_option);

    uint8NDArray get_named_icon (const std::string& icon_name);

    std::string gui_preference (const std::string& key,
                                const std::string& value);

    bool copy_image_to_clipboard (const std::string& file);

    void focus_window (const std::string win_name);

    void execute_command_in_terminal (const std::string& command);

    void register_documentation (const std::string& file);

    void unregister_documentation (const std::string& file);

    // Note: this function currently does nothing with the old terminal
    // widget.
    void interpreter_output (const std::string& msg);

    void display_exception (const execution_exception& ee, bool beep);

    void gui_status_update (const std::string& feature, const std::string& status);

    void update_gui_lexer (void);

    void directory_changed (const std::string& dir);

    void file_remove (const std::string& old_name,
                      const std::string& new_name);

    void file_renamed (bool load_new = true);

    void set_workspace (bool top_level, bool debug,
                        const symbol_info_list& syminfo,
                        bool update_variable_editor);

    void clear_workspace (void);

    void update_prompt (const std::string& prompt);

    void set_history (const string_vector& hist);

    void append_history (const std::string& hist_entry);

    void clear_history (void);

    void pre_input_event (void);

    void post_input_event (void);

    void enter_debugger_event (const std::string& fcn_name,
                               const std::string& fcn_file_name, int line);

    void execute_in_debugger_event (const std::string& file, int line);

    void exit_debugger_event (void);

    void update_breakpoint (bool insert, const std::string& file, int line,
                            const std::string& cond);

    void lock (void) { m_mutex.lock (); }

    void wait (void) { m_waitcondition.wait (&m_mutex); }

    void unlock (void) { m_mutex.unlock (); }

    void wake_all (void) { m_waitcondition.wakeAll (); }

  public slots:

    void confirm_shutdown_octave (void);

    void get_named_icon_slot (const QString& name);

    void gui_preference_slot (const QString& key, const QString& value);

  signals:

    // Note: these signals are not currently used by the old terminal widget.
    void start_gui_signal (bool gui_app);
    void close_gui_signal (void);

    void copy_image_to_clipboard_signal (const QString& file, bool remove_file);

    void focus_window_signal (const QString& win_name);

    void edit_file_signal (const QString& file);

    void directory_changed_signal (const QString& dir);

    void update_path_dialog_signal (void);

    void file_remove_signal (const QString& old_name, const QString& new_name);

    void file_renamed_signal (bool load_new);

    void execute_command_in_terminal_signal (const QString& command);

    void set_workspace_signal (bool top_level, bool debug,
                               const symbol_info_list& syminfo);

    void clear_workspace_signal (void);

    void update_prompt_signal (const QString& prompt);

    void set_history_signal (const QStringList& hist);

    void append_history_signal (const QString& hist_entry);

    void clear_history_signal (void);

    void enter_debugger_signal (void);

    void exit_debugger_signal (void);

    void update_breakpoint_marker_signal (bool insert, const QString& file,
                                          int line, const QString& cond);

    void insert_debugger_pointer_signal (const QString&, int);

    void delete_debugger_pointer_signal (const QString&, int);

    void show_preferences_signal (void);

    void gui_preference_signal (const QString& key, const QString& value);

    void show_documentation_signal (const QString& file);

    void register_documentation_signal (const QString& file);

    void unregister_documentation_signal (const QString& file);

    void show_file_browser_signal (void);

    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);

    void gui_status_update_signal (const QString& feature, const QString& status);

    void update_gui_lexer_signal (bool update_apis_only);

    void edit_variable_signal (const QString& name, const octave_value& val);

    void refresh_variable_editor_signal (void);

    void confirm_shutdown_signal (void);

    void get_named_icon_signal (const QString& name);

    void settings_changed (const gui_settings *, bool);

    void apply_new_settings (void);

  private:

    QString gui_preference_adjust (const QString& key, const QString& value);

    void insert_debugger_pointer (const std::string& file, int line);

    void delete_debugger_pointer (const std::string& file, int line);

    base_qobject& m_octave_qobj;

    QUIWidgetCreator m_uiwidget_creator;

    QVariant m_result;

    QMutex m_mutex;

    QWaitCondition m_waitcondition;
  };
}

#endif