/libgui/src/main-window.cc
C++ | 2354 lines | 1776 code | 460 blank | 118 comment | 127 complexity | e67221535b71e6a2f58a858c179bf5bf MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /*
- Copyright (C) 2013-2015 John W. Eaton
- Copyright (C) 2011-2015 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
- <http://www.gnu.org/licenses/>.
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <QKeySequence>
- #include <QApplication>
- #include <QLabel>
- #include <QMenuBar>
- #include <QMenu>
- #include <QAction>
- #include <QSettings>
- #include <QStyle>
- #include <QToolBar>
- #include <QDesktopServices>
- #include <QDesktopWidget>
- #include <QFileDialog>
- #include <QMessageBox>
- #include <QIcon>
- #include <QTextStream>
- #include <QThread>
- #include <QDateTime>
- #include <QDebug>
- #include <utility>
- #ifdef HAVE_QSCINTILLA
- #include "file-editor.h"
- #endif
- #include "main-window.h"
- #include "settings-dialog.h"
- #include "shortcut-manager.h"
- #include "__init_qt__.h"
- #include "Array.h"
- #include "cmd-edit.h"
- #include "url-transfer.h"
- #include "builtin-defun-decls.h"
- #include "defaults.h"
- #include "symtab.h"
- #include "version.h"
- #include "utils.h"
- static file_editor_interface *
- create_default_editor (QWidget *p)
- {
- #ifdef HAVE_QSCINTILLA
- return new file_editor (p);
- #else
- return 0;
- #endif
- }
- main_window::main_window (QWidget *p)
- : QMainWindow (p),
- _workspace_model (new workspace_model ()),
- status_bar (new QStatusBar ()),
- command_window (new terminal_dock_widget (this)),
- history_window (new history_dock_widget (this)),
- file_browser_window (new files_dock_widget (this)),
- doc_browser_window (new documentation_dock_widget (this)),
- editor_window (create_default_editor (this)),
- workspace_window (new workspace_view (this)),
- _settings_dlg (0),
- find_files_dlg (0),
- release_notes_window (0),
- community_news_window (0),
- _octave_qt_link (0),
- _clipboard (QApplication::clipboard ()),
- _cmd_queue (QList<octave_cmd *> ()), // no command pending
- _cmd_processing (1),
- _cmd_queue_mutex (),
- _dbg_queue (new QStringList ()), // no debug pending
- _dbg_processing (1),
- _dbg_queue_mutex (),
- _prevent_readline_conflicts (true)
- {
- QSettings *settings = resource_manager::get_settings ();
- bool connect_to_web = true;
- QDateTime last_checked;
- int serial = 0;
- _active_dock = 0;
- if (settings)
- {
- connect_to_web
- = settings->value ("news/allow_web_connection", true).toBool ();
- last_checked
- = settings->value ("news/last_time_checked", QDateTime ()).toDateTime ();
- serial = settings->value ("news/last_news_item", 0).toInt ();
- }
- QDateTime current = QDateTime::currentDateTime ();
- QDateTime one_day_ago = current.addDays (-1);
- if (connect_to_web
- && (! last_checked.isValid () || one_day_ago > last_checked))
- load_and_display_community_news (serial);
- // We have to set up all our windows, before we finally launch octave.
- construct ();
- }
- main_window::~main_window (void)
- {
- // Destroy the terminal first so that STDERR stream is redirected back
- // to its original pipe to capture error messages at exit.
- delete editor_window; // first one for dialogs of modified editor-tabs
- delete command_window;
- delete workspace_window;
- delete doc_browser_window;
- delete file_browser_window;
- delete history_window;
- delete status_bar;
- delete _workspace_model;
- if (find_files_dlg)
- {
- delete find_files_dlg;
- find_files_dlg = 0;
- }
- if (release_notes_window)
- {
- delete release_notes_window;
- release_notes_window = 0;
- }
- if (_settings_dlg)
- {
- delete _settings_dlg;
- _settings_dlg = 0;
- }
- if (community_news_window)
- {
- delete community_news_window;
- community_news_window = 0;
- }
- delete _octave_qt_link;
- }
- // catch focus changes and determine the active dock widget
- void
- main_window::focus_changed (QWidget *, QWidget *new_widget)
- {
- octave_dock_widget* dock = 0;
- QWidget *w_new = new_widget; // get a copy of new focus widget
- QWidget *start = w_new; // Save it as start of our search
- int count = 0; // fallback to prevent endless loop
- while (w_new && w_new != _main_tool_bar && count < 100)
- {
- dock = qobject_cast <octave_dock_widget *> (w_new);
- if (dock)
- break; // it is a QDockWidget ==> exit loop
- #ifdef HAVE_QSCINTILLA
- if (qobject_cast <octave_qscintilla *> (w_new))
- {
- dock = static_cast<octave_dock_widget *> (editor_window);
- break; // it is the editor window ==> exit loop
- }
- #endif
- w_new = qobject_cast <QWidget *> (w_new->previousInFocusChain ());
- if (w_new == start)
- break; // we have arrived where we began ==> exit loop
- count++;
- }
- // editor needs extra handling
- octave_dock_widget *edit_dock_widget =
- static_cast<octave_dock_widget *> (editor_window);
- // if new dock has focus, emit signal and store active focus
- // except editor changes to a dialog (dock=0)
- if ((dock || _active_dock != edit_dock_widget) && (dock != _active_dock))
- {
- // signal to all dock widgets for updating the style
- emit active_dock_changed (_active_dock, dock);
- if (edit_dock_widget == dock)
- emit editor_focus_changed (true);
- else if (edit_dock_widget == _active_dock)
- emit editor_focus_changed (false);
- _active_dock = dock;
- }
- }
- bool
- main_window::command_window_has_focus (void) const
- {
- return command_window->has_focus ();
- }
- void
- main_window::focus_command_window (void)
- {
- command_window->focus ();
- }
- void
- main_window::new_file (const QString& commands)
- {
- emit new_file_signal (commands);
- }
- void
- main_window::open_file (const QString& file_name)
- {
- emit open_file_signal (file_name);
- }
- void
- main_window::report_status_message (const QString& statusMessage)
- {
- status_bar->showMessage (statusMessage, 1000);
- }
- void
- main_window::handle_save_workspace_request (void)
- {
- QString file =
- QFileDialog::getSaveFileName (this, tr ("Save Workspace As"), ".", 0, 0,
- QFileDialog::DontUseNativeDialog);
- if (! file.isEmpty ())
- octave_link::post_event (this, &main_window::save_workspace_callback,
- file.toStdString ());
- }
- void
- main_window::handle_load_workspace_request (const QString& file_arg)
- {
- QString file = file_arg;
- if (file.isEmpty ())
- file = QFileDialog::getOpenFileName (this, tr ("Load Workspace"), ".", 0, 0,
- QFileDialog::DontUseNativeDialog);
- if (! file.isEmpty ())
- octave_link::post_event (this, &main_window::load_workspace_callback,
- file.toStdString ());
- }
- void
- main_window::handle_clear_workspace_request (void)
- {
- octave_link::post_event (this, &main_window::clear_workspace_callback);
- }
- void
- main_window::handle_rename_variable_request (const QString& old_name,
- const QString& new_name)
- {
- name_pair names (old_name.toStdString (), new_name.toStdString ());
- octave_link::post_event (this, &main_window::rename_variable_callback,
- names);
- }
- void
- main_window::handle_undo_request (void)
- {
- octave_link::post_event (this, &main_window::command_window_undo_callback);
- }
- void
- main_window::handle_clear_command_window_request (void)
- {
- octave_link::post_event (this, &main_window::clear_command_window_callback);
- }
- void
- main_window::handle_clear_history_request (void)
- {
- octave_link::post_event (this, &main_window::clear_history_callback);
- }
- bool
- main_window::focus_console_after_command ()
- {
- QSettings *settings = resource_manager::get_settings ();
- return settings->value ("terminal/focus_after_command",false).toBool ();
- }
- void
- main_window::execute_command_in_terminal (const QString& command)
- {
- octave_cmd_exec *cmd = new octave_cmd_exec (command);
- queue_command (cmd);
- if (focus_console_after_command ())
- focus_command_window ();
- }
- void
- main_window::run_file_in_terminal (const QFileInfo& info)
- {
- octave_link::post_event (this, &main_window::run_file_callback, info);
- if (focus_console_after_command ())
- focus_command_window ();
- }
- void
- main_window::run_file_callback (const QFileInfo& info)
- {
- octave_cmd_eval *cmd = new octave_cmd_eval (info);
- queue_command (cmd);
- }
- void
- main_window::queue_command (octave_cmd* cmd)
- {
- _cmd_queue_mutex.lock ();
- _cmd_queue.append (cmd); // queue command and type
- _cmd_queue_mutex.unlock ();
- if (_cmd_processing.tryAcquire ()) // if callback not processing, post event
- octave_link::post_event (this, &main_window::execute_command_callback);
- }
- void
- main_window::handle_new_figure_request (void)
- {
- octave_link::post_event (this, &main_window::new_figure_callback);
- }
- void
- main_window::open_online_documentation_page (void)
- {
- QDesktopServices::openUrl (QUrl ("http://octave.org/doc/interpreter"));
- }
- void
- main_window::display_release_notes (void)
- {
- if (! release_notes_window)
- {
- std::string news_file = Voct_etc_dir + "/NEWS";
- QString news;
- QFile *file = new QFile (QString::fromStdString (news_file));
- if (file->open (QFile::ReadOnly))
- {
- QTextStream *stream = new QTextStream (file);
- news = stream->readAll ();
- if (! news.isEmpty ())
- {
- news.prepend ("<pre>");
- news.append ("</pre>");
- }
- else
- news = (tr ("The release notes file '%1' is empty.")
- . arg (QString::fromStdString (news_file)));
- }
- else
- news = (tr ("The release notes file '%1' cannot be read.")
- . arg (QString::fromStdString (news_file)));
- release_notes_window = new QWidget;
- QTextBrowser *browser = new QTextBrowser (release_notes_window);
- browser->setText (news);
- QVBoxLayout *vlayout = new QVBoxLayout;
- vlayout->addWidget (browser);
- release_notes_window->setLayout (vlayout);
- release_notes_window->setWindowTitle (tr ("Octave Release Notes"));
- browser->document()->adjustSize ();
- // center the window on the screen where octave is running
- QDesktopWidget *m_desktop = QApplication::desktop ();
- int screen = m_desktop->screenNumber (this); // screen of the main window
- QRect screen_geo = m_desktop->availableGeometry (screen);
- int win_x = screen_geo.width (); // width of the screen
- int win_y = screen_geo.height (); // height of the screen
- int reln_x = std::min (480, win_x-80); // desired width of release notes
- int reln_y = std::min (640, win_y-80); // desired height of release notes
- release_notes_window->resize (reln_x, reln_y); // set size
- release_notes_window->move (20, 0); // move to the top left corner
- }
- if (! release_notes_window->isVisible ())
- release_notes_window->show ();
- else if (release_notes_window->isMinimized ())
- release_notes_window->showNormal ();
- release_notes_window->setWindowIcon (QIcon (_release_notes_icon));
- release_notes_window->raise ();
- release_notes_window->activateWindow ();
- }
- void
- news_reader::process (void)
- {
- QString html_text;
- if (connect_to_web)
- {
- // Run this part in a separate thread so Octave can continue to
- // run while we wait for the page to load. Then emit the signal
- // to display it when we have the page contents.
- QString url = base_url + "/" + page;
- std::ostringstream buf;
- url_transfer octave_dot_org (url.toStdString (), buf);
- if (octave_dot_org.is_valid ())
- {
- Array<std::string> param;
- octave_dot_org.http_get (param);
- if (octave_dot_org.good ())
- html_text = QString::fromStdString (buf.str ());
- }
- if (html_text.contains ("this-is-the-gnu-octave-community-news-page"))
- {
- if (serial >= 0)
- {
- QSettings *settings = resource_manager::get_settings ();
- if (settings)
- {
- settings->setValue ("news/last_time_checked",
- QDateTime::currentDateTime ());
- settings->sync ();
- }
- QString tag ("community-news-page-serial=");
- int b = html_text.indexOf (tag);
- if (b)
- {
- b += tag.length ();
- int e = html_text.indexOf ("\n", b);
- QString tmp = html_text.mid (b, e-b);
- int curr_page_serial = tmp.toInt ();
- if (curr_page_serial > serial)
- {
- if (settings)
- {
- settings->setValue ("news/last_news_item",
- curr_page_serial);
- settings->sync ();
- }
- }
- else
- return;
- }
- else
- return;
- }
- }
- else
- html_text = QString
- (tr ("<html>\n"
- "<body>\n"
- "<p>\n"
- "Octave's community news source seems to be unavailable.\n"
- "</p>\n"
- "<p>\n"
- "For the latest news, please check\n"
- "<a href=\"http://octave.org/community-news.html\">http://octave.org/community-news.html</a>\n"
- "when you have a connection to the web (link opens in an external browser).\n"
- "</p>\n"
- "<p>\n"
- "<small><em>— The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
- "</p>\n"
- "</body>\n"
- "</html>\n");
- }
- else
- html_text = QString
- (tr ("<html>\n"
- "<body>\n"
- "<p>\n"
- "Connecting to the web to display the latest Octave Community news has been disabled.\n"
- "</p>\n"
- "<p>\n"
- "For the latest news, please check\n"
- "<a href=\"http://octave.org/community-news.html\">http://octave.org/community-news.html</a>\n"
- "when you have a connection to the web (link opens in an external browser)\n"
- "or enable web connections for news in Octave's network settings dialog.\n"
- "</p>\n"
- "<p>\n"
- "<small><em>— The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
- "</p>\n"
- "</body>\n"
- "</html>\n");
- emit display_news_signal (html_text);
- emit finished ();
- }
- void
- main_window::load_and_display_community_news (int serial)
- {
- QSettings *settings = resource_manager::get_settings ();
- bool connect_to_web
- = (settings
- ? settings->value ("news/allow_web_connection", true).toBool ()
- : true);
- QString base_url = "http://octave.org";
- QString page = "community-news.html";
- QThread *worker_thread = new QThread;
- news_reader *reader = new news_reader (base_url, page, serial,
- connect_to_web);
- reader->moveToThread (worker_thread);
- connect (reader, SIGNAL (display_news_signal (const QString&)),
- this, SLOT (display_community_news (const QString&)));
- connect (worker_thread, SIGNAL (started (void)),
- reader, SLOT (process ()));
- connect (reader, SIGNAL (finished (void)), worker_thread, SLOT (quit ()));
- connect (reader, SIGNAL (finished (void)), reader, SLOT (deleteLater ()));
- connect (worker_thread, SIGNAL (finished (void)),
- worker_thread, SLOT (deleteLater ()));
- worker_thread->start ();
- }
- void
- main_window::display_community_news (const QString& news)
- {
- if (! community_news_window)
- {
- community_news_window = new QWidget;
- QTextBrowser *browser = new QTextBrowser (community_news_window);
- browser->setHtml (news);
- browser->setObjectName ("OctaveNews");
- browser->setOpenExternalLinks (true);
- QVBoxLayout *vlayout = new QVBoxLayout;
- vlayout->addWidget (browser);
- community_news_window->setLayout (vlayout);
- community_news_window->setWindowTitle (tr ("Octave Community News"));
- // center the window on the screen where octave is running
- QDesktopWidget *m_desktop = QApplication::desktop ();
- int screen = m_desktop->screenNumber (this); // screen of the main window
- QRect screen_geo = m_desktop->availableGeometry (screen);
- int win_x = screen_geo.width (); // width of the screen
- int win_y = screen_geo.height (); // height of the screen
- int news_x = std::min (640, win_x-80); // desired width of news window
- int news_y = std::min (480, win_y-80); // desired height of news window
- community_news_window->resize (news_x, news_y); // set size and center
- community_news_window->move ((win_x - community_news_window->width ())/2,
- (win_y - community_news_window->height ())/2);
- }
- if (! community_news_window->isVisible ())
- community_news_window->show ();
- else if (community_news_window->isMinimized ())
- community_news_window->showNormal ();
- // same icon as release notes
- community_news_window->setWindowIcon (QIcon (_release_notes_icon));
- community_news_window->raise ();
- community_news_window->activateWindow ();
- }
- void
- main_window::open_bug_tracker_page (void)
- {
- QDesktopServices::openUrl (QUrl ("http://octave.org/bugs.html"));
- }
- void
- main_window::open_octave_packages_page (void)
- {
- QDesktopServices::openUrl (QUrl ("http://octave.org/packages.html"));
- }
- void
- main_window::open_agora_page (void)
- {
- QDesktopServices::openUrl (QUrl ("http://agora.octave.org"));
- }
- void
- main_window::open_contribute_page (void)
- {
- QDesktopServices::openUrl (QUrl ("http://octave.org/donate.html"));
- }
- void
- main_window::open_developer_page (void)
- {
- QDesktopServices::openUrl (QUrl ("http://octave.org/get-involved.html"));
- }
- void
- main_window::process_settings_dialog_request (const QString& desired_tab)
- {
- if (_settings_dlg) // _settings_dlg is a guarded pointer!
- { // here the dialog is still open and called once again
- if (! desired_tab.isEmpty ())
- _settings_dlg->show_tab (desired_tab);
- return;
- }
- _settings_dlg = new settings_dialog (this, desired_tab);
- connect (_settings_dlg, SIGNAL (apply_new_settings ()),
- this, SLOT (request_reload_settings ()));
- _settings_dlg->setModal (false);
- _settings_dlg->setAttribute (Qt::WA_DeleteOnClose);
- _settings_dlg->show ();
- }
- void
- main_window::request_reload_settings ()
- {
- QSettings *settings = resource_manager::get_settings ();
- if (settings)
- emit settings_changed (settings);
- }
- void
- main_window::notice_settings (const QSettings *settings)
- {
- // QSettings pointer is checked before emitting.
- // the widget's icons (when floating)
- QString icon_set
- = settings->value ("DockWidgets/widget_icon_set", "NONE").toString ();
- static struct
- {
- QString name;
- QString path;
- }
- widget_icon_data[] =
- {
- // array of possible icon sets (name, path (complete for NONE))
- // the first entry here is the default!
- {"NONE", ":/actions/icons/logo.png"},
- {"GRAPHIC", ":/actions/icons/graphic_logo_"},
- {"LETTER", ":/actions/icons/letter_logo_"},
- {"", ""} // end marker has empty name
- };
- int count = 0;
- int icon_set_found = 0; // default
- while (!widget_icon_data[count].name.isEmpty ())
- {
- // while not end of data
- if (widget_icon_data[count].name == icon_set)
- {
- // data of desired icon set found
- icon_set_found = count;
- break;
- }
- count++;
- }
- QString icon;
- foreach (octave_dock_widget *widget, dock_widget_list ())
- {
- QString name = widget->objectName ();
- if (! name.isEmpty ())
- { // if children has a name
- icon = widget_icon_data[icon_set_found].path; // prefix or octave-logo
- if (widget_icon_data[icon_set_found].name != "NONE")
- icon = icon + name + ".png"; // add widget name and ext.
- widget->setWindowIcon (QIcon (icon));
- }
- }
- if (widget_icon_data[icon_set_found].name != "NONE")
- _release_notes_icon = widget_icon_data[icon_set_found].path
- + "ReleaseWidget.png";
- else
- _release_notes_icon = ":/actions/icons/logo.png";
- int icon_size = settings->value ("toolbar_icon_size",16).toInt ();
- _main_tool_bar->setIconSize (QSize (icon_size,icon_size));
- if (settings->value ("show_status_bar",true).toBool ())
- status_bar->show ();
- else
- status_bar->hide ();
- _prevent_readline_conflicts =
- settings->value ("shortcuts/prevent_readline_conflicts", true).toBool ();
- configure_shortcuts ();
- set_global_shortcuts (command_window_has_focus ());
- _suppress_dbg_location =
- ! settings->value ("terminal/print_debug_location", false).toBool ();
- resource_manager::update_network_settings ();
- }
- void
- main_window::confirm_shutdown_octave (void)
- {
- bool closenow = true;
- QSettings *settings = resource_manager::get_settings ();
- if (settings->value ("prompt_to_exit", false).toBool ())
- {
- int ans = QMessageBox::question (this, tr ("Octave"),
- tr ("Are you sure you want to exit Octave?"),
- QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
- if (ans != QMessageBox::Ok)
- closenow = false;
- }
- #ifdef HAVE_QSCINTILLA
- if (closenow)
- closenow = editor_window->check_closing ();
- #endif
- _octave_qt_link->shutdown_confirmation (closenow);
- // Awake the worker thread so that it continues shutting down (or not).
- _octave_qt_link->waitcondition.wakeAll ();
- }
- void
- main_window::prepare_to_exit (void)
- {
- write_settings ();
- }
- void
- main_window::exit_app (int status)
- {
- qApp->exit (status);
- }
- void
- main_window::reset_windows (void)
- {
- QSettings *settings = resource_manager::get_default_settings ();
- set_window_layout (settings);
- showNormal (); // make sure main window is not minimized
- }
- void
- main_window::change_directory (const QString& dir)
- {
- // Remove existing entry, if any, then add new directory at top and
- // mark it as the current directory. Finally, update the file list
- // widget.
- int index = _current_directory_combo_box->findText (dir);
- if (index >= 0)
- _current_directory_combo_box->removeItem (index);
- _current_directory_combo_box->insertItem (0, dir);
- _current_directory_combo_box->setCurrentIndex (0);
- }
- void
- main_window::browse_for_directory (void)
- {
- QString dir
- = QFileDialog::getExistingDirectory (this, tr ("Browse directories"), 0,
- QFileDialog::ShowDirsOnly |
- QFileDialog::DontUseNativeDialog);
- set_current_working_directory (dir);
- // FIXME: on Windows systems, the command window freezes after the
- // previous actions. Forcing the focus appears to unstick it.
- focus_command_window ();
- }
- void
- main_window::set_current_working_directory (const QString& dir)
- {
- // Change to dir if it is an existing directory.
- QString xdir = dir.isEmpty () ? "." : dir;
- QFileInfo fileInfo (xdir);
- if (fileInfo.exists () && fileInfo.isDir ())
- octave_link::post_event (this, &main_window::change_directory_callback,
- xdir.toStdString ());
- }
- void
- main_window::change_directory_up (void)
- {
- set_current_working_directory ("..");
- }
- // Slot that is called if return is pressed in the line edit of the
- // combobox to change to a new directory or a directory that is already
- // in the drop down list.
- void
- main_window::accept_directory_line_edit (void)
- {
- // Get new directory name, and change to it if it is new. Otherwise,
- // the combo box will triggers the "activated" signal to change to the
- // directory.
- QString dir = _current_directory_combo_box->currentText ();
- int index = _current_directory_combo_box->findText (dir);
- if (index < 0)
- set_current_working_directory (dir);
- }
- void
- main_window::handle_enter_debugger (void)
- {
- setWindowTitle ("Octave (Debugging)");
- _debug_continue->setEnabled (true);
- _debug_step_into->setEnabled (true);
- _debug_step_over->setEnabled (true);
- _debug_step_out->setEnabled (true);
- _debug_quit->setEnabled (true);
- #ifdef HAVE_QSCINTILLA
- editor_window->handle_enter_debug_mode ();
- #endif
- }
- void
- main_window::handle_exit_debugger (void)
- {
- setWindowTitle ("Octave");
- _debug_continue->setEnabled (false);
- _debug_step_into->setEnabled (false);
- _debug_step_over->setEnabled (false);
- _debug_step_out->setEnabled (false);
- _debug_quit->setEnabled (false);
- #ifdef HAVE_QSCINTILLA
- editor_window->handle_exit_debug_mode ();
- #endif
- }
- void
- main_window::debug_continue (void)
- {
- queue_debug ("cont");
- }
- void
- main_window::debug_step_into (void)
- {
- queue_debug ("in");
- }
- void
- main_window::debug_step_over (void)
- {
- queue_debug ("step");
- }
- void
- main_window::debug_step_out (void)
- {
- queue_debug ("out");
- }
- void
- main_window::debug_quit (void)
- {
- queue_debug ("quit");
- }
- void
- main_window::handle_insert_debugger_pointer_request (const QString& file,
- int line)
- {
- bool cmd_focus = command_window_has_focus ();
- emit insert_debugger_pointer_signal (file, line);
- if (cmd_focus)
- focus_command_window ();
- }
- void
- main_window::handle_delete_debugger_pointer_request (const QString& file,
- int line)
- {
- bool cmd_focus = command_window_has_focus ();
- emit delete_debugger_pointer_signal (file, line);
- if (cmd_focus)
- focus_command_window ();
- }
- void
- main_window::handle_update_breakpoint_marker_request (bool insert,
- const QString& file,
- int line)
- {
- bool cmd_focus = command_window_has_focus ();
- emit update_breakpoint_marker_signal (insert, file, line);
- if (cmd_focus)
- focus_command_window ();
- }
- void
- main_window::show_about_octave (void)
- {
- std::string message
- = octave_name_version_copyright_copying_warranty_and_bugs (true);
- QMessageBox::about (this, tr ("About Octave"),
- QString::fromStdString (message));
- }
- void
- main_window::closeEvent (QCloseEvent *e)
- {
- e->ignore ();
- octave_cmd_exec *cmd = new octave_cmd_exec ("exit");
- queue_command (cmd);
- }
- void
- main_window::read_settings (void)
- {
- QSettings *settings = resource_manager::get_settings ();
- if (!settings)
- {
- qDebug ("Error: QSettings pointer from resource manager is NULL.");
- return;
- }
- set_window_layout (settings);
- // restore the list of the last directories
- QStringList curr_dirs
- = settings->value ("MainWindow/current_directory_list").toStringList ();
- for (int i=0; i < curr_dirs.size (); i++)
- {
- _current_directory_combo_box->addItem (curr_dirs.at (i));
- }
- emit settings_changed (settings);
- }
- void
- main_window::init_terminal_size (void)
- {
- emit init_terminal_size_signal ();
- }
- void
- main_window::set_window_layout (QSettings *settings)
- {
- #if ! defined (Q_OS_WIN32)
- restoreState (settings->value ("MainWindow/windowState").toByteArray ());
- restoreGeometry (settings->value ("MainWindow/geometry").toByteArray ());
- #endif
- // Restore the geometry of all dock-widgets
- foreach (octave_dock_widget *widget, dock_widget_list ())
- {
- QString name = widget->objectName ();
- if (! name.isEmpty ())
- {
- bool floating = settings->value
- ("DockWidgets/" + name + "Floating", false).toBool ();
- bool visible = settings->value
- ("DockWidgets/" + name + "Visible", true).toBool ();
- // If floating, make window from widget.
- if (floating)
- widget->make_window ();
- else if (! widget->parent ()) // should not be floating but is
- widget->make_widget (false); // no docking, just reparent
- #if ! defined (Q_OS_WIN32)
- // restore geometry
- QVariant val = settings->value ("DockWidgets/" + name);
- widget->restoreGeometry (val.toByteArray ());
- #endif
- // make widget visible if desired
- if (floating && visible) // floating and visible
- {
- if (settings->value ("DockWidgets/" + widget->objectName () + "_minimized").toBool ())
- widget->showMinimized ();
- else
- widget->setVisible (true);
- }
- else
- {
- widget->make_widget ();
- widget->setVisible (visible); // not floating -> show
- }
- }
- }
- #if defined (Q_OS_WIN32)
- restoreState (settings->value ("MainWindow/windowState").toByteArray ());
- restoreGeometry (settings->value ("MainWindow/geometry").toByteArray ());
- #endif
- show ();
- }
- void
- main_window::write_settings (void)
- {
- QSettings *settings = resource_manager::get_settings ();
- if (!settings)
- {
- qDebug ("Error: QSettings pointer from resource manager is NULL.");
- return;
- }
- settings->setValue ("MainWindow/geometry", saveGeometry ());
- settings->setValue ("MainWindow/windowState", saveState ());
- // write the list of recent used directories
- QStringList curr_dirs;
- for (int i=0; i<_current_directory_combo_box->count (); i++)
- {
- curr_dirs.append (_current_directory_combo_box->itemText (i));
- }
- settings->setValue ("MainWindow/current_directory_list", curr_dirs);
- settings->sync ();
- }
- // Connecting the signals emitted when the visibility of a widget changes.
- // This has to be done after the window is shown (see octave-gui.cc)
- void
- main_window::connect_visibility_changed (void)
- {
- foreach (octave_dock_widget *widget, dock_widget_list ())
- widget->connect_visibility_changed ();
- #ifdef HAVE_QSCINTILLA
- editor_window->enable_menu_shortcuts (false);
- #endif
- }
- void
- main_window::copyClipboard (void)
- {
- if (_current_directory_combo_box->hasFocus ())
- {
- QLineEdit * edit = _current_directory_combo_box->lineEdit ();
- if (edit && edit->hasSelectedText ())
- {
- QClipboard *clipboard = QApplication::clipboard ();
- clipboard->setText (edit->selectedText ());
- }
- }
- else
- emit copyClipboard_signal ();
- }
- void
- main_window::pasteClipboard (void)
- {
- if (_current_directory_combo_box->hasFocus ())
- {
- QLineEdit * edit = _current_directory_combo_box->lineEdit ();
- QClipboard *clipboard = QApplication::clipboard ();
- QString str = clipboard->text ();
- if (edit && str.length () > 0)
- {
- edit->insert (str);
- }
- }
- else
- emit pasteClipboard_signal ();
- }
- void
- main_window::selectAll (void)
- {
- if (_current_directory_combo_box->hasFocus ())
- {
- QLineEdit * edit = _current_directory_combo_box->lineEdit ();
- if (edit)
- {
- edit->selectAll ();
- }
- }
- else
- emit selectAll_signal ();
- }
- // Connect the signals emitted when the Octave thread wants to create
- // a dialog box of some sort. Perhaps a better place for this would be
- // as part of the QUIWidgetCreator class. However, mainWindow currently
- // is not a global variable and not accessible for connecting.
- void
- main_window::connect_uiwidget_links ()
- {
- connect (&uiwidget_creator,
- SIGNAL (create_dialog (const QString&, const QString&,
- const QString&, const QStringList&,
- const QString&, const QStringList&)),
- this,
- SLOT (handle_create_dialog (const QString&, const QString&,
- const QString&, const QStringList&,
- const QString&, const QStringList&)));
- // Register QIntList so that list of ints may be part of a signal.
- qRegisterMetaType<QIntList> ("QIntList");
- connect (&uiwidget_creator,
- SIGNAL (create_listview (const QStringList&, const QString&,
- int, int, const QIntList&,
- const QString&, const QStringList&,
- const QString&, const QString&)),
- this,
- SLOT (handle_create_listview (const QStringList&, const QString&,
- int, int, const QIntList&,
- const QString&, const QStringList&,
- const QString&, const QString&)));
- // Register QFloatList so that list of floats may be part of a signal.
- qRegisterMetaType<QFloatList> ("QFloatList");
- connect (&uiwidget_creator,
- SIGNAL (create_inputlayout (const QStringList&, const QString&,
- const QFloatList&, const QFloatList&,
- const QStringList&)),
- this,
- SLOT (handle_create_inputlayout (const QStringList&, const QString&,
- const QFloatList&,
- const QFloatList&,
- const QStringList&)));
- connect (&uiwidget_creator,
- SIGNAL (create_filedialog (const QStringList &,const QString&,
- const QString&, const QString&,
- const QString&)),
- this,
- SLOT (handle_create_filedialog (const QStringList &, const QString&,
- const QString&, const QString&,
- const QString&)));
- }
- // Create a message dialog with specified string, buttons and decorative
- // text.
- void
- main_window::handle_create_dialog (const QString& message,
- const QString& title,
- const QString& icon,
- const QStringList& button,
- const QString& defbutton,
- const QStringList& role)
- {
- MessageDialog *message_dialog = new MessageDialog (message, title, icon,
- button, defbutton, role);
- message_dialog->setAttribute (Qt::WA_DeleteOnClose);
- message_dialog->show ();
- }
- // Create a list dialog with specified list, initially selected, mode,
- // view size and decorative text.
- void
- main_window::handle_create_listview (const QStringList& list,
- const QString& mode,
- int wd, int ht,
- const QIntList& initial,
- const QString& name,
- const QStringList& prompt,
- const QString& ok_string,
- const QString& cancel_string)
- {
- ListDialog *list_dialog = new ListDialog (list, mode, wd, ht,
- initial, name, prompt,
- ok_string, cancel_string);
- list_dialog->setAttribute (Qt::WA_DeleteOnClose);
- list_dialog->show ();
- }
- // Create an input dialog with specified prompts and defaults, title and
- // row/column size specifications.
- void
- main_window::handle_create_inputlayout (const QStringList& prompt,
- const QString& title,
- const QFloatList& nr,
- const QFloatList& nc,
- const QStringList& defaults)
- {
- InputDialog *input_dialog = new InputDialog (prompt, title, nr, nc,
- defaults);
- input_dialog->setAttribute (Qt::WA_DeleteOnClose);
- input_dialog->show ();
- }
- void
- main_window::handle_create_filedialog (const QStringList& filters,
- const QString& title,
- const QString& filename,
- const QString& dirname,
- const QString& multimode)
- {
- FileDialog *file_dialog = new FileDialog (filters, title, filename,
- dirname, multimode);
- file_dialog->setAttribute (Qt::WA_DeleteOnClose);
- file_dialog->show ();
- }
- // Main subroutine of the constructor
- void
- main_window::construct (void)
- {
- _closing = false; // flag for editor files when closed
- setWindowIcon (QIcon (":/actions/icons/logo.png"));
- workspace_window->setModel (_workspace_model);
- connect (_workspace_model, SIGNAL (model_changed (void)),
- workspace_window, SLOT (handle_model_changed (void)));
- // Create and set the central widget. QMainWindow takes ownership of
- // the widget (pointer) so there is no need to delete the object upon
- // destroying this main_window.
- QWidget *dummyWidget = new QWidget ();
- dummyWidget->setObjectName ("CentralDummyWidget");
- dummyWidget->resize (10, 10);
- dummyWidget->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);
- dummyWidget->hide ();
- setCentralWidget (dummyWidget);
- construct_menu_bar ();
- construct_tool_bar ();
- connect (qApp, SIGNAL (aboutToQuit ()),
- this, SLOT (prepare_to_exit ()));
- connect (qApp, SIGNAL (focusChanged (QWidget*, QWidget*)),
- this, SLOT(focus_changed (QWidget*, QWidget*)));
- connect (this, SIGNAL (settings_changed (const QSettings *)),
- this, SLOT (notice_settings (const QSettings *)));
- connect (this, SIGNAL (editor_focus_changed (bool)),
- this, SLOT (set_global_edit_shortcuts (bool)));
- connect (this, SIGNAL (editor_focus_changed (bool)),
- editor_window, SLOT (enable_menu_shortcuts (bool)));
- connect (file_browser_window, SIGNAL (load_file_signal (const QString&)),
- this, SLOT (handle_load_workspace_request (const QString&)));
- connect (file_browser_window, SIGNAL (find_files_signal (const QString&)),
- this, SLOT (find_files (const QString&)));
- connect_uiwidget_links ();
- setWindowTitle ("Octave");
- setDockOptions (QMainWindow::AnimatedDocks
- | QMainWindow::AllowNestedDocks
- | QMainWindow::AllowTabbedDocks);
- addDockWidget (Qt::RightDockWidgetArea, command_window);
- addDockWidget (Qt::RightDockWidgetArea, doc_browser_window);
- tabifyDockWidget (command_window, doc_browser_window);
- #ifdef HAVE_QSCINTILLA
- addDockWidget (Qt::RightDockWidgetArea, editor_window);
- tabifyDockWidget (command_window, editor_window);
- #endif
- addDockWidget (Qt::LeftDockWidgetArea, file_browser_window);
- addDockWidget (Qt::LeftDockWidgetArea, workspace_window);
- addDockWidget (Qt::LeftDockWidgetArea, history_window);
- int win_x = QApplication::desktop ()->width ();
- int win_y = QApplication::desktop ()->height ();
- if (win_x > 960)
- win_x = 960;
- if (win_y > 720)
- win_y = 720;
- setGeometry (0, 0, win_x, win_y);
- setStatusBar (status_bar);
- construct_octave_qt_link ();
- #ifdef HAVE_QSCINTILLA
- connect (this,
- SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
- editor_window,
- SLOT (handle_insert_debugger_pointer_request (const QString&, int)));
- connect (this,
- SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
- editor_window,
- SLOT (handle_delete_debugger_pointer_request (const QString&, int)));
- connect (this,
- SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)),
- editor_window,
- SLOT (handle_update_breakpoint_marker_request (bool,
- const QString&,
- int)));
- #endif
- octave_link::post_event (this, &main_window::resize_command_window_callback);
- install___init_qt___functions ();
- Fregister_graphics_toolkit (ovl ("qt"));
- configure_shortcuts ();
- }
- void
- main_window::handle_octave_ready ()
- {
- // actions after the startup files are executed
- QSettings *settings = resource_manager::get_settings ();
- QDir startup_dir = QDir (); // current octave dir after startup
- if (settings->value ("restore_octave_dir").toBool ())
- {
- // restore last dir from previous session
- QStringList curr_dirs
- = settings->value ("MainWindow/current_directory_list").toStringList ();
- startup_dir = QDir (curr_dirs.at (0)); // last dir in previous session
- }
- else if (! settings->value ("octave_startup_dir").toString ().isEmpty ())
- {
- // do not restore but there is a startup dir configured
- startup_dir = QDir (settings->value ("octave_startup_dir").toString ());
- }
- if (! startup_dir.exists ())
- {
- // the configured startup dir does not exist, take actual one
- startup_dir = QDir ();
- }
- set_current_working_directory (startup_dir.absolutePath ());
- #ifdef HAVE_QSCINTILLA
- // Octave ready, determine whether to create an empty script.
- // This can not be done when the editor is created because all functions
- // must be known for the lexer's auto completion informations
- editor_window->empty_script (true, false);
- #endif
- focus_command_window (); // make sure that the command window has focus
- }
- void
- main_window::construct_octave_qt_link (void)
- {
- _octave_qt_link = new octave_qt_link (this);
- connect (_octave_qt_link, SIGNAL (confirm_shutdown_signal ()),
- this, SLOT (confirm_shutdown_octave ()));
- connect (_octave_qt_link, SIGNAL (exit_app_signal (int)),
- this, SLOT (exit_app (int)));
- connect (_octave_qt_link,
- SIGNAL (set_workspace_signal
- (bool, const QString&, const QStringList&,
- const QStringList&, const QStringList&,
- const QStringList&, const QIntList&)),
- _workspace_model,
- SLOT (set_workspace
- (bool, const QString&, const QStringList&,
- const QStringList&, const QStringList&,
- const QStringList&, const QIntList&)));
- connect (_octave_qt_link, SIGNAL (clear_workspace_signal ()),
- _workspace_model, SLOT (clear_workspace ()));
- connect (_octave_qt_link, SIGNAL (change_directory_signal (QString)),
- this, SLOT (change_directory (QString)));
- connect (_octave_qt_link, SIGNAL (change_directory_signal (QString)),
- file_browser_window, SLOT (update_octave_directory (QString)));
- connect (_octave_qt_link, SIGNAL (change_directory_signal (QString)),
- editor_window, SLOT (update_octave_directory (QString)));
- connect (_octave_qt_link,
- SIGNAL (execute_command_in_terminal_signal (QString)),
- this, SLOT (execute_command_in_terminal (QString)));
- connect (_octave_qt_link,
- SIGNAL (set_history_signal (const QStringList&)),
- history_window, SLOT (set_history (const QStringList&)));
- connect (_octave_qt_link,
- SIGNAL (append_history_signal (const QString&)),
- history_window, SLOT (append_history (const QString&)));
- connect (_octave_qt_link,
- SIGNAL (clear_history_signal (void)),
- history_window, SLOT (clear_history (void)));
- connect (_octave_qt_link, SIGNAL (enter_debugger_signal ()),
- this, SLOT (handle_enter_debugger ()));
- connect (_octave_qt_link, SIGNAL (exit_debugger_signal ()),
- this, SLOT (handle_exit_debugger ()));
- connect (_octave_qt_link,
- SIGNAL (show_preferences_signal (void)),
- this, SLOT (process_settings_dialog_request ()));
- #ifdef HAVE_QSCINTILLA
- connect (_octave_qt_link,
- SIGNAL (edit_file_signal (const QString&)),
- editor_window,
- SLOT (handle_edit_file_request (const QString&)));
- #endif
- connect (_octave_qt_link,
- SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
- this,
- SLOT (handle_insert_debugger_pointer_request (const QString&, int)));
- connect (_octave_qt_link,
- SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
- this,
- SLOT (handle_delete_debugger_pointer_request (const QString&, int)));
- connect (_octave_qt_link,
- SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)),
- this,
- SLOT (handle_update_breakpoint_marker_request (bool, const QString&,
- int)));
- connect (_octave_qt_link,
- SIGNAL (show_doc_signal (const QString &)),
- this, SLOT (handle_show_doc (const QString &)));
- connect (_workspace_model,
- SIGNAL (rename_variable (const QString&, const QString&)),
- this,
- SLOT (handle_rename_variable_request (const QString&,
- const QString&)));
- connect (command_window, SIGNAL (interrupt_signal (void)),
- _octave_qt_link, SLOT (terminal_interrupt (void)));
- _octave_qt_link->execute_interpreter ();
- octave_link::connect_link (_octave_qt_link);
- }
- void
- main_window::construct_menu_bar (void)
- {
- QMenuBar *menu_bar = menuBar ();
- construct_file_menu (menu_bar);
- construct_edit_menu (menu_bar);
- construct_debug_menu (menu_bar);
- construct_window_menu (menu_bar);
- construct_help_menu (menu_bar);
- construct_news_menu (menu_bar);
- }
- QAction*
- main_window::add_action (QMenu *menu, const QIcon &icon, const QString &text,
- const char *member, const QWidget *receiver)
- {
- QAction *a;
- if (receiver)
- a = menu->addAction (icon, text, receiver, member);
- else
- a = menu->addAction (icon, text, this, member);
- addAction (a); // important for shortcut context
- a->setShortcutContext (Qt::ApplicationShortcut);
- return a;
- }
- void
- main_window::enable_menu_shortcuts (bool enable)
- {
- QHash<QMenu*, QStringList>::const_iterator i = _hash_menu_text.constBegin();
- while (i != _hash_menu_text.constEnd())
- {
- i.key ()->setTitle (i.value ().at (! enable));
- ++i;
- }
- }
- QMenu*
- main_window::m_add_menu (QMenuBar *p, QString name)
- {
- QMenu *menu = p->addMenu (name);
- QString base_name = name; // get a copy
- // replace intended '&' ("&&") by a temp. string
- base_name.replace ("&&","___octave_amp_replacement___");
- // remove single '&' (shortcut)
- base_name.remove ("&");
- // restore intended '&'
- base_name.replace ("___octave_amp_replacement___","&&");
- // remember names with and without shortcut
- _hash_menu_text[menu] = QStringList () << name << base_name;
- return menu;
- }
- void
- main_window::construct_file_menu (QMenuBar *p)
- {
- QMenu *file_menu = m_add_menu (p, tr ("&File"));
- construct_new_menu (file_menu);
- _open_action
- = file_menu->addAction (QIcon (":/actions/icons/folder_documents.png"),
- tr ("Open..."));
- _open_action->setShortcutContext (Qt::ApplicationShortcut);
- _open_action->setToolTip (tr ("Open an existing file in editor"));
- #ifdef HAVE_QSCINTILLA
- editor_window->insert_new_open_actions (_new_script_action,
- _new_function_action,
- _open_action);
- file_menu->addMenu (editor_window->get_mru_menu ());
- #endif
- file_menu->addSeparator ();
- _load_workspace_action
- = file_menu->addAction (tr ("Load Workspace..."));
- _save_workspace_action
- = file_menu->addAction (tr ("Save Workspace As..."));
- file_menu->addSeparator ();
- _preferences_action
- = file_menu->addAction (QIcon (":/actions/icons/configure.png"),
- tr ("Preferences..."));
- file_menu->addSeparator ();
- _exit_action = file_menu->addAction (tr ("Exit"));
- _exit_action->setShortcutContext (Qt::ApplicationShortcut);
- connect (_preferences_action, SIGNAL (triggered ()),
- this, SLOT (process_settings_dialog_request ()));
- #ifdef HAVE_QSCINTILLA
- connect (_open_action, SIGNAL (triggered ()),
- editor_window, SLOT (request_open_file ()));
- #endif
- connect (_load_workspace_action, SIGNAL (triggered ()),
- this, SLOT (handle_load_workspace_request ()));
- connect (_save_workspace_action, SIGNAL (triggered ()),
- this, SLOT (handle_save_workspace_request ()));
- connect (_exit_action, SIGNAL (triggered ()),
- this, SLOT (close ()));
- }
- void
- main_window::construct_new_menu (QMenu *p)
- {
- QMenu *new_menu = p->addMenu (tr ("New"));
- _new_script_action
- = new_menu->addAction (QIcon (":/actions/icons/filenew.png"),
- tr ("New Script"));
- _new_script_action->setShortcutContext (Qt::ApplicationShortcut);
- _new_function_action = new_menu->addAction (tr ("New Function..."));
- _new_function_action->setEnabled (true);
- _new_function_action->setShortcutContext (Qt::ApplicationShortcut);
- _new_figure_action = new_menu->addAction (tr ("New Figure"));
- _new_figure_action->setEnabled (true);
- #ifdef HAVE_QSCINTILLA
- connect (_new_script_action, SIGNAL (triggered ()),
- editor_window, SLOT (request_new_script ()));
- connect (_new_function_action, SIGNAL (triggered ()),
- editor_window, SLOT (request_new_function ()));
- #endif
- connect (_new_figure_action, SIGNAL (triggered ()),
- this, SLOT (handle_new_figure_request ()));
- }
- void
- main_w…
Large files files are truncated, but you can click here to view the full file