# HG changeset patch # User John W. Eaton # Date 1347937642 14400 # Node ID 7f423c6111c64ba34bfd6f5d05d2db53a14da216 # Parent 4d0ed64a6d1964972e23fbf568abeb2cfb7dfdde refactor GUI event handling to use new event_queue class * octave-link.h, octave-link.cc (event_queue): Delete. (gui_event_queue): New event_queue variable. Change all uses of event_queue to user gui_event_queue instead. (octave_link::handle_event): Delete. (octave_link::post_event, octave_link::do_post_event): Provide methods that work directly with member functions pointers and data. * octave-event.h, octave-event.cc, octave-event-observer.h: Delete. Delete all uses. * libgui/src/module.mk (noinst_HEADERS): Delete octave-event.h and octave-event-observer.h from the list. (src_libgui_src_la_SOURCES): Delete octave-event.cc from the list. * workspace-view.h, history-dockwidget.h, main-window.h: Don't include octave-link.h. * history-dockwidget.cc (history_dock_widget::handle_event): Delete. (history_dock_widget::handle_event): New function adapted from handle_event. (history_dock_widget::request_history_model_update): Update for new event callback mechanism. * history-dockwidget.h: Update decls. * file-editor-tab.cc (file_editor_tab::handle_event): Delete. (file_editor_tab::run_file_callback, file_editor_tab::add_breakpoint_callback, file_editor_tab::remove_breakpoint_callback, file_editor_tab::remove_all_breakpoints_callback): New functions adapted from handle_event and corresponding octave_event classes. (file_editor_tab::request_add_breakpoint, file_editor_tab::request_remove_breakpoint, file_editor_tab::remove_all_breakpoints, file_editor_tab::run_file): Update for new event callback mechanism. * file-editor-tab.h: Update decls. (file_editor_tab::bp_info): New nested struct. * main-window.cc (main_window::handle_event): Delete. (main_window::save_workspace_callback, main_window::load_workspace_callback, main_window::clear_workspace_callback, main_window::clear_history_callback, main_window::change_directory_callback, main_window::debug_continue_callback, main_window::debug_step_into_callback, main_window::debug_step_over_callback, main_window::debug_step_out_callback, main_window::debug_quit_callback, main_window::exit_callback): New functions. (main_window::handle_save_workspace_request, main_window::handle_load_workspace_request, main_window::handle_clear_workspace_request, main_window::handle_clear_history_request, main_window::change_current_working_directory, main_window::set_current_working_directory, main_window::debug_continue, main_window::debug_step_into, main_window::debug_step_over, main_window::debug_step_out, main_window::debug_quit): Update for new event callback mechanism. * main-window.h: Update decls. * workspace-model.cc (workspace_model::handle_event): Delete. (workspace_model::update_workspace_callback): New function. (workspace_model::request_update_workspace): Update for new event callback mechanism. * workspace-model.h: Update decls. diff --git a/libgui/src/history-dockwidget.cc b/libgui/src/history-dockwidget.cc --- a/libgui/src/history-dockwidget.cc +++ b/libgui/src/history-dockwidget.cc @@ -26,75 +26,21 @@ #include -#include "cmd-hist.h" - #include "error.h" +#include "cmd-hist.h" + #include "history-dockwidget.h" +#include "octave-link.h" history_dock_widget::history_dock_widget (QWidget * p) - : QDockWidget (p), octave_event_observer () + : QDockWidget (p) { setObjectName ("HistoryDockWidget"); construct (); } void -history_dock_widget::handle_event (octave_event *e, bool accept) -{ - static bool scroll_window = false; - - if (accept) - { - if (dynamic_cast (e)) - { - // Determine the client's (our) history length and the one of the server. - int clientHistoryLength = _history_model->rowCount (); - int serverHistoryLength = command_history::length (); - - // If were behind the server, iterate through all new entries and add - // them to our history. - if (clientHistoryLength < serverHistoryLength) - { - int elts_to_add = serverHistoryLength - clientHistoryLength; - - _history_model->insertRows (clientHistoryLength, elts_to_add); - - for (int i = clientHistoryLength; i < serverHistoryLength; i++) - { - std::string entry = command_history::get_entry (i); - - _history_model->setData (_history_model->index (i), - QString::fromStdString (entry)); - } - - // FIXME -- does this behavior make sense? Calling - // _history_list_view->scrollToBottom () here doesn't seem to - // have any effect. Instead, we need to request that action - // and wait until the next event occurs in which no items - // are added to the history list. - - scroll_window = true; - } - else if (scroll_window) - { - scroll_window = false; - - _history_list_view->scrollToBottom (); - } - } - - // Post a new update event in a given time. This prevents flooding the - // event queue. - _update_history_model_timer.start (); - } - else - { - // octave_event::perform failed to handle event. - } -} - -void history_dock_widget::construct () { _history_model = new QStringListModel (); @@ -161,7 +107,7 @@ void history_dock_widget::request_history_model_update () { - octave_link::post_event (new octave_update_history_event (*this)); + octave_link::post_event (this, &history_dock_widget::update_history_callback); } void @@ -176,3 +122,48 @@ emit active_changed (false); QDockWidget::closeEvent (e); } + +void +history_dock_widget::update_history_callback (void) +{ + static bool scroll_window = false; + + // Determine the client's (our) history length and the one of the server. + int clientHistoryLength = _history_model->rowCount (); + int serverHistoryLength = command_history::length (); + + // If were behind the server, iterate through all new entries and add + // them to our history. + if (clientHistoryLength < serverHistoryLength) + { + int elts_to_add = serverHistoryLength - clientHistoryLength; + + _history_model->insertRows (clientHistoryLength, elts_to_add); + + for (int i = clientHistoryLength; i < serverHistoryLength; i++) + { + std::string entry = command_history::get_entry (i); + + _history_model->setData (_history_model->index (i), + QString::fromStdString (entry)); + } + + // FIXME -- does this behavior make sense? Calling + // _history_list_view->scrollToBottom () here doesn't seem to + // have any effect. Instead, we need to request that action + // and wait until the next event occurs in which no items + // are added to the history list. + + scroll_window = true; + } + else if (scroll_window) + { + scroll_window = false; + + _history_list_view->scrollToBottom (); + } + + // Post a new update event in a given time. This prevents flooding the + // event queue. + _update_history_model_timer.start (); +} diff --git a/libgui/src/history-dockwidget.h b/libgui/src/history-dockwidget.h --- a/libgui/src/history-dockwidget.h +++ b/libgui/src/history-dockwidget.h @@ -30,17 +30,12 @@ #include #include -#include "octave-link.h" -#include "octave-event-observer.h" - -class history_dock_widget : public QDockWidget, public octave_event_observer +class history_dock_widget : public QDockWidget { Q_OBJECT public: history_dock_widget (QWidget *parent = 0); - void handle_event (octave_event *e, bool accept); - public slots: void handle_visibility_changed (bool visible); void request_history_model_update (); @@ -69,6 +64,8 @@ QStringListModel *_history_model; QTimer _update_history_model_timer; + + void update_history_callback (void); }; #endif // HISTORYDOCKWIDGET_H diff --git a/libgui/src/m-editor/file-editor-tab.cc b/libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc +++ b/libgui/src/m-editor/file-editor-tab.cc @@ -24,12 +24,6 @@ #include #endif -#include "file-editor-tab.h" -#include "file-editor.h" -#include "find-dialog.h" -#include "octave-link.h" - - #include // Not available in the Debian repos yet! // #include @@ -46,8 +40,16 @@ #include #include +#include "file-editor-tab.h" +#include "file-editor.h" +#include "find-dialog.h" +#include "octave-link.h" + +#include "debug.h" +#include "oct-env.h" + file_editor_tab::file_editor_tab(file_editor *fileEditor) - : QWidget ((QWidget*)fileEditor), octave_event_observer () + : QWidget ((QWidget*)fileEditor) { _file_editor = fileEditor; _file_name = ""; @@ -116,44 +118,6 @@ } void -file_editor_tab::handle_event (octave_event *e, bool accept) -{ - if (accept) - { - if (dynamic_cast (e)) - { - // File was run successfully. - } - - if (octave_add_breakpoint_event *abe - = dynamic_cast (e)) - { - // TODO: Check file. - _edit_area->markerAdd (abe->get_line (), breakpoint); - } - - if (octave_remove_breakpoint_event *rbe - = dynamic_cast (e)) - { - // TODO: Check file. - _edit_area->markerDelete (rbe->get_line (), breakpoint); - } - - if (dynamic_cast (e)) - { - _edit_area->markerDeleteAll (breakpoint); - } - } - else - { - if (dynamic_cast (e)) - { - // Running file failed. - } - } -} - -void file_editor_tab::closeEvent (QCloseEvent *e) { if (_file_editor->get_main_window ()->is_closing ()) @@ -307,9 +271,10 @@ // We have to cut off the suffix, because octave appends it. function_name.chop (file_info.suffix ().length () + 1); - octave_link::post_event (new octave_add_breakpoint_event - (*this, path.toStdString (), - function_name.toStdString (), line)); + bp_info info (path, function_name, line); + + octave_link::post_event + (this, &file_editor_tab::add_breakpoint_callback, info); } void @@ -322,9 +287,10 @@ // We have to cut off the suffix, because octave appends it. function_name.chop (file_info.suffix ().length () + 1); - octave_link::post_event (new octave_remove_breakpoint_event - (*this, path.toStdString (), - function_name.toStdString (), line)); + bp_info info (path, function_name, line); + + octave_link::post_event + (this, &file_editor_tab::remove_breakpoint_callback, info); } void @@ -492,9 +458,10 @@ // We have to cut off the suffix, because octave appends it. function_name.chop (file_info.suffix ().length () + 1); - octave_link::post_event (new octave_remove_all_breakpoints_event - (*this, path.toStdString (), - function_name.toStdString ())); + bp_info info (path, function_name, 0); + + octave_link::post_event + (this, &file_editor_tab::remove_all_breakpoints_callback, info); } void @@ -749,8 +716,8 @@ _file_editor->terminal ()->sendText (QString ("cd \'%1\'\n%2\n") .arg(path).arg (function_name)); // TODO: Sending a run event crashes for long scripts. Find out why. - // octave_link::post_event (new octave_run_file_event - // (*this, _file_name.toStdString ())); + // octave_link::post_event + // (this, &file_editor_tab::run_file_callback, _file_name.toStdString ())); } void @@ -839,3 +806,61 @@ update_window_title (false); } + +void +file_editor_tab::run_file_callback (void) +{ + // Maybe someday we will do something here? +} + +void +file_editor_tab::add_breakpoint_callback (const bp_info& info) +{ + bp_table::intmap intmap; + intmap[0] = info.line + 1; + + std::string previous_directory = octave_env::get_current_directory (); + octave_env::chdir (info.path); + intmap = bp_table::add_breakpoint (info.function_name, intmap); + octave_env::chdir (previous_directory); + + if (intmap.size () > 0) + { + // FIXME -- Check file. + _edit_area->markerAdd (info.line, breakpoint); + } +} + +void +file_editor_tab::remove_breakpoint_callback (const bp_info& info) +{ + bp_table::intmap intmap; + intmap[0] = info.line; + + std::string previous_directory = octave_env::get_current_directory (); + octave_env::chdir (info.path); + bp_table::remove_breakpoint (info.function_name, intmap); + octave_env::chdir (previous_directory); + + // FIXME -- check result + bool success = true; + + if (success) + { + // FIXME -- check file. + _edit_area->markerDelete (info.line, breakpoint); + } +} + +void +file_editor_tab::remove_all_breakpoints_callback (const bp_info& info) +{ + bp_table::intmap intmap; + std::string previous_directory = octave_env::get_current_directory (); + octave_env::chdir (info.path); + intmap = bp_table::remove_all_breakpoints_in_file (info.function_name, true); + octave_env::chdir (previous_directory); + + if (intmap.size() > 0) + _edit_area->markerDeleteAll (breakpoint); +} diff --git a/libgui/src/m-editor/file-editor-tab.h b/libgui/src/m-editor/file-editor-tab.h --- a/libgui/src/m-editor/file-editor-tab.h +++ b/libgui/src/m-editor/file-editor-tab.h @@ -27,18 +27,15 @@ #include #include #include -#include "octave-event-observer.h" class file_editor; -class file_editor_tab : public QWidget, public octave_event_observer +class file_editor_tab : public QWidget { Q_OBJECT public: file_editor_tab (file_editor *fileEditor); bool copy_available (); - void handle_event (octave_event *e, bool accept); - public slots: void update_window_title(bool modified); void handle_copy_available(bool enableCopy); @@ -87,6 +84,18 @@ void set_file_name (const QString& fileName); private: + + struct bp_info + { + bp_info (const QString& p, const QString& fn, int l) + : path (p.toStdString ()), function_name (fn.toStdString ()), line (l) + { } + + std::string path; + std::string function_name; + int line; + }; + void update_lexer (); void request_add_breakpoint (int line); void request_remove_breakpoint (int line); @@ -95,6 +104,11 @@ int check_file_modified (const QString& msg, int cancelButton); void do_comment_selected_text (bool comment); + void run_file_callback (void); + void add_breakpoint_callback (const bp_info& info); + void remove_breakpoint_callback (const bp_info& info); + void remove_all_breakpoints_callback (const bp_info& info); + file_editor * _file_editor; QsciScintilla * _edit_area; diff --git a/libgui/src/main-window.cc b/libgui/src/main-window.cc --- a/libgui/src/main-window.cc +++ b/libgui/src/main-window.cc @@ -37,12 +37,21 @@ #include #include +#include "file-editor.h" #include "main-window.h" -#include "file-editor.h" +#include "octave-link.h" #include "settings-dialog.h" +#include "debug.h" +#include "load-save.h" +#include "toplev.h" +#include "variables.h" + +#include "cmd-hist.h" +#include "oct-env.h" + main_window::main_window (QWidget *p) - : QMainWindow (p), octave_event_observer () + : QMainWindow (p) { // We have to set up all our windows, before we finally launch octave. construct (); @@ -54,23 +63,6 @@ } void -main_window::handle_event (octave_event *e, bool accept) -{ - if (accept) - { - if (dynamic_cast (e)) - { - // After clearing the history, we need to reset the model. - _history_dock_widget->reset_model (); - } - } - else - { - // octave_event::perform failed to process event. - } -} - -void main_window::new_file () { _file_editor->request_new_file (); @@ -104,10 +96,8 @@ QFileDialog::getSaveFileName (this, tr ("Save Workspace"), resource_manager::get_home_path ()); if (!selectedFile.isEmpty ()) - { - octave_link::post_event (new octave_save_workspace_event - (*this, selectedFile.toStdString ())); - } + octave_link::post_event (this, &main_window::save_workspace_callback, + selectedFile.toStdString ()); } void @@ -117,22 +107,20 @@ QFileDialog::getOpenFileName (this, tr ("Load Workspace"), resource_manager::get_home_path ()); if (!selectedFile.isEmpty ()) - { - octave_link::post_event (new octave_load_workspace_event - (*this, selectedFile.toStdString ())); - } + octave_link::post_event (this, &main_window::load_workspace_callback, + selectedFile.toStdString ()); } void main_window::handle_clear_workspace_request () { - octave_link::post_event (new octave_clear_workspace_event (*this)); + octave_link::post_event (this, &main_window::clear_workspace_callback); } void main_window::handle_clear_history_request() { - octave_link::post_event (new octave_clear_history_event (*this)); + octave_link::post_event (this, &main_window::clear_history_callback); } void @@ -232,17 +220,15 @@ QFileDialog::getExistingDirectory(this, tr ("Set working direcotry")); if (!selectedDirectory.isEmpty ()) - { - octave_link::post_event (new octave_change_directory_event - (*this, selectedDirectory.toStdString ())); - } + octave_link::post_event (this, &main_window::change_directory_callback, + selectedDirectory.toStdString ()); } void main_window::set_current_working_directory (const QString& directory) { - octave_link::post_event (new octave_change_directory_event - (*this, directory.toStdString ())); + octave_link::post_event (this, &main_window::change_directory_callback, + directory.toStdString ()); } void @@ -360,31 +346,31 @@ void main_window::debug_continue () { - octave_link::post_event (new octave_debug_continue_event (*this)); + octave_link::post_event (this, &main_window::debug_continue_callback); } void main_window::debug_step_into () { - octave_link::post_event (new octave_debug_step_into_event (*this)); + octave_link::post_event (this, &main_window::debug_step_into_callback); } void main_window::debug_step_over () { - octave_link::post_event (new octave_debug_step_over_event (*this)); + octave_link::post_event (this, &main_window::debug_step_over_callback); } void main_window::debug_step_out () { - octave_link::post_event (new octave_debug_step_out_event (*this)); + octave_link::post_event (this, &main_window::debug_step_out_callback); } void main_window::debug_quit () { - octave_link::post_event (new octave_debug_quit_event (*this)); + octave_link::post_event (this, &main_window::debug_quit_callback); } void @@ -414,7 +400,7 @@ main_window::closeEvent (QCloseEvent *e) { e->ignore (); - octave_link::post_event (new octave_exit_event (*this)); + octave_link::post_event (this, &main_window::exit_callback); } void @@ -895,3 +881,70 @@ SLOT (handle_quit_debug_mode ())); } +void +main_window::save_workspace_callback (const std::string& file) +{ + save_workspace (file); +} + +void +main_window::load_workspace_callback (const std::string& file) +{ + load_workspace (file); +} + +void +main_window::clear_workspace_callback (void) +{ + clear_current_scope (); +} + +void +main_window::clear_history_callback (void) +{ + command_history::clear (); + + _history_dock_widget->reset_model (); +} + +void +main_window::change_directory_callback (const std::string& directory) +{ + octave_env::chdir (directory); +} + +void +main_window::debug_continue_callback (void) +{ + debug_continue (); +} + +void +main_window::debug_step_into_callback (void) +{ + debug_step ("in"); +} + +void +main_window::debug_step_over_callback (void) +{ + debug_step (); +} + +void +main_window::debug_step_out_callback (void) +{ + debug_step ("out"); +} + +void +main_window::debug_quit_callback (void) +{ + debug_quit (); +} + +void +main_window::exit_callback (void) +{ + clean_up_and_exit (0); +} diff --git a/libgui/src/main-window.h b/libgui/src/main-window.h --- a/libgui/src/main-window.h +++ b/libgui/src/main-window.h @@ -44,29 +44,24 @@ // Own includes #include "resource-manager.h" -#include "octave-link.h" #include "workspace-view.h" #include "history-dockwidget.h" #include "files-dockwidget.h" #include "terminal-dockwidget.h" #include "documentation-dockwidget.h" #include "octave-qt-event-listener.h" -#include "octave-event-observer.h" /** * \class MainWindow * * Represents the main window. */ -class main_window - : public QMainWindow, public octave_event_observer +class main_window : public QMainWindow { Q_OBJECT public: main_window (QWidget * parent = 0); ~main_window (); - void handle_event (octave_event *e, bool accept); - QTerminal *get_terminal_view () { return _terminal; } history_dock_widget *get_history_dock_widget () { @@ -128,6 +123,28 @@ void construct (); void establish_octave_link (); + void save_workspace_callback (const std::string& file); + + void load_workspace_callback (const std::string& file); + + void clear_workspace_callback (void); + + void clear_history_callback (void); + + void change_directory_callback (const std::string& directory); + + void debug_continue_callback (void); + + void debug_step_into_callback (void); + + void debug_step_over_callback (void); + + void debug_step_out_callback (void); + + void debug_quit_callback (void); + + void exit_callback (void); + QTerminal * _terminal; file_editor_interface * _file_editor; QMenu * _debug_menu; diff --git a/libgui/src/module.mk b/libgui/src/module.mk --- a/libgui/src/module.mk +++ b/libgui/src/module.mk @@ -84,8 +84,6 @@ src/m-editor/lexer-octave-gui.h \ src/main-window.h \ src/octave-adapter/octave-event-listener.h \ - src/octave-adapter/octave-event-observer.h \ - src/octave-adapter/octave-event.h \ src/octave-adapter/octave-link.h \ src/octave-adapter/octave-main-thread.h \ src/octave-gui.h \ @@ -109,7 +107,6 @@ src/m-editor/find-dialog.cc \ src/m-editor/lexer-octave-gui.cc \ src/main-window.cc \ - src/octave-adapter/octave-event.cc \ src/octave-adapter/octave-link.cc \ src/octave-adapter/octave-main-thread.cc \ src/octave-gui.cc \ diff --git a/libgui/src/octave-adapter/octave-event-observer.h b/libgui/src/octave-adapter/octave-event-observer.h deleted file mode 100644 --- a/libgui/src/octave-adapter/octave-event-observer.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - -Copyright (C) 2011-2012 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 -. - -*/ - -#ifndef OCTAVEEVENTOBSERVER_H -#define OCTAVEEVENTOBSERVER_H - -class octave_event; - -/** - * \class octave_event_observer - * \brief Implements the observer part for the observer pattern. - */ -class octave_event_observer -{ - public: - octave_event_observer () { } - virtual ~octave_event_observer () { } - - /** - * This will be called after the octave_event::perform function - * has processed an event. ACCEPT will be true if the event was - * successfully handled and false otherwise. - */ - virtual void handle_event (octave_event *e, bool accept) = 0; -}; - -#include "octave-event.h" - -#endif // OCTAVEEVENTOBSERVER_H diff --git a/libgui/src/octave-adapter/octave-event.cc b/libgui/src/octave-adapter/octave-event.cc deleted file mode 100644 --- a/libgui/src/octave-adapter/octave-event.cc +++ /dev/null @@ -1,176 +0,0 @@ -/* - -Copyright (C) 2011-2012 Jacob Dawid -Copyright (C) 2011-2012 John P. Swensen - -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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include - -#include "cmd-hist.h" -#include "oct-env.h" - -#include "debug.h" -#include "oct-obj.h" -#include "parse.h" -#include "symtab.h" -#include "toplev.h" - -#include "octave-event.h" - -#include - -void -octave_event::call_octave_function (const std::string& name) -{ - call_octave_function (name, octave_value_list ()); -} - -void -octave_event::call_octave_function (const std::string& name, - const octave_value_list& args, - int nargout) -{ - try - { - feval (name, args, nargout); - } catch (...) { } // Ignore exceptions. Crashes without that. -} - -void -octave_event::finish_readline_event () const -{ - rl_line_buffer[0] = '\0'; - rl_point = rl_end = 0; - rl_done = 1; - //rl_forced_update_display (); -} - -bool -octave_clear_history_event::perform () -{ - int i; - while ((i = command_history::length ()) > 0) { - command_history::remove (i - 1); - } - return true; -} - -bool -octave_debug_step_into_event::perform () -{ - octave_value_list args; - args.append (octave_value ("in")); - call_octave_function ("dbstep", args); - finish_readline_event (); - return true; -} - -bool -octave_debug_step_out_event::perform () -{ - octave_value_list args; - args.append (octave_value ("out")); - call_octave_function ("dbstep", args); - finish_readline_event (); - return true; -} - - -bool -octave_exit_event::perform () -{ - clean_up_and_exit (0); - return true; -} - -bool -octave_run_file_event::perform () -{ - octave_value_list args; - args.append (octave_value (_file)); - call_octave_function ("run", args); - finish_readline_event (); - return true; -} - -bool -octave_change_directory_event::perform () -{ - return octave_env::chdir (_directory); -} - -bool -octave_load_workspace_event::perform () -{ - octave_value_list args; - args.append (octave_value (_file)); - call_octave_function ("load", args); - return true; -} - -bool -octave_save_workspace_event::perform () -{ - octave_value_list args; - args.append (octave_value (_file)); - call_octave_function ("save", args); - return true; -} - -bool -octave_add_breakpoint_event::perform () -{ - bp_table::intmap intmap; - intmap[0] = _line + 1; - - std::string previous_directory = octave_env::get_current_directory (); - octave_env::chdir (_path); - intmap = bp_table::add_breakpoint (_function_name, intmap); - octave_env::chdir (previous_directory); - return intmap.size () > 0; -} - -bool -octave_remove_breakpoint_event::perform () -{ - bp_table::intmap intmap; - intmap[0] = _line; - - std::string previous_directory = octave_env::get_current_directory (); - octave_env::chdir (_path); - bp_table::remove_breakpoint (_function_name, intmap); - octave_env::chdir (previous_directory); - return true; // TODO: Check result. -} - -bool -octave_remove_all_breakpoints_event::perform () -{ - bp_table::intmap intmap; - std::string previous_directory = octave_env::get_current_directory (); - octave_env::chdir (_path); - intmap = bp_table::remove_all_breakpoints_in_file (_function_name, true); - octave_env::chdir (previous_directory); - return intmap.size() > 0; -} diff --git a/libgui/src/octave-adapter/octave-event.h b/libgui/src/octave-adapter/octave-event.h deleted file mode 100644 --- a/libgui/src/octave-adapter/octave-event.h +++ /dev/null @@ -1,379 +0,0 @@ -/* - -Copyright (C) 2011-2012 Jacob Dawid -Copyright (C) 2011-2012 John P. Swensen - -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 -. - -*/ - -#ifndef OCTAVEEVENT_H -#define OCTAVEEVENT_H - -#include - -class octave_value_list; - -#include "octave-event-observer.h" - -/** - * \class octave_event - * \brief Base class for an octave event. - * In order to make communication with octave threadsafe, comunication is - * implemented via events. An application may create events and post them, - * however there is no guarantee events will be processed in a given time. - * - * In order to create an event, there must be an event observer. The event - * observer will be given the opportunity to react on the event as soon as - * it has been processed in the octave thread. Accepting and ignoring takes - * places in the octave thread. - */ -class octave_event -{ - public: - octave_event (octave_event_observer& o) - : _octave_event_observer (o) - { } - - virtual ~octave_event () - { } - - /** Performs what is necessary to make this event happen. This - * code is thread-safe since it will be executed in the octave - * thread. However, you should take care to keep this code as - * short as possible. */ - virtual bool perform () = 0; - - /** - * Pass the event on to the class that posted the event. ACCEPT - * will be true if the perform function was successful, and false - * otherwise. - */ - void handle_event (bool accept) - { - _octave_event_observer.handle_event (this, accept); - } - - protected: - void call_octave_function (const std::string& name); - - void call_octave_function (const std::string& name, - const octave_value_list& args, - int nargout = 0); - - void finish_readline_event () const; - - private: - octave_event_observer& _octave_event_observer; -}; - -class octave_update_history_event : public octave_event -{ - public: - /** Creates a new octave_exit_event. */ - octave_update_history_event (octave_event_observer& o) - : octave_event (o) - { } - - bool perform () - { return true; /* Always grant. */ } -}; - -class octave_update_workspace_event : public octave_event -{ - public: - /** Creates a new octave_exit_event. */ - octave_update_workspace_event (octave_event_observer& o) - : octave_event (o) - { } - - bool perform () - { return true; /* Always grant. */ } -}; - -/** Implements an octave exit event. */ -class octave_exit_event : public octave_event -{ - public: - /** Creates a new octave_exit_event. */ - octave_exit_event (octave_event_observer& o) - : octave_event (o) - { } - - bool perform (); -}; - -/** Implements an octave run file event. */ -class octave_run_file_event : public octave_event -{ - public: - /** Creates a new octave_run_file_event. */ - octave_run_file_event (octave_event_observer& o, - const std::string& file) - : octave_event (o) - { _file = file; } - - bool perform (); - - private: - std::string _file; -}; - -/** Implements a change directory event. */ -class octave_change_directory_event : public octave_event -{ - public: - /** Creates a new octave_change_directory_event. */ - octave_change_directory_event (octave_event_observer& o, - const std::string& directory) - : octave_event (o) - { _directory = directory; } - - bool perform (); - - private: - std::string _directory; -}; - -/** Implements a clear workspace event. */ -class octave_clear_workspace_event : public octave_event -{ - public: - /** Creates a new octave_run_file_event. */ - octave_clear_workspace_event (octave_event_observer& o) - : octave_event (o) - { } - - bool perform () - { - call_octave_function ("clear"); - return true; - } -}; - -/** Implements a load workspace event. */ -class octave_load_workspace_event : public octave_event -{ - public: - /** Creates a new octave_change_directory_event. */ - octave_load_workspace_event (octave_event_observer& o, - const std::string& file) - : octave_event (o) - { _file = file; } - - bool perform (); - - private: - std::string _file; -}; - -/** Implements a save workspace event. */ -class octave_save_workspace_event : public octave_event -{ - public: - /** Creates a new octave_change_directory_event. */ - octave_save_workspace_event (octave_event_observer& o, - const std::string& file) - : octave_event (o) - { _file = file; } - - bool perform (); - - private: - std::string _file; -}; - -class octave_clear_history_event : public octave_event -{ - public: - /** Creates a new octave_clear_history_event. */ - octave_clear_history_event (octave_event_observer& o) - : octave_event (o) - { } - - bool perform (); -}; - -class octave_add_breakpoint_event : public octave_event -{ - public: - octave_add_breakpoint_event (octave_event_observer& o, - const std::string& path, - const std::string& function_name, - int line) - : octave_event (o) - { - _path = path; - _function_name = function_name; - _line = line; - } - - bool perform (); - - std::string get_path () - { - return _path; - } - - std::string get_function_name () - { - return _function_name; - } - - int get_line () - { - return _line; - } - - private: - std::string _path; - std::string _function_name; - int _line; -}; - -class octave_remove_breakpoint_event : public octave_event -{ - public: - octave_remove_breakpoint_event (octave_event_observer& o, - const std::string& path, - const std::string& function_name, - int line) - : octave_event (o) - { - _path = path; - _function_name = function_name; - _line = line; - } - - bool perform (); - - std::string get_path () - { - return _path; - } - - std::string get_function_name () - { - return _function_name; - } - - int get_line () - { - return _line; - } - - private: - std::string _path; - std::string _function_name; - int _line; -}; - -class octave_remove_all_breakpoints_event : public octave_event -{ - public: - octave_remove_all_breakpoints_event (octave_event_observer& o, - const std::string& path, - const std::string& function_name) - : octave_event (o) - { - _path = path; - _function_name = function_name; - } - - bool perform (); - - std::string get_path () - { - return _path; - } - - std::string get_function_name () - { - return _function_name; - } - - private: - std::string _path; - std::string _function_name; -}; - -class octave_debug_step_into_event : public octave_event -{ - public: - /** Creates a new octave_debug_step_into_event. */ - octave_debug_step_into_event (octave_event_observer& o) - : octave_event (o) { } - - bool perform (); -}; - -class octave_debug_step_over_event : public octave_event -{ - public: - /** Creates a new octave_debug_step_over_event. */ - octave_debug_step_over_event (octave_event_observer& o) - : octave_event (o) { } - - bool perform () - { - call_octave_function ("dbnext"); - finish_readline_event (); - return true; - } -}; - -class octave_debug_step_out_event : public octave_event -{ - public: - /** Creates a new octave_debug_step_out_event. */ - octave_debug_step_out_event (octave_event_observer& o) - : octave_event (o) { } - - bool perform (); -}; - -class octave_debug_continue_event : public octave_event -{ - public: - /** Creates a new octave_debug_step_out_event. */ - octave_debug_continue_event (octave_event_observer& o) - : octave_event (o) { } - - bool perform () - { - call_octave_function ("dbcont"); - finish_readline_event (); - return true; - } -}; - -class octave_debug_quit_event : public octave_event -{ - public: - /** Creates a new octave_debug_step_out_event. */ - octave_debug_quit_event (octave_event_observer& o) - : octave_event (o) { } - - bool perform () - { - call_octave_function ("dbquit"); - finish_readline_event (); - return true; - } -}; - -#endif // OCTAVEEVENT_H diff --git a/libgui/src/octave-adapter/octave-link.cc b/libgui/src/octave-adapter/octave-link.cc --- a/libgui/src/octave-adapter/octave-link.cc +++ b/libgui/src/octave-adapter/octave-link.cc @@ -55,7 +55,7 @@ octave_link::octave_link (void) : event_listener (0), event_queue_mutex (new octave_mutex ()), - event_queue (), last_cwd (), debugging (false) + gui_event_queue (), last_cwd (), debugging (false) { } void @@ -110,40 +110,17 @@ { event_queue_mutex->lock (); - while (event_queue.size () > 0) - { - octave_event *e = event_queue.front (); - - event_queue.pop (); - - bool status = e->perform (); - - e->handle_event (status); - - delete e; - } + gui_event_queue.run (); event_queue_mutex->unlock (); } void -octave_link::do_post_event (octave_event *e) -{ - if (e) - { - event_queue_mutex->lock (); - event_queue.push (e); - event_queue_mutex->unlock (); - } -} - -void octave_link::do_about_to_exit (void) { event_queue_mutex->lock (); - while (! event_queue.empty ()) - event_queue.pop (); + gui_event_queue.discard (); event_queue_mutex->unlock (); @@ -157,11 +134,6 @@ return last_cwd; } -void -octave_link::handle_event (octave_event *, bool) -{ -} - bool octave_link::instance_ok (void) { diff --git a/libgui/src/octave-adapter/octave-link.h b/libgui/src/octave-adapter/octave-link.h --- a/libgui/src/octave-adapter/octave-link.h +++ b/libgui/src/octave-adapter/octave-link.h @@ -24,14 +24,13 @@ #ifndef OCTAVELINK_H #define OCTAVELINK_H -#include #include class octave_mutex; +#include "event-queue.h" + #include "octave-main-thread.h" -#include "octave-event.h" -#include "octave-event-observer.h" #include "octave-event-listener.h" // \class OctaveLink @@ -42,7 +41,7 @@ // buffering access operations to octave and executing them in the // readline event hook, which lives in the octave thread. -class octave_link : public octave_event_observer +class octave_link { protected: @@ -76,10 +75,25 @@ instance->do_process_events (); } - static void post_event (octave_event *e) + template + static void post_event (T *obj, void (T::*method) (void)) { if (instance_ok ()) - instance->do_post_event (e); + instance->do_post_event (obj, method); + } + + template + static void post_event (T *obj, void (T::*method) (A), A arg) + { + if (instance_ok ()) + instance->do_post_event (obj, method, arg); + } + + template + static void post_event (T *obj, void (T::*method) (const A&), const A& arg) + { + if (instance_ok ()) + instance->do_post_event (obj, method, arg); } static void about_to_exit (void) @@ -128,8 +142,8 @@ // Semaphore to lock access to the event queue. octave_mutex *event_queue_mutex; - // Buffer for queueing events until they will be processed. - std::queue event_queue; + // Event Queue. + event_queue gui_event_queue; // Stores the last known current working directory of octave. std::string last_cwd; @@ -141,7 +155,24 @@ void do_generate_events (void); void do_process_events (void); - void do_post_event (octave_event *e); + + template + void do_post_event (T *obj, void (T::*method) (void)) + { + gui_event_queue.add_method (obj, method); + } + + template + void do_post_event (T *obj, void (T::*method) (A), A arg) + { + gui_event_queue.add_method (obj, method, arg); + } + + template + void do_post_event (T *obj, void (T::*method) (const A&), const A& arg) + { + gui_event_queue.add_method (obj, method, arg); + } void do_about_to_exit (void); @@ -149,8 +180,6 @@ void do_finished_readline_hook (void) { } std::string do_last_working_directory (void); - - void handle_event (octave_event *e, bool accept); }; #endif // OCTAVELINK_H diff --git a/libgui/src/workspace-model.cc b/libgui/src/workspace-model.cc --- a/libgui/src/workspace-model.cc +++ b/libgui/src/workspace-model.cc @@ -29,13 +29,14 @@ #include -#include +#include "symtab.h" +#include "variables.h" #include "workspace-model.h" #include "octave-link.h" workspace_model::workspace_model(QObject *p) - : QAbstractItemModel (p), octave_event_observer () + : QAbstractItemModel (p) { QList rootData; rootData << tr ("Name") << tr ("Class") << tr("Dimension") << tr ("Value"); @@ -63,68 +64,7 @@ void workspace_model::request_update_workspace () { - octave_link::post_event (new octave_update_workspace_event (*this)); -} - -void -workspace_model::handle_event (octave_event *e, bool accept) -{ - if (accept) - { - if (dynamic_cast (e)) - { - std::list < symbol_table::symbol_record > symbolTable = symbol_table::all_variables (); - - _symbol_information.clear (); - for (std::list < symbol_table::symbol_record > ::iterator iterator = symbolTable.begin (); - iterator != symbolTable.end (); iterator++) - _symbol_information.push_back (symbol_information (*iterator)); - - beginResetModel(); - top_level_item (0)->delete_child_items (); - top_level_item (1)->delete_child_items (); - top_level_item (2)->delete_child_items (); - - foreach (const symbol_information& s, _symbol_information) - { - tree_item *child = new tree_item (); - - child->set_data (0, s.symbol ()); - child->set_data (1, s.class_name ()); - child->set_data (2, s.dimension ()); - child->set_data (3, s.value ()); - - switch (s.scope ()) - { - case symbol_information::local: - top_level_item (0)->add_child (child); - break; - - case symbol_information::global: - top_level_item (1)->add_child (child); - break; - - case symbol_information::persistent: - top_level_item (2)->add_child (child); - break; - - default: - break; - } - } - - endResetModel(); - emit model_changed(); - } - - // Post a new event in a given time. - // This prevents flooding the event queue when no events are being processed. - _update_workspace_model_timer.start (); - } - else - { - // octave_event::perform failed to process event. - } + octave_link::post_event (this, &workspace_model::update_workspace_callback); } QModelIndex @@ -236,3 +176,54 @@ return item->data(idx.column()); } +void +workspace_model::update_workspace_callback (void) +{ + std::list < symbol_table::symbol_record > symbolTable = symbol_table::all_variables (); + + _symbol_information.clear (); + for (std::list < symbol_table::symbol_record > ::iterator iterator = symbolTable.begin (); + iterator != symbolTable.end (); iterator++) + _symbol_information.push_back (symbol_information (*iterator)); + + beginResetModel(); + top_level_item (0)->delete_child_items (); + top_level_item (1)->delete_child_items (); + top_level_item (2)->delete_child_items (); + + foreach (const symbol_information& s, _symbol_information) + { + tree_item *child = new tree_item (); + + child->set_data (0, s.symbol ()); + child->set_data (1, s.class_name ()); + child->set_data (2, s.dimension ()); + child->set_data (3, s.value ()); + + switch (s.scope ()) + { + case symbol_information::local: + top_level_item (0)->add_child (child); + break; + + case symbol_information::global: + top_level_item (1)->add_child (child); + break; + + case symbol_information::persistent: + top_level_item (2)->add_child (child); + break; + + default: + break; + } + } + + endResetModel(); + emit model_changed(); + + // Post a new event in a given time. + // This prevents flooding the event queue when no events are being processed. + _update_workspace_model_timer.start (); +} + diff --git a/libgui/src/workspace-model.h b/libgui/src/workspace-model.h --- a/libgui/src/workspace-model.h +++ b/libgui/src/workspace-model.h @@ -30,7 +30,6 @@ #include #include "symbol-information.h" -#include "octave-event-observer.h" class tree_item { @@ -112,7 +111,7 @@ }; class workspace_model - : public QAbstractItemModel, public octave_event_observer + : public QAbstractItemModel { Q_OBJECT @@ -120,8 +119,6 @@ workspace_model (QObject *parent = 0); ~workspace_model (); - void handle_event (octave_event *e, bool accept); - QVariant data (const QModelIndex &index, int role) const; Qt::ItemFlags flags (const QModelIndex &index) const; QVariant headerData (int section, Qt::Orientation orientation, @@ -142,6 +139,9 @@ void model_changed (); private: + + void update_workspace_callback (void); + /** Timer for periodically updating the workspace model from the current * symbol information. */ QTimer _update_workspace_model_timer; diff --git a/libgui/src/workspace-view.h b/libgui/src/workspace-view.h --- a/libgui/src/workspace-view.h +++ b/libgui/src/workspace-view.h @@ -26,7 +26,7 @@ #include #include #include -#include "octave-link.h" + #include "workspace-model.h" class workspace_view : public QDockWidget