changeset 15403:7f423c6111c6

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.
author John W. Eaton <jwe@octave.org>
date Mon, 17 Sep 2012 23:07:22 -0400
parents 4d0ed64a6d19
children 7b69cd89868c
files libgui/src/history-dockwidget.cc libgui/src/history-dockwidget.h libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor-tab.h libgui/src/main-window.cc libgui/src/main-window.h libgui/src/module.mk libgui/src/octave-adapter/octave-event-observer.h libgui/src/octave-adapter/octave-event.cc libgui/src/octave-adapter/octave-event.h libgui/src/octave-adapter/octave-link.cc libgui/src/octave-adapter/octave-link.h libgui/src/workspace-model.cc libgui/src/workspace-model.h libgui/src/workspace-view.h
diffstat 15 files changed, 372 insertions(+), 889 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/history-dockwidget.cc
+++ b/libgui/src/history-dockwidget.cc
@@ -26,75 +26,21 @@
 
 #include <QVBoxLayout>
 
-#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 <octave_update_history_event*> (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 ();
+}
--- a/libgui/src/history-dockwidget.h
+++ b/libgui/src/history-dockwidget.h
@@ -30,17 +30,12 @@
 #include <QStringListModel>
 #include <QTimer>
 
-#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
--- a/libgui/src/m-editor/file-editor-tab.cc
+++ b/libgui/src/m-editor/file-editor-tab.cc
@@ -24,12 +24,6 @@
 #include <config.h>
 #endif
 
-#include "file-editor-tab.h"
-#include "file-editor.h"
-#include "find-dialog.h"
-#include "octave-link.h"
-
-
 #include <Qsci/qsciapis.h>
 // Not available in the Debian repos yet!
 // #include <Qsci/qscilexeroctave.h>
@@ -46,8 +40,16 @@
 #include <QTextStream>
 #include <QVBoxLayout>
 
+#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<octave_run_file_event*> (e))
-        {
-          // File was run successfully.
-        }
-
-      if (octave_add_breakpoint_event *abe
-          = dynamic_cast<octave_add_breakpoint_event*> (e))
-        {
-          // TODO: Check file.
-          _edit_area->markerAdd (abe->get_line (), breakpoint);
-        }
-
-      if (octave_remove_breakpoint_event *rbe
-          = dynamic_cast<octave_remove_breakpoint_event*> (e))
-        {
-          // TODO: Check file.
-          _edit_area->markerDelete (rbe->get_line (), breakpoint);
-        }
-
-      if (dynamic_cast<octave_remove_all_breakpoints_event*> (e))
-        {
-          _edit_area->markerDeleteAll (breakpoint);
-        }
-    }
-  else
-    {
-      if (dynamic_cast<octave_run_file_event*> (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);
+}
--- a/libgui/src/m-editor/file-editor-tab.h
+++ b/libgui/src/m-editor/file-editor-tab.h
@@ -27,18 +27,15 @@
 #include <QWidget>
 #include <QCloseEvent>
 #include <QFileSystemWatcher>
-#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;
 
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -37,12 +37,21 @@
 #include <QMessageBox>
 #include <QIcon>
 
+#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<octave_clear_history_event*> (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);
+}
--- 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;
--- 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 \
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
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#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
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
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string>
-
-#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 <readline/readline.h>
-
-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;
-}
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
-<http://www.gnu.org/licenses/>.
-
-*/
-
-#ifndef OCTAVEEVENT_H
-#define OCTAVEEVENT_H
-
-#include <string>
-
-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
--- 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)
 {
--- 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 <queue>
 #include <string>
 
 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 <class T>
+  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 <class T, class A>
+  static void post_event (T *obj, void (T::*method) (A), A arg)
+  {
+    if (instance_ok ())
+      instance->do_post_event (obj, method, arg);
+  }
+
+  template <class T, class A>
+  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 <octave_event *> 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 <class T>
+  void do_post_event (T *obj, void (T::*method) (void))
+  {
+    gui_event_queue.add_method (obj, method);
+  }
+
+  template <class T, class A>
+  void do_post_event (T *obj, void (T::*method) (A), A arg)
+  {
+    gui_event_queue.add_method (obj, method, arg);
+  }
+
+  template <class T, class A>
+  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
--- a/libgui/src/workspace-model.cc
+++ b/libgui/src/workspace-model.cc
@@ -29,13 +29,14 @@
 
 #include <list>
 
-#include <symtab.h>
+#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<QVariant> 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 <octave_update_workspace_event*> (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 ();
+}
+
--- a/libgui/src/workspace-model.h
+++ b/libgui/src/workspace-model.h
@@ -30,7 +30,6 @@
 #include <QTimer>
 
 #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;
--- a/libgui/src/workspace-view.h
+++ b/libgui/src/workspace-view.h
@@ -26,7 +26,7 @@
 #include <QDockWidget>
 #include <QTreeView>
 #include <QSemaphore>
-#include "octave-link.h"
+
 #include "workspace-model.h"
 
 class workspace_view : public QDockWidget