changeset 14720:cecc7da96e2a gui

Added update events for the command history model and workspace model. * history-dockwidget.cc: Moved string list model to dock widget. * octave-event-observer.h: Removed constness from accepted and rejected methods. * octave-event.h: Removed constness from accepted and rejected methods, add new event types. * octave-link: Almost removed all Qt code. * workspace-model: Moved update timer to model. * workspace-view: Model workspace model to widget.
author Jacob Dawid <jacob.dawid@googlemail.com>
date Mon, 04 Jun 2012 21:28:08 +0200
parents 89c64340e9ab
children ec76264adca9
files gui/src/history-dockwidget.cc gui/src/history-dockwidget.h gui/src/octave-adapter/octave-event-observer.h gui/src/octave-adapter/octave-event.h gui/src/octave-adapter/octave-link.cc gui/src/octave-adapter/octave-link.h gui/src/workspace-model.cc gui/src/workspace-model.h gui/src/workspace-view.cc gui/src/workspace-view.h
diffstat 10 files changed, 218 insertions(+), 203 deletions(-) [+]
line wrap: on
line diff
--- a/gui/src/history-dockwidget.cc	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/history-dockwidget.cc	Mon Jun 04 21:28:08 2012 +0200
@@ -18,37 +18,91 @@
 #include "history-dockwidget.h"
 #include <QVBoxLayout>
 
-history_dock_widget::history_dock_widget (QWidget * parent):QDockWidget (parent)
+history_dock_widget::history_dock_widget (QWidget * parent)
+  : QDockWidget (parent), octave_event_observer ()
 {
   setObjectName ("HistoryDockWidget");
   construct ();
 }
 
 void
+history_dock_widget::event_accepted (octave_event *e)
+{
+  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)
+        {
+          for (int i = clientHistoryLength; i < serverHistoryLength; i++)
+            {
+              _history_model->insertRow (0);
+              _history_model->setData (_history_model->index (0),
+                QString (command_history::get_entry (i).c_str ()));
+            }
+        }
+    }
+
+  delete e;
+}
+
+void
+history_dock_widget::event_reject (octave_event *e)
+{
+  delete e;
+}
+
+void
 history_dock_widget::construct ()
 {
-  m_sortFilterProxyModel.setSourceModel(octave_link::instance ()->get_history_model());
-  m_historyListView = new QListView (this);
-  m_historyListView->setModel (&m_sortFilterProxyModel);
-  m_historyListView->setAlternatingRowColors (true);
-  m_historyListView->setEditTriggers (QAbstractItemView::NoEditTriggers);
-  m_historyListView->setStatusTip (tr ("Doubleclick a command to transfer it to the terminal."));
-  m_filterLineEdit = new QLineEdit (this);
-  m_filterLineEdit->setStatusTip (tr ("Enter text to filter the command history."));
+  _history_model = new QStringListModel ();
+  _sort_filter_proxy_model.setSourceModel (_history_model);
+  _history_list_view = new QListView (this);
+  _history_list_view->setModel (&_sort_filter_proxy_model);
+  _history_list_view->setAlternatingRowColors (true);
+  _history_list_view->setEditTriggers (QAbstractItemView::NoEditTriggers);
+  _history_list_view->setStatusTip (tr ("Doubleclick a command to transfer it to the terminal."));
+  _filter_line_edit = new QLineEdit (this);
+  _filter_line_edit->setStatusTip (tr ("Enter text to filter the command history."));
   QVBoxLayout *layout = new QVBoxLayout ();
 
   setWindowTitle (tr ("Command History"));
   setWidget (new QWidget ());
 
-  layout->addWidget (m_historyListView);
-  layout->addWidget (m_filterLineEdit);
+  layout->addWidget (_history_list_view);
+  layout->addWidget (_filter_line_edit);
   layout->setMargin (2);
 
   widget ()->setLayout (layout);
 
-  connect (m_filterLineEdit, SIGNAL (textEdited (QString)), &m_sortFilterProxyModel, SLOT (setFilterWildcard(QString)));
-  connect (m_historyListView, SIGNAL (doubleClicked (QModelIndex)), this, SLOT (handle_double_click (QModelIndex)));
-  connect (this, SIGNAL (visibilityChanged(bool)), this, SLOT(handle_visibility_changed(bool)));
+  connect (_filter_line_edit,
+           SIGNAL (textEdited (QString)),
+           &_sort_filter_proxy_model,
+           SLOT (setFilterWildcard (QString)));
+
+  connect (_history_list_view,
+           SIGNAL (doubleClicked (QModelIndex)),
+           this,
+           SLOT (handle_double_click (QModelIndex)));
+
+  connect (this,
+           SIGNAL (visibilityChanged (bool)),
+           this,
+           SLOT (handle_visibility_changed (bool)));
+
+  _update_history_model_timer.setInterval (200);
+  _update_history_model_timer.setSingleShot (false);
+
+  connect (&_update_history_model_timer,
+           SIGNAL (timeout ()),
+           this,
+           SLOT (request_history_model_update ()));
+
+  _update_history_model_timer.start ();
 }
 
 void
@@ -65,6 +119,13 @@
 }
 
 void
+history_dock_widget::request_history_model_update ()
+{
+  octave_link::instance ()
+      ->post_event (new octave_update_history_event (*this));
+}
+
+void
 history_dock_widget::closeEvent (QCloseEvent *event)
 {
   emit active_changed (false);
--- a/gui/src/history-dockwidget.h	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/history-dockwidget.h	Mon Jun 04 21:28:08 2012 +0200
@@ -22,17 +22,24 @@
 #include <QLineEdit>
 #include <QListView>
 #include <QSortFilterProxyModel>
-#include "octave-link.h"
+#include <QStringListModel>
+#include <QTimer>
 
-class history_dock_widget:public QDockWidget
+#include "octave-link.h"
+#include "octave-event-observer.h"
+
+class history_dock_widget : public QDockWidget, public octave_event_observer
 {
 Q_OBJECT
 public:
   history_dock_widget (QWidget *parent = 0);
-  void update_history (QStringList history);
+
+  void event_accepted (octave_event *e);
+  void event_reject (octave_event *e);
 
 public slots:
   void handle_visibility_changed (bool visible);
+  void request_history_model_update ();
 
 signals:
   void information (QString message);
@@ -46,9 +53,14 @@
 
 private:
   void construct ();
-  QListView *m_historyListView;
-  QLineEdit *m_filterLineEdit;
-  QSortFilterProxyModel m_sortFilterProxyModel;
+  QListView *_history_list_view;
+  QLineEdit *_filter_line_edit;
+  QSortFilterProxyModel _sort_filter_proxy_model;
+
+  /** Stores the current history_model. */
+  QStringListModel *_history_model;
+
+  QTimer _update_history_model_timer;
 };
 
 #endif // HISTORYDOCKWIDGET_H
--- a/gui/src/octave-adapter/octave-event-observer.h	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/octave-adapter/octave-event-observer.h	Mon Jun 04 21:28:08 2012 +0200
@@ -34,13 +34,13 @@
       * This will be called when an event has been accepted. Operations
       * in this routine will be processed in the octave thread.
       */
-    virtual void event_accepted (octave_event *e) const = 0;
+    virtual void event_accepted (octave_event *e) = 0;
 
     /**
       * This will be called when an event has been rejected. Operations
       * in this routine will be processed in the octave thread.
       */
-    virtual void event_reject (octave_event *e) const = 0;
+    virtual void event_reject (octave_event *e) = 0;
 };
 
 #include "octave-event.h"
--- a/gui/src/octave-adapter/octave-event.h	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/octave-adapter/octave-event.h	Mon Jun 04 21:28:08 2012 +0200
@@ -38,14 +38,14 @@
 class octave_event
 {
   public:
-    octave_event (const octave_event_observer& o)
+    octave_event (octave_event_observer& o)
       : _octave_event_observer (o)
     { }
 
     virtual ~octave_event ()
     { }
 
-    /** Performs what it necessary to make this event happen.
+    /** 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 () const = 0;
@@ -65,7 +65,31 @@
     { _octave_event_observer.event_reject (this); }
 
   private:
-    const octave_event_observer& _octave_event_observer;
+    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 () const
+    { 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 () const
+    { return true; /* Always grant. */ }
 };
 
 /** Implements an octave exit event. */
@@ -73,7 +97,7 @@
 {
   public:
     /** Creates a new octave_exit_event. */
-    octave_exit_event (const octave_event_observer& o)
+    octave_exit_event (octave_event_observer& o)
       : octave_event (o)
     { }
 
@@ -86,7 +110,7 @@
 {
   public:
     /** Creates a new octave_change_directory_event. */
-    octave_change_directory_event (const octave_event_observer& o,
+    octave_change_directory_event (octave_event_observer& o,
                                    std::string directory)
       : octave_event (o)
     { _directory = directory; }
--- a/gui/src/octave-adapter/octave-link.cc	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/octave-adapter/octave-link.cc	Mon Jun 04 21:28:08 2012 +0200
@@ -22,9 +22,6 @@
 
 int octave_readline_hook ()
 {
-  octave_link::instance ()->trigger_update_history_model ();
-  octave_link::instance ()->build_symbol_information ();
-
   octave_link::instance ()->generate_events ();
   octave_link::instance ()->process_events ();
   return 0;
@@ -40,9 +37,6 @@
 
 octave_link::octave_link ()
 {
-  _history_model = new QStringListModel ();
-  _workspace_model = new workspace_model (qApp);
-  _symbol_information_semaphore = new QSemaphore (1);
   _event_queue_semaphore = new QSemaphore (1);
   _last_working_directory = "";
 }
@@ -64,74 +58,9 @@
 }
 
 void
-octave_link::trigger_update_history_model ()
-{
-  // 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)
-    {
-      for (int i = clientHistoryLength; i < serverHistoryLength; i++)
-        {
-          _history_model->insertRow (0);
-          _history_model->setData (_history_model->index (0), QString (command_history::get_entry (i).c_str ()));
-        }
-    }
-}
-
-void
-octave_link::acquire_symbol_information ()
-{
-  _symbol_information_semaphore->acquire (1);
-}
-
-void
-octave_link::release_symbol_information ()
-{
-  _symbol_information_semaphore->release (1);
-}
-
-void
-octave_link::build_symbol_information ()
-{
-  std::list < symbol_table::symbol_record > symbolTable = symbol_table::all_variables ();
-
-  acquire_symbol_information ();
-  _symbol_information.clear ();
-  for (std::list < symbol_table::symbol_record > ::iterator iterator = symbolTable.begin ();
-     iterator != symbolTable.end (); iterator++)
-  {
-    symbol_information symbolInformation;
-    symbolInformation.from_symbol_record (*iterator);
-    _symbol_information.push_back (symbolInformation);
-  }
-  release_symbol_information ();
-}
-
-const QList <symbol_information>&
-octave_link::get_symbol_information () const
-{
-  return _symbol_information;
-}
-
-void
 octave_link::register_event_listener (octave_event_listener *oel)
 { _octave_event_listener = oel; }
 
-QStringListModel *
-octave_link::get_history_model ()
-{
-  return _history_model;
-}
-
-workspace_model *
-octave_link::get_workspace_model ()
-{
-  return _workspace_model;
-}
-
 void
 octave_link::generate_events ()
 {
@@ -173,11 +102,11 @@
 }
 
 void
-octave_link::event_accepted (octave_event *e) const
+octave_link::event_accepted (octave_event *e)
 { delete e; }
 
 void
-octave_link::event_reject (octave_event *e) const
+octave_link::event_reject (octave_event *e)
 { delete e; }
 
 void
--- a/gui/src/octave-adapter/octave-link.h	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/octave-adapter/octave-link.h	Mon Jun 04 21:28:08 2012 +0200
@@ -62,17 +62,7 @@
 #include <queue>
 
 // Qt includes
-#include <QMutexLocker>
-#include <QMutex>
-#include <QFileInfo>
-#include <QList>
-#include <QString>
-#include <QStringList>
-#include <QVector>
 #include <QSemaphore>
-#include <QStringListModel>
-#include <QTimer>
-#include <QQueue>
 
 #include "workspace-model.h"
 #include "octave-main-thread.h"
@@ -98,40 +88,13 @@
 
   /** Starts octave. */
   void launch_octave ();
-
-  /** Returns the current history model. */
-  QStringListModel *get_history_model ();
-
-  /** Returns the current workspace model. */
-  workspace_model *get_workspace_model ();
-
-  /** Triggers an update of the history model. */
-  void trigger_update_history_model ();
-
-  /** Acquires the symbol information. You need to acquire that before
-    * actually accessing it. Make sure that you release it properly in order
-    * to avoid deadlocks. */
-  void acquire_symbol_information ();
-
-  /** Releases access to the symbol information. */
-  void release_symbol_information ();
-
-  /** Update symbol information from octave's symboltable. */
-  void build_symbol_information ();
-
-  /** Provides acces to the current symbol information.
-    * WARNING: Always acquire the symbol information before actually
-    * using it and make sure you release it properly afterwards.
-    */
-  const QList <symbol_information>& get_symbol_information () const;
-
   void register_event_listener (octave_event_listener *oel);
 
   void generate_events ();
   void process_events ();
   void post_event (octave_event *e);
-  void event_accepted (octave_event *e) const;
-  void event_reject (octave_event *e) const;
+  void event_accepted (octave_event *e);
+  void event_reject (octave_event *e);
 
   void request_working_directory_change (std::string directory);
   void request_octave_exit ();
@@ -143,27 +106,15 @@
 
   octave_event_listener *_octave_event_listener;
 
-  /** Stores the current history_model. */
-  QStringListModel *_history_model;
-
-  /** Stores the current workspace model. */
-  workspace_model *_workspace_model;
-
   /** Thread running octave_main. */
   octave_main_thread *_octave_main_thread;
 
-  /** Semaphore to lock access to the symbol information. */
-  QSemaphore *_symbol_information_semaphore;
-
   /** Semaphore to lock access to the event queue. */
   QSemaphore *_event_queue_semaphore;
 
   /** Buffer for queueing events until they will be processed. */
   std::queue <octave_event *> _event_queue;
 
-  /** Stores the current symbol information. */
-  QList <symbol_information> _symbol_information;
-
   /** Stores the last known current working directory of octave. */
   std::string _last_working_directory;
 
--- a/gui/src/workspace-model.cc	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/workspace-model.cc	Mon Jun 04 21:28:08 2012 +0200
@@ -21,7 +21,7 @@
 #include "octave-link.h"
 
 workspace_model::workspace_model(QObject *parent)
-  : QAbstractItemModel(parent)
+  : QAbstractItemModel(parent), octave_event_observer ()
 {
   QList<QVariant> rootData;
   rootData << tr ("Name") << tr ("Type") << tr ("Value");
@@ -31,6 +31,15 @@
   insert_top_level_item(1, new tree_item ("Global"));
   insert_top_level_item(2, new tree_item ("Persistent"));
   insert_top_level_item(3, new tree_item ("Hidden"));
+
+  connect(&_update_workspace_model_timer,
+          SIGNAL (timeout ()),
+          this,
+          SLOT (request_update_workspace()));
+
+  _update_workspace_model_timer.setInterval (500);
+  _update_workspace_model_timer.setSingleShot (false);
+  _update_workspace_model_timer.start ();
 }
 
 workspace_model::~workspace_model()
@@ -38,6 +47,63 @@
   delete _rootItem;
 }
 
+void
+workspace_model::request_update_workspace ()
+{
+  octave_link::instance ()
+      ->post_event (new octave_update_workspace_event (*this));
+}
+
+void
+workspace_model::event_accepted (octave_event *e)
+{
+  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 symbolInformation;
+        symbolInformation.from_symbol_record (*iterator);
+        _symbol_information.push_back (symbolInformation);
+      }
+
+      top_level_item (0)->delete_child_items ();
+      top_level_item (1)->delete_child_items ();
+      top_level_item (2)->delete_child_items ();
+      top_level_item (3)->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._type);
+          child->set_data (2, 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;
+              case symbol_information::hidden:      top_level_item (3)->add_child (child); break;
+            }
+        }
+
+      reset();
+      emit expand_request();
+    }
+  delete e;
+}
+
+void
+workspace_model::event_reject (octave_event *e)
+{
+  delete e;
+}
+
 QModelIndex
 workspace_model::index(int row, int column, const QModelIndex &parent) const
 {
@@ -141,37 +207,3 @@
   return item->data(index.column());
 }
 
-
-void
-workspace_model::update_from_symbol_table ()
-{
-  top_level_item (0)->delete_child_items ();
-  top_level_item (1)->delete_child_items ();
-  top_level_item (2)->delete_child_items ();
-  top_level_item (3)->delete_child_items ();
-
-  octave_link::instance ()-> acquire_symbol_information();
-  const QList <symbol_information>& symbolInformation = octave_link::instance() ->get_symbol_information ();
-
-  foreach (const symbol_information& s, symbolInformation)
-    {
-      tree_item *child = new tree_item ();
-
-      child->set_data (0, s._symbol);
-      child->set_data (1, s._type);
-      child->set_data (2, 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;
-          case symbol_information::hidden:      top_level_item (3)->add_child (child); break;
-        }
-    }
-
-  octave_link::instance ()-> release_symbol_information();
-
-  reset();
-  emit expand_request();
-}
--- a/gui/src/workspace-model.h	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/workspace-model.h	Mon Jun 04 21:28:08 2012 +0200
@@ -24,6 +24,9 @@
 #include <QSemaphore>
 #include <QTimer>
 
+#include "symbol-information.h"
+#include "octave-event-observer.h"
+
 class tree_item
 {
 public:
@@ -103,13 +106,17 @@
   tree_item *_parent_item;
 };
 
-class workspace_model : public QAbstractItemModel
+class workspace_model
+    : public QAbstractItemModel, public octave_event_observer
 {
   Q_OBJECT
 
 public:
-  workspace_model(QObject *parent = 0);
-  ~workspace_model();
+  workspace_model (QObject *parent = 0);
+  ~workspace_model ();
+
+  void event_accepted (octave_event *e);
+  void event_reject (octave_event *e);
 
   QVariant data(const QModelIndex &index, int role) const;
   Qt::ItemFlags flags(const QModelIndex &index) const;
@@ -125,12 +132,18 @@
   tree_item *top_level_item (int at);
 
 public slots:
-  void update_from_symbol_table ();
+  void request_update_workspace ();
 
 signals:
   void expand_request();
 
 private:
+  /** Timer for periodically updating the workspace model from the current
+    * symbol information. */
+  QTimer _update_workspace_model_timer;
+
+  /** Stores the current symbol information. */
+  QList <symbol_information> _symbol_information;
   tree_item *_rootItem;
 };
 
--- a/gui/src/workspace-view.cc	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/workspace-view.cc	Mon Jun 04 21:28:08 2012 +0200
@@ -26,11 +26,13 @@
   setObjectName ("WorkspaceView");
   setWindowTitle (tr ("Workspace"));
 
+  _workspace_model = new workspace_model ();
+
   _workspace_tree_view = new QTreeView (this);
   _workspace_tree_view->setHeaderHidden (false);
   _workspace_tree_view->setAlternatingRowColors (true);
   _workspace_tree_view->setAnimated (true);
-  _workspace_tree_view->setModel(octave_link::instance()->get_workspace_model());
+  _workspace_tree_view->setModel (_workspace_model);
 
   setWidget (new QWidget (this));
   QVBoxLayout *layout = new QVBoxLayout ();
@@ -41,16 +43,8 @@
   connect (this, SIGNAL (visibilityChanged (bool)),
            this, SLOT(handle_visibility_changed (bool)));
 
-  connect (octave_link::instance()->get_workspace_model(), SIGNAL(expand_request()),
+  connect (_workspace_model, SIGNAL(expand_request()),
            _workspace_tree_view, SLOT(expandAll()));
-
-  connect(&_update_workspace_model_timer, SIGNAL (timeout ()),
-    octave_link::instance()->get_workspace_model(),
-          SLOT (update_from_symbol_table ()));
-
-  _update_workspace_model_timer.setInterval (1000);
-  _update_workspace_model_timer.setSingleShot (false);
-  _update_workspace_model_timer.start ();
 }
 
 void
--- a/gui/src/workspace-view.h	Mon Jun 04 16:08:44 2012 +0200
+++ b/gui/src/workspace-view.h	Mon Jun 04 21:28:08 2012 +0200
@@ -42,9 +42,8 @@
 private:
   QTreeView *_workspace_tree_view;
 
-  /** Timer for periodically updating the workspace model from the current
-    * symbol information. */
-  QTimer _update_workspace_model_timer;
+  /** Stores the current workspace model. */
+  workspace_model *_workspace_model;
 };
 
 #endif // WORKSPACEVIEW_H