Mercurial > octave
changeset 27197:b8c0d5ad024f
refactor and rename some qt application objects
* octave-qobject.h, octave-qobject.cc: New files. Move
octave_qapplication, octave_qt_app, octave_qt_cli_app, and
octave_qt_gui_app classes here from main-window.h and main-window.cc.
Rename octave_qt_app to base_qobject. Rename octave_qt_cli_app to
cli_qobject. Rename octave_qt_gui_app to gui_qobject.
* qt-application.h, qt-application.cc: Rename from octave-gui.h and
octave-gui.cc. Rename gui_application class to qt_application.
Change all uses.
* libgui/src/module.mk: Update.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sat, 22 Jun 2019 17:30:16 -0500 |
parents | d993642352d0 |
children | dffdabfd0213 |
files | libgui/src/interpreter-qobject.cc libgui/src/interpreter-qobject.h libgui/src/main-window.cc libgui/src/main-window.h libgui/src/module.mk libgui/src/octave-gui.cc libgui/src/octave-gui.h libgui/src/octave-qobject.cc libgui/src/octave-qobject.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libgui/src/qt-application.cc libgui/src/qt-application.h src/main-gui.cc |
diffstat | 14 files changed, 747 insertions(+), 613 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/interpreter-qobject.cc Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/interpreter-qobject.cc Sat Jun 22 17:30:16 2019 -0500 @@ -26,14 +26,14 @@ #endif #include "interpreter-qobject.h" -#include "octave-gui.h" +#include "qt-application.h" #include "input.h" #include "interpreter.h" namespace octave { - interpreter_qobject::interpreter_qobject (gui_application& app_context) + interpreter_qobject::interpreter_qobject (qt_application& app_context) : QObject (), m_app_context (app_context) { }
--- a/libgui/src/interpreter-qobject.h Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/interpreter-qobject.h Sat Jun 22 17:30:16 2019 -0500 @@ -28,7 +28,7 @@ namespace octave { - class gui_application; + class qt_application; class interpreter_qobject : public QObject { @@ -36,7 +36,7 @@ public: - interpreter_qobject (gui_application& app_context); + interpreter_qobject (qt_application& app_context); ~interpreter_qobject (void) = default; @@ -53,7 +53,7 @@ private: - gui_application& m_app_context; + qt_application& m_app_context; }; }
--- a/libgui/src/main-window.cc Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/main-window.cc Sat Jun 22 17:30:16 2019 -0500 @@ -58,6 +58,7 @@ #include "interpreter-qobject.h" #include "main-window.h" #include "news-reader.h" +#include "octave-qobject.h" #include "settings-dialog.h" #include "shortcut-manager.h" #include "welcome-wizard.h" @@ -96,20 +97,10 @@ #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 - { } - - main_window::main_window (octave_qt_app& oct_qt_app, - octave_qt_link *oct_qt_lnk) + main_window::main_window (base_qobject& qobj, + octave_qt_link *lnk) : QMainWindow (), - m_qt_app (oct_qt_app.qt_app ()), m_octave_qt_link (oct_qt_lnk), + m_octave_qapp (qobj.octave_qapp ()), m_octave_qt_link (lnk), m_workspace_model (nullptr), m_status_bar (nullptr), m_command_window (nullptr), m_history_window (nullptr), m_file_browser_window (nullptr), @@ -126,7 +117,7 @@ if (resource_manager::is_first_run ()) { // Before wizard. - oct_qt_app.config_translators (); + qobj.config_translators (); welcome_wizard welcomeWizard; @@ -142,7 +133,7 @@ resource_manager::reload_settings (); // After settings. - oct_qt_app.config_translators (); + qobj.config_translators (); } resource_manager::update_network_settings (); @@ -176,7 +167,7 @@ QGuiApplication::setDesktopFileName ("org.octave.Octave.desktop"); #endif - m_default_style = m_qt_app->style ()->objectName (); + m_default_style = m_octave_qapp->style ()->objectName (); QSettings *settings = resource_manager::get_settings (); @@ -685,7 +676,7 @@ QStyle *new_style = QStyleFactory::create (preferred_style); if (new_style) - m_qt_app->setStyle (new_style); + m_octave_qapp->setStyle (new_style); // the widget's icons (when floating) QString icon_set @@ -2650,329 +2641,4 @@ list.append (static_cast<octave_dock_widget *> (m_variable_editor_window)); return list; } - - //! Reimplements QApplication::notify. - /*! Octave's own exceptions are caugh and rethrown in the interpreter - thread.*/ - bool - octave_qapplication::notify (QObject *receiver, QEvent *ev) - { - try - { - return QApplication::notify (receiver, ev); - } - catch (execution_exception&) - { - octave_link::post_exception (std::current_exception ()); - } - - return false; - } - - 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_qobject (new interpreter_qobject (m_app_context)), - m_main_thread (new QThread ()) - { - 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 octave_qapplication (m_argc, m_argv); - - // 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_qobject, SIGNAL (octave_finished_signal (int)), - this, SLOT (handle_octave_finished (int))); - - connect (m_interpreter_qobject, SIGNAL (octave_finished_signal (int)), - m_main_thread, SLOT (quit (void))); - - connect (m_main_thread, SIGNAL (finished (void)), - m_main_thread, SLOT (deleteLater (void))); - } - - octave_qt_app::~octave_qt_app (void) - { - delete m_interpreter_qobject; - 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::start_main_thread (void) - { - // Defer initializing and executing the interpreter until after the main - // window and QApplication are running to prevent race conditions - QTimer::singleShot (0, m_interpreter_qobject, SLOT (execute (void))); - - m_interpreter_qobject->moveToThread (m_main_thread); - - m_main_thread->start (); - } - - 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) - { - confirm_shutdown_octave_internal (true); - } - - 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&))); - } - - void octave_qt_app::confirm_shutdown_octave_internal (bool closenow) - { - // 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 (); - } - - octave_qt_cli_app::octave_qt_cli_app (gui_application& app_context) - : octave_qt_app (app_context) - { - // Get settings file. - resource_manager::reload_settings (); - - // After settings. - config_translators (); - - m_qt_app->setQuitOnLastWindowClosed (false); - - start_main_thread (); - } - - octave_qt_gui_app::octave_qt_gui_app (gui_application& app_context) - : octave_qt_app (app_context), - m_main_window (new main_window (*this, m_octave_qt_link)) - { - connect (m_interpreter_qobject, SIGNAL (octave_ready_signal (void)), - m_main_window, SLOT (handle_octave_ready (void))); - - m_app_context.gui_running (true); - - start_main_thread (); - } - - octave_qt_gui_app::~octave_qt_gui_app (void) - { - delete m_main_window; - } - - void octave_qt_gui_app::confirm_shutdown_octave (void) - { - bool closenow = true; - - if (m_main_window) - closenow = m_main_window->confirm_shutdown_octave (); - - confirm_shutdown_octave_internal (closenow); - } }
--- a/libgui/src/main-window.h Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/main-window.h Sat Jun 22 17:30:16 2019 -0500 @@ -52,8 +52,8 @@ #include "history-dock-widget.h" #include "octave-cmd.h" #include "octave-dock-widget.h" -#include "octave-gui.h" #include "octave-qt-link.h" +#include "qt-application.h" #include "resource-manager.h" #include "terminal-dock-widget.h" #include "variable-editor.h" @@ -64,10 +64,9 @@ namespace octave { + class base_qobject; class settings_dialog; - class octave_qt_app; - //! Represents the main window. class main_window : public QMainWindow @@ -79,7 +78,7 @@ typedef std::pair <std::string, std::string> name_pair; typedef std::pair <int, int> int_pair; - main_window (octave_qt_app& oct_qt_app, octave_qt_link *oct_qt_lnk); + main_window (base_qobject& qapp, octave_qt_link *lnk); ~main_window (void); @@ -308,7 +307,7 @@ QList<octave_dock_widget *> dock_widget_list (void); - QApplication *m_qt_app; + QApplication *m_octave_qapp; octave_qt_link *m_octave_qt_link; @@ -440,129 +439,6 @@ QString m_file_encoding; }; - - class octave_qapplication : public QApplication - { - public: - - octave_qapplication (int& argc, char **argv) - : QApplication (argc, argv) - { } - - virtual bool notify (QObject *receiver, QEvent *e) override; - - ~octave_qapplication (void) { }; - }; - - class interpreter_qobject; - - 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 start_main_thread (void); - - int exec (void); - - QApplication *qt_app (void) { return m_qt_app; }; - - public slots: - - void handle_octave_finished (int); - - virtual 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); - - protected: - - 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; - - octave_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; - - interpreter_qobject *m_interpreter_qobject; - - QThread *m_main_thread; - - void connect_uiwidget_links (void); - - void confirm_shutdown_octave_internal (bool closenow); - }; - - class octave_qt_cli_app : public octave_qt_app - { - Q_OBJECT - - public: - - octave_qt_cli_app (gui_application& app_context); - - ~octave_qt_cli_app (void) = default; - }; - - class octave_qt_gui_app : public octave_qt_app - { - Q_OBJECT - - public: - - octave_qt_gui_app (gui_application& app_context); - - ~octave_qt_gui_app (void); - - public slots: - - void confirm_shutdown_octave (void); - - private: - - main_window *m_main_window; - }; } #endif
--- a/libgui/src/module.mk Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/module.mk Sat Jun 22 17:30:16 2019 -0500 @@ -142,6 +142,7 @@ %reldir%/moc-main-window.cc \ %reldir%/moc-news-reader.cc \ %reldir%/moc-octave-cmd.cc \ + %reldir%/moc-octave-qobject.cc \ %reldir%/moc-octave-qt-link.cc \ %reldir%/moc-settings-dialog.cc \ %reldir%/moc-terminal-dock-widget.cc \ @@ -199,9 +200,10 @@ %reldir%/m-editor/marker.h \ %reldir%/main-window.h \ %reldir%/news-reader.h \ - %reldir%/octave-gui.h \ %reldir%/octave-cmd.h \ + %reldir%/octave-qobject.h \ %reldir%/octave-qt-link.h \ + %reldir%/qt-application.h \ %reldir%/resource-manager.h \ %reldir%/settings-dialog.h \ %reldir%/shortcut-manager.h \ @@ -235,8 +237,9 @@ %reldir%/news-reader.cc \ %reldir%/octave-cmd.cc \ %reldir%/octave-dock-widget.cc \ - %reldir%/octave-gui.cc \ + %reldir%/octave-qobject.cc \ %reldir%/octave-qt-link.cc \ + %reldir%/qt-application.cc \ %reldir%/resource-manager.cc \ %reldir%/settings-dialog.cc \ %reldir%/shortcut-manager.cc \
--- a/libgui/src/octave-gui.cc Fri Jun 21 14:41:04 2019 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - -Copyright (C) 2011-2019 Jacob Dawid - -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 (HAVE_CONFIG_H) -# include "config.h" -#endif - -#include "lo-utils.h" -#include "oct-env.h" -#include "oct-syscalls.h" -#include "signal-wrappers.h" - -#include "builtin-defun-decls.h" -#include "display.h" -#include "octave.h" -#include "sysdep.h" - -#include "main-window.h" -#include "octave-gui.h" - -namespace octave -{ - gui_application::gui_application (int argc, char **argv) - : application (argc, argv) - { - // This should probably happen early. - sysdep_init (); - } - - bool gui_application::start_gui_p (void) const - { - return m_options.gui (); - } - - int gui_application::execute (void) - { - octave_block_interrupt_signal (); - - set_application_id (); - - // Create and show main window. - - if (start_gui_p ()) - { - octave_qt_gui_app octave_app (*this); - return octave_app.exec (); - } - else - { - octave_qt_cli_app octave_app (*this); - return octave_app.exec (); - } - } -}
--- a/libgui/src/octave-gui.h Fri Jun 21 14:41:04 2019 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - -Copyright (C) 2012-2019 John W. Eaton - -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_octave_gui_h) -#define octave_octave_gui_h 1 - -#include "octave.h" - -namespace octave -{ - class OCTGUI_API gui_application : public application - { - public: - - gui_application (int argc, char **argv); - - // No copying, at least not yet. - - gui_application (const gui_application&) = delete; - - 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; - - int execute (void); - - bool gui_running (void) const { return m_gui_running; } - void gui_running (bool arg) { m_gui_running = arg; } - - private: - - // If TRUE, the GUI should be started. - bool m_gui_running = false; - }; -} - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/octave-qobject.cc Sat Jun 22 17:30:16 2019 -0500 @@ -0,0 +1,388 @@ +/* + +Copyright (C) 2013-2019 John W. Eaton +Copyright (C) 2011-2019 Jacob Dawid + +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 (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include <QApplication> +#include <QFile> +#include <QTextCodec> +#include <QThread> +#include <QTranslator> +#include <QTimer> + +#include <utility> + +#include "dialog.h" +#include "interpreter-qobject.h" +#include "main-window.h" +#include "octave-qobject.h" +#include "octave-qt-link.h" +#include "qt-application.h" +#include "resource-manager.h" + +#include "oct-env.h" +#include "version.h" + +namespace octave +{ + // 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 + { } + + //! Reimplement QApplication::notify. Octave's own exceptions are + //! caught and rethrown in the interpreter thread. + + bool octave_qapplication::notify (QObject *receiver, QEvent *ev) + { + try + { + return QApplication::notify (receiver, ev); + } + catch (execution_exception&) + { + octave_link::post_exception (std::current_exception ()); + } + + return false; + } + + // We will create a QApplication object, even if START_GUI is false, + // so that we can use Qt widgets for plot windows when running in + // command-line mode. Note that we are creating an + // octave_qapplication object but handling it as a QApplication object + // because the octave_qapplication should behave identically to a + // QApplication object except that it overrides the notify method so + // we can handle forward Octave interpreter exceptions from the GUI + // thread to the interpreter thread. + + base_qobject::base_qobject (qt_application& app_context) + : QObject (), m_app_context (app_context), + m_argc (m_app_context.sys_argc ()), + m_argv (m_app_context.sys_argv ()), + m_octave_qapp (new octave_qapplication (m_argc, m_argv)), + 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_qobject (new interpreter_qobject (m_app_context)), + m_main_thread (new QThread ()) + { + 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"); + + // Force left-to-right alignment (see bug #46204) + m_octave_qapp->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_qobject, SIGNAL (octave_finished_signal (int)), + this, SLOT (handle_octave_finished (int))); + + connect (m_interpreter_qobject, SIGNAL (octave_finished_signal (int)), + m_main_thread, SLOT (quit (void))); + + connect (m_main_thread, SIGNAL (finished (void)), + m_main_thread, SLOT (deleteLater (void))); + } + + base_qobject::~base_qobject (void) + { + delete m_interpreter_qobject; + delete m_octave_qapp; + + string_vector::delete_c_str_vec (m_argv); + } + + void base_qobject::config_translators (void) + { + if (m_translators_installed) + return; + + resource_manager::config_translators (m_qt_tr, m_qsci_tr, m_gui_tr); + + m_octave_qapp->installTranslator (m_qt_tr); + m_octave_qapp->installTranslator (m_gui_tr); + m_octave_qapp->installTranslator (m_qsci_tr); + + m_translators_installed = true; + } + + void base_qobject::start_main_thread (void) + { + // Defer initializing and executing the interpreter until after the main + // window and QApplication are running to prevent race conditions + QTimer::singleShot (0, m_interpreter_qobject, SLOT (execute (void))); + + m_interpreter_qobject->moveToThread (m_main_thread); + + m_main_thread->start (); + } + + int base_qobject::exec (void) + { + return m_octave_qapp->exec (); + } + + void base_qobject::handle_octave_finished (int exit_status) + { + qApp->exit (exit_status); + } + + void base_qobject::confirm_shutdown_octave (void) + { + confirm_shutdown_octave_internal (true); + } + + void base_qobject::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 base_qobject::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 base_qobject::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 base_qobject::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 base_qobject::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 base_qobject::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&))); + } + + void base_qobject::confirm_shutdown_octave_internal (bool closenow) + { + // 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 (); + } + + cli_qobject::cli_qobject (qt_application& app_context) + : base_qobject (app_context) + { + // Get settings file. + resource_manager::reload_settings (); + + // After settings. + config_translators (); + + m_octave_qapp->setQuitOnLastWindowClosed (false); + + start_main_thread (); + } + + gui_qobject::gui_qobject (qt_application& app_context) + : base_qobject (app_context), + m_main_window (new main_window (*this, m_octave_qt_link)) + { + connect (m_interpreter_qobject, SIGNAL (octave_ready_signal (void)), + m_main_window, SLOT (handle_octave_ready (void))); + + m_app_context.gui_running (true); + + start_main_thread (); + } + + gui_qobject::~gui_qobject (void) + { + delete m_main_window; + } + + void gui_qobject::confirm_shutdown_octave (void) + { + bool closenow = true; + + if (m_main_window) + closenow = m_main_window->confirm_shutdown_octave (); + + confirm_shutdown_octave_internal (closenow); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/octave-qobject.h Sat Jun 22 17:30:16 2019 -0500 @@ -0,0 +1,188 @@ +/* + +Copyright (C) 2013-2019 John W. Eaton +Copyright (C) 2011-2019 Jacob Dawid + +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_octave_qobject_h) +#define octave_octave_qobject_h 1 + +#include <QApplication> +#include <QList> +#include <QObject> +#include <QString> +#include <QStringList> + +#include "qt-application.h" + +// Defined for purposes of sending QList<int> as part of signal. +typedef QList<int> QIntList; + +// Defined for purposes of sending QList<float> as part of signal. +typedef QList<float> QFloatList; + +namespace octave +{ + class interpreter_qobject; + class main_window; + class octave_qt_link; + + //! This class is a simple wrapper around QApplication so that we can + //! reimplement QApplication::notify. The octave_qapplication object + //! should behave identically to a QApplication object except that it + //! overrides the notify method so we can handle forward Octave + //! octave::execution_exception exceptions from the GUI thread to the + //! interpreter thread. + + class octave_qapplication : public QApplication + { + public: + + octave_qapplication (int& argc, char **argv) + : QApplication (argc, argv) + { } + + virtual bool notify (QObject *receiver, QEvent *e) override; + + ~octave_qapplication (void) { }; + }; + + //! 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 + //! full GUI experience. + + class base_qobject : public QObject + { + Q_OBJECT + + public: + + base_qobject (qt_application& app_context); + + ~base_qobject (void); + + void config_translators (void); + + void start_main_thread (void); + + int exec (void); + + QApplication *octave_qapp (void) { return m_octave_qapp; }; + + public slots: + + void handle_octave_finished (int); + + virtual 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); + + protected: + + qt_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_octave_qapp; + + QTranslator *m_qt_tr; + QTranslator *m_gui_tr; + QTranslator *m_qsci_tr; + + bool m_translators_installed; + + octave_qt_link *m_octave_qt_link; + + interpreter_qobject *m_interpreter_qobject; + + QThread *m_main_thread; + + void connect_uiwidget_links (void); + + void confirm_shutdown_octave_internal (bool closenow); + }; + + //! This object provides a command-line interface to Octave that may + //! use Qt graphics. + + class cli_qobject : public base_qobject + { + Q_OBJECT + + public: + + cli_qobject (qt_application& app_context); + + ~cli_qobject (void) = default; + }; + + //! This object provides a full GUI interface to Octave that is + //! implemented Qt. + + class gui_qobject : public base_qobject + { + Q_OBJECT + + public: + + gui_qobject (qt_application& app_context); + + ~gui_qobject (void); + + public slots: + + void confirm_shutdown_octave (void); + + private: + + main_window *m_main_window; + }; +} + +#endif +
--- a/libgui/src/octave-qt-link.cc Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/octave-qt-link.cc Sat Jun 22 17:30:16 2019 -0500 @@ -46,8 +46,8 @@ #include "syminfo.h" #include "utils.h" -#include "octave-gui.h" #include "octave-qt-link.h" +#include "qt-application.h" #include "resource-manager.h" Q_DECLARE_METATYPE (octave_value)
--- a/libgui/src/octave-qt-link.h Fri Jun 21 14:41:04 2019 -0500 +++ b/libgui/src/octave-qt-link.h Sat Jun 22 17:30:16 2019 -0500 @@ -34,7 +34,8 @@ #include <QMutex> #include <QWaitCondition> -#include "octave-gui.h" +#include "qt-application.h" + #include "octave-link.h" // Defined for purposes of sending QList<int> as part of signal.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/qt-application.cc Sat Jun 22 17:30:16 2019 -0500 @@ -0,0 +1,74 @@ +/* + +Copyright (C) 2011-2019 Jacob Dawid + +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 (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "lo-utils.h" +#include "oct-env.h" +#include "oct-syscalls.h" +#include "signal-wrappers.h" + +#include "builtin-defun-decls.h" +#include "display.h" +#include "octave.h" +#include "sysdep.h" + +#include "main-window.h" +#include "octave-qobject.h" +#include "qt-application.h" + +namespace octave +{ + qt_application::qt_application (int argc, char **argv) + : application (argc, argv) + { + // This should probably happen early. + sysdep_init (); + } + + bool qt_application::start_gui_p (void) const + { + return m_options.gui (); + } + + int qt_application::execute (void) + { + octave_block_interrupt_signal (); + + set_application_id (); + + // Create and show main window. + + if (start_gui_p ()) + { + gui_qobject gui_interface (*this); + return gui_interface.exec (); + } + else + { + cli_qobject cli_interface (*this); + return cli_interface.exec (); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgui/src/qt-application.h Sat Jun 22 17:30:16 2019 -0500 @@ -0,0 +1,70 @@ +/* + +Copyright (C) 2012-2019 John W. Eaton + +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_octave_gui_h) +#define octave_octave_gui_h 1 + +#include "octave.h" + +namespace octave +{ + // Programming Note: This file must not include any Qt headers. Any + // Qt header files required by the qt_application::execute function + // must be included only in the corresponding .cc file. + + //! This class inherits from the pure-virtual base class + //! octave::application and provides an implementation of the + //! application::execute method that starts an interface to Octave + //! that is based on Qt. It may start a command-line interface that + //! allows Qt graphics to be used or it may start an interface that + //! provides the full GUI experience. + + class OCTGUI_API qt_application : public application + { + public: + + qt_application (int argc, char **argv); + + // No copying, at least not yet. + + qt_application (const qt_application&) = delete; + + qt_application& operator = (const qt_application&) = delete; + + ~qt_application (void) = default; + + // Should we start the GUI or fall back to the CLI? + bool start_gui_p (void) const; + + int execute (void); + + bool gui_running (void) const { return m_gui_running; } + void gui_running (bool arg) { m_gui_running = arg; } + + private: + + // If TRUE, the GUI should be started. + bool m_gui_running = false; + }; +} + +#endif
--- a/src/main-gui.cc Fri Jun 21 14:41:04 2019 -0500 +++ b/src/main-gui.cc Sat Jun 22 17:30:16 2019 -0500 @@ -39,7 +39,7 @@ #include "octave.h" #include "octave-build-info.h" -#include "octave-gui.h" +#include "qt-application.h" #include "sysdep.h" static void @@ -98,7 +98,7 @@ octave::sys::env::set_program_name (argv[0]); - octave::gui_application app (argc, argv); + octave::qt_application app (argc, argv); return app.execute (); }