changeset 13683:25dc40d24a44

Renamed VariablesDockWidget to WorkspaceView and optimized memory footprint for 30%.
author Jacob Dawid <jacob.dawid@googlemail.com>
date Fri, 30 Sep 2011 12:34:37 +0200
parents c0e0625ffd13
children 4eb1247acf8f
files gui/octave-gui.pro gui/src/MainWindow.cpp gui/src/MainWindow.h gui/src/VariablesDockWidget.cpp gui/src/VariablesDockWidget.h gui/src/WorkspaceView.cpp gui/src/WorkspaceView.h gui/src/backend/OctaveCallbackThread.cpp gui/src/backend/OctaveLink.cpp gui/src/backend/OctaveLink.h
diffstat 10 files changed, 299 insertions(+), 327 deletions(-) [+]
line wrap: on
line diff
--- a/gui/octave-gui.pro	Mon Sep 26 07:55:20 2011 +0200
+++ b/gui/octave-gui.pro	Fri Sep 30 12:34:37 2011 +0200
@@ -67,7 +67,7 @@
 SOURCES +=\
     src/lexer/lexeroctavegui.cpp \
     src/MainWindow.cpp \
-    src/VariablesDockWidget.cpp \
+    src/WorkspaceView.cpp \
     src/HistoryDockWidget.cpp \
     src/FilesDockWidget.cpp \
     src/FileEditorMdiSubWindow.cpp \
@@ -98,7 +98,7 @@
 HEADERS += \
     src/lexer/lexeroctavegui.h \
     src/MainWindow.h \
-    src/VariablesDockWidget.h \
+    src/WorkspaceView.h \
     src/HistoryDockWidget.h \
     src/FilesDockWidget.h \
     src/FileEditorMdiSubWindow.h \
--- a/gui/src/MainWindow.cpp	Mon Sep 26 07:55:20 2011 +0200
+++ b/gui/src/MainWindow.cpp	Fri Sep 30 12:34:37 2011 +0200
@@ -26,9 +26,8 @@
 #include "FileEditorMdiSubWindow.h"
 #include "ImageViewerMdiSubWindow.h"
 #include "SettingsDialog.h"
-#include "cmd-edit.h"
 
-#define VERSION_STRING "Octave GUI (0.8.4)"
+#define VERSION_STRING "Octave GUI (0.8.5)"
 
 MainWindow::MainWindow (QWidget * parent):QMainWindow (parent)
 {
@@ -278,8 +277,8 @@
   m_centralMdiArea->setViewMode (QMdiArea::TabbedView);
 
   // Setup dockable widgets and the status bar.
-  m_variablesDockWidget = new VariablesDockWidget (this);
-  m_variablesDockWidget->setStatusTip (tr ("View the variables in the active workspace."));
+  m_workspaceView = new WorkspaceView (this);
+  m_workspaceView->setStatusTip (tr ("View the variables in the active workspace."));
   m_historyDockWidget = new HistoryDockWidget (this);
   m_historyDockWidget->setStatusTip (tr ("Browse and search the command history."));
   m_filesDockWidget = new FilesDockWidget (this);
@@ -378,14 +377,14 @@
   connect (aboutOctaveAction, SIGNAL (triggered ()), this, SLOT (showAboutOctave ()));
   connect (aboutQt, SIGNAL (triggered ()), this, SLOT (showAboutQt ()));
 
-  connect (showWorkspaceAction, SIGNAL (toggled (bool)), m_variablesDockWidget, SLOT (setShown (bool)));
-  connect (m_variablesDockWidget, SIGNAL (activeChanged (bool)), showWorkspaceAction, SLOT (setChecked (bool)));
+  connect (showWorkspaceAction, SIGNAL (toggled (bool)), m_workspaceView, SLOT (setShown (bool)));
+  connect (m_workspaceView, SIGNAL (activeChanged (bool)), showWorkspaceAction, SLOT (setChecked (bool)));
   connect (showHistoryAction, SIGNAL (toggled (bool)), m_historyDockWidget, SLOT (setShown (bool)));
   connect (m_historyDockWidget, SIGNAL (activeChanged (bool)), showHistoryAction, SLOT (setChecked (bool)));
   connect (showFileBrowserAction, SIGNAL (toggled (bool)), m_filesDockWidget, SLOT (setShown (bool)));
   connect (m_filesDockWidget, SIGNAL (activeChanged (bool)), showFileBrowserAction, SLOT (setChecked (bool)));
 
-  connect (this, SIGNAL (settingsChanged ()), m_variablesDockWidget, SLOT (noticeSettings ()));
+  connect (this, SIGNAL (settingsChanged ()), m_workspaceView, SLOT (noticeSettings ()));
   connect (this, SIGNAL (settingsChanged ()), m_historyDockWidget, SLOT (noticeSettings ()));
   connect (this, SIGNAL (settingsChanged ()), m_filesDockWidget, SLOT (noticeSettings ()));
 
@@ -399,7 +398,7 @@
   setWindowTitle (QString (VERSION_STRING));
 
   setCentralWidget (m_centralMdiArea);
-  addDockWidget (Qt::LeftDockWidgetArea, m_variablesDockWidget);
+  addDockWidget (Qt::LeftDockWidgetArea, m_workspaceView);
   addDockWidget (Qt::LeftDockWidgetArea, m_historyDockWidget);
   addDockWidget (Qt::RightDockWidgetArea, m_filesDockWidget);
   setStatusBar (m_statusBar);
--- a/gui/src/MainWindow.h	Mon Sep 26 07:55:20 2011 +0200
+++ b/gui/src/MainWindow.h	Fri Sep 30 12:34:37 2011 +0200
@@ -30,7 +30,7 @@
 #include "ResourceManager.h"
 #include "TerminalView.h"
 #include "OctaveLink.h"
-#include "VariablesDockWidget.h"
+#include "WorkspaceView.h"
 #include "HistoryDockWidget.h"
 #include "FilesDockWidget.h"
 #include "BrowserWidget.h"
@@ -66,10 +66,7 @@
   {
     return m_terminalView;
   }
-  VariablesDockWidget *variablesDockWidget ()
-  {
-    return m_variablesDockWidget;
-  }
+
   HistoryDockWidget *historyDockWidget ()
   {
     return m_historyDockWidget;
@@ -125,7 +122,7 @@
   NonClosableMdiSubWindow *m_ircWidgetSubWindow;
 
   // Dock widgets.
-  VariablesDockWidget *m_variablesDockWidget;
+  WorkspaceView *m_workspaceView;
   HistoryDockWidget *m_historyDockWidget;
   FilesDockWidget *m_filesDockWidget;
 
--- a/gui/src/VariablesDockWidget.cpp	Mon Sep 26 07:55:20 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,225 +0,0 @@
-/* OctaveGUI - A graphical user interface for Octave
- * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "VariablesDockWidget.h"
-#include <QHBoxLayout>
-#include <QVBoxLayout>
-#include <QPushButton>
-
-VariablesDockWidget::VariablesDockWidget (QWidget * parent):QDockWidget
-  (parent)
-{
-  setObjectName ("VariablesDockWidget");
-  construct ();
-
-  connect (OctaveLink::instance(), SIGNAL (symbolTableChanged()), this, SLOT (fetchSymbolTable()));
-}
-
-void
-VariablesDockWidget::construct ()
-{
-  setWindowTitle (tr ("Workspace"));
-
-  m_updateSemaphore = new QSemaphore (1);
-  QStringList headerLabels;
-  headerLabels << tr ("Name") << tr ("Type") << tr ("Value");
-  m_variablesTreeWidget = new QTreeWidget (this);
-  m_variablesTreeWidget->setHeaderHidden (false);
-  m_variablesTreeWidget->setHeaderLabels (headerLabels);
-
-  setWidget (new QWidget (this));
-  QVBoxLayout *layout = new QVBoxLayout ();
-  layout->addWidget (m_variablesTreeWidget);
-  layout->setMargin (2);
-  widget ()->setLayout (layout);
-
-  QTreeWidgetItem *treeWidgetItem = new QTreeWidgetItem ();
-  treeWidgetItem->setData (0, 0, QString (tr ("Local")));
-  m_variablesTreeWidget->insertTopLevelItem (0, treeWidgetItem);
-
-  treeWidgetItem = new QTreeWidgetItem ();
-  treeWidgetItem->setData (0, 0, QString (tr ("Global")));
-  m_variablesTreeWidget->insertTopLevelItem (1, treeWidgetItem);
-
-  treeWidgetItem = new QTreeWidgetItem ();
-  treeWidgetItem->setData (0, 0, QString (tr ("Persistent")));
-  m_variablesTreeWidget->insertTopLevelItem (2, treeWidgetItem);
-
-  treeWidgetItem = new QTreeWidgetItem ();
-  treeWidgetItem->setData (0, 0, QString (tr ("Hidden")));
-  m_variablesTreeWidget->insertTopLevelItem (3, treeWidgetItem);
-
-  m_variablesTreeWidget->expandAll ();
-  m_variablesTreeWidget->setAlternatingRowColors (true);
-  m_variablesTreeWidget->setAnimated (true);
-
-  connect (this, SIGNAL (visibilityChanged(bool)), this, SLOT(handleVisibilityChanged(bool)));
-
-  setStyleSheet(
-      " QDockWidget { "
-      "   border:1px solid rgba(200, 200, 200, 255); "
-      "   background-color: qlineargradient(spread:pad, "
-      "   x1:0.1, y1:0, x2:0.9, y2:1, "
-      "   stop:0.256444 rgba(255, 215, 215, 255), "
-      "   stop:0.550888 rgba(255, 255, 255, 255), "
-      "   stop:0.780424 rgba(255, 215, 215, 255)); "
-      " } "
-      );
-}
-
-void
-VariablesDockWidget::updateTreeEntry (QTreeWidgetItem * treeItem,
-				      SymbolRecord symbolRecord)
-{
-  treeItem->setData (0, 0, QString (symbolRecord.name ().c_str ()));
-  treeItem->setData (1, 0,
-		     QString (symbolRecord.varval ().type_name ().c_str ()));
-  treeItem->setData (2, 0,
-		     OctaveLink::octaveValueAsQString (symbolRecord.
-						       varval ()));
-}
-
-void
-VariablesDockWidget::setVariablesList (QList < SymbolRecord > symbolTable)
-{
-  m_updateSemaphore->acquire ();
-  // Split the symbol table into its different scopes.
-  QList < SymbolRecord > localSymbolTable;
-  QList < SymbolRecord > globalSymbolTable;
-  QList < SymbolRecord > persistentSymbolTable;
-  QList < SymbolRecord > hiddenSymbolTable;
-
-  foreach (SymbolRecord symbolRecord, symbolTable)
-  {
-    // It's true that being global or hidden includes it's can mean it's also locally visible,
-    // but we want to distinguish that here.
-    if (symbolRecord.is_local () && !symbolRecord.is_global ()
-	&& !symbolRecord.is_hidden ())
-      {
-	localSymbolTable.append (symbolRecord);
-      }
-
-    if (symbolRecord.is_global ())
-      {
-	globalSymbolTable.append (symbolRecord);
-      }
-
-    if (symbolRecord.is_persistent ())
-      {
-	persistentSymbolTable.append (symbolRecord);
-      }
-
-    if (symbolRecord.is_hidden ())
-      {
-	hiddenSymbolTable.append (symbolRecord);
-      }
-  }
-
-  updateScope (0, localSymbolTable);
-  updateScope (1, globalSymbolTable);
-  updateScope (2, persistentSymbolTable);
-  updateScope (3, hiddenSymbolTable);
-  m_updateSemaphore->release ();
-}
-
-void
-VariablesDockWidget::updateScope (int topLevelItemIndex,
-				  QList < SymbolRecord > symbolTable)
-{
-  // This method may be a little bit confusing; variablesList is a complete list of all
-  // variables that are in the workspace currently.
-  QTreeWidgetItem *topLevelItem =
-    m_variablesTreeWidget->topLevelItem (topLevelItemIndex);
-
-  // First we check, if any variables that exist in the model tree have to be updated
-  // or created. So we walk the variablesList check against the tree.
-  foreach (SymbolRecord symbolRecord, symbolTable)
-  {
-    int childCount = topLevelItem->childCount ();
-    bool alreadyExists = false;
-    QTreeWidgetItem *child;
-
-    // Search for the corresponding item in the tree. If it has been found, child
-    // will contain the appropriate QTreeWidgetItem* pointing at it.
-    for (int i = 0; i < childCount; i++)
-      {
-        child = topLevelItem->child (i);
-        if (child->data (0, 0).toString () ==
-            QString (symbolRecord.name ().c_str ()))
-          {
-            alreadyExists = true;
-            break;
-          }
-      }
-
-    // If it already exists, just update it.
-    if (alreadyExists)
-      {
-        updateTreeEntry (child, symbolRecord);
-      }
-    else
-      {
-        // It does not exist, so create a new one and set the right values.
-        child = new QTreeWidgetItem ();
-        updateTreeEntry (child, symbolRecord);
-        topLevelItem->addChild (child);
-      }
-  }
-
-  // Check the tree against the list for deleted variables.
-  for (int i = 0; i < topLevelItem->childCount (); i++)
-    {
-      bool existsInVariableList = false;
-      QTreeWidgetItem *child = topLevelItem->child (i);
-      foreach (SymbolRecord symbolRecord, symbolTable)
-        {
-          if (QString (symbolRecord.name ().c_str ()) ==
-              child->data (0, 0).toString ())
-            {
-              existsInVariableList = true;
-            }
-        }
-
-      if (!existsInVariableList)
-        {
-          topLevelItem->removeChild (child);
-          delete child;
-          i--;
-        }
-    }
-}
-
-void
-VariablesDockWidget::fetchSymbolTable ()
-{
-  QList < SymbolRecord > symbolTable = OctaveLink::instance ()->copyCurrentSymbolTable ();
-  setVariablesList (symbolTable);
-}
-
-void
-VariablesDockWidget::handleVisibilityChanged (bool visible)
-{
-  if (visible)
-    emit activeChanged (true);
-}
-
-void
-VariablesDockWidget::closeEvent (QCloseEvent *event)
-{
-  emit activeChanged (false);
-  QDockWidget::closeEvent (event);
-}
--- a/gui/src/VariablesDockWidget.h	Mon Sep 26 07:55:20 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* OctaveGUI - A graphical user interface for Octave
- * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com)
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program 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 Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef VARIABLESDOCKWIDGET_H
-#define VARIABLESDOCKWIDGET_H
-
-#include <QDockWidget>
-#include <QTreeWidget>
-#include <QSemaphore>
-#include "OctaveLink.h"
-
-class VariablesDockWidget:public QDockWidget
-{
-  Q_OBJECT
-public:
-  VariablesDockWidget (QWidget * parent = 0);
-  void setVariablesList (QList < SymbolRecord > symbolTable);
-
-public slots:
-  void fetchSymbolTable ();
-  void handleVisibilityChanged (bool visible);
-signals:
-  /** Custom signal that tells if a user has clicke away that dock widget. */
-  void activeChanged (bool active);
-protected:
-  void closeEvent (QCloseEvent *event);
-private:
-  void construct ();
-  void updateTreeEntry (QTreeWidgetItem * treeItem,
-			SymbolRecord symbolRecord);
-  void updateScope (int topLevelItemIndex,
-		    QList < SymbolRecord > symbolTable);
-  QTreeWidget *m_variablesTreeWidget;
-  QSemaphore *m_updateSemaphore;
-};
-
-#endif // VARIABLESDOCKWIDGET_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gui/src/WorkspaceView.cpp	Fri Sep 30 12:34:37 2011 +0200
@@ -0,0 +1,219 @@
+/* OctaveGUI - A graphical user interface for Octave
+ * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WorkspaceView.h"
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QPushButton>
+
+WorkspaceView::WorkspaceView (QWidget * parent) : QDockWidget
+  (parent)
+{
+  setObjectName ("WorkspaceView");
+  setWindowTitle (tr ("Workspace"));
+
+  m_updateSemaphore = new QSemaphore (1);
+  QStringList headerLabels;
+  headerLabels << tr ("Name") << tr ("Type") << tr ("Value");
+  m_variablesTreeWidget = new QTreeWidget (this);
+  m_variablesTreeWidget->setHeaderHidden (false);
+  m_variablesTreeWidget->setHeaderLabels (headerLabels);
+
+  setWidget (new QWidget (this));
+  QVBoxLayout *layout = new QVBoxLayout ();
+  layout->addWidget (m_variablesTreeWidget);
+  layout->setMargin (2);
+  widget ()->setLayout (layout);
+
+  QTreeWidgetItem *treeWidgetItem = new QTreeWidgetItem ();
+  treeWidgetItem->setData (0, 0, QString (tr ("Local")));
+  m_variablesTreeWidget->insertTopLevelItem (0, treeWidgetItem);
+
+  treeWidgetItem = new QTreeWidgetItem ();
+  treeWidgetItem->setData (0, 0, QString (tr ("Global")));
+  m_variablesTreeWidget->insertTopLevelItem (1, treeWidgetItem);
+
+  treeWidgetItem = new QTreeWidgetItem ();
+  treeWidgetItem->setData (0, 0, QString (tr ("Persistent")));
+  m_variablesTreeWidget->insertTopLevelItem (2, treeWidgetItem);
+
+  treeWidgetItem = new QTreeWidgetItem ();
+  treeWidgetItem->setData (0, 0, QString (tr ("Hidden")));
+  m_variablesTreeWidget->insertTopLevelItem (3, treeWidgetItem);
+
+  m_variablesTreeWidget->expandAll ();
+  m_variablesTreeWidget->setAlternatingRowColors (true);
+  m_variablesTreeWidget->setAnimated (true);
+
+  connect (this, SIGNAL (visibilityChanged(bool)), this, SLOT(handleVisibilityChanged(bool)));
+
+  setStyleSheet(
+      " QDockWidget { "
+      "   border:1px solid rgba(200, 200, 200, 255); "
+      "   background-color: qlineargradient(spread:pad, "
+      "   x1:0.1, y1:0, x2:0.9, y2:1, "
+      "   stop:0.256444 rgba(255, 215, 215, 255), "
+      "   stop:0.550888 rgba(255, 255, 255, 255), "
+      "   stop:0.780424 rgba(255, 215, 215, 255)); "
+      " } "
+      );
+
+  connect (OctaveLink::instance(), SIGNAL (symbolTableChanged()), this, SLOT (fetchSymbolTable()));
+}
+
+void
+WorkspaceView::updateTreeEntry (QTreeWidgetItem * treeItem, SymbolRecord symbolRecord)
+{
+  treeItem->setData (0, 0, QString (symbolRecord.name ().c_str ()));
+  treeItem->setData (1, 0,
+		     QString (symbolRecord.varval ().type_name ().c_str ()));
+  treeItem->setData (2, 0,
+		     OctaveLink::octaveValueAsQString (symbolRecord.
+						       varval ()));
+}
+
+void
+WorkspaceView::updateFromSymbolTable (QList < SymbolRecord > symbolTable)
+{
+  m_updateSemaphore->acquire ();
+  // Split the symbol table into its different scopes.
+  QList < SymbolRecord > localSymbolTable;
+  QList < SymbolRecord > globalSymbolTable;
+  QList < SymbolRecord > persistentSymbolTable;
+  QList < SymbolRecord > hiddenSymbolTable;
+
+  foreach (SymbolRecord symbolRecord, symbolTable)
+  {
+    // It's true that being global or hidden includes it's can mean it's also locally visible,
+    // but we want to distinguish that here.
+    if (symbolRecord.is_local () && !symbolRecord.is_global ()
+        && !symbolRecord.is_hidden ())
+      {
+        localSymbolTable.append (symbolRecord);
+      }
+
+    if (symbolRecord.is_global ())
+      {
+        globalSymbolTable.append (symbolRecord);
+      }
+
+    if (symbolRecord.is_persistent ())
+      {
+        persistentSymbolTable.append (symbolRecord);
+      }
+
+    if (symbolRecord.is_hidden ())
+      {
+        hiddenSymbolTable.append (symbolRecord);
+      }
+  }
+
+  updateScope (0, localSymbolTable);
+  updateScope (1, globalSymbolTable);
+  updateScope (2, persistentSymbolTable);
+  updateScope (3, hiddenSymbolTable);
+  m_updateSemaphore->release ();
+}
+
+void
+WorkspaceView::updateScope (int topLevelItemIndex, QList < SymbolRecord > symbolTable)
+{
+  // This method may be a little bit confusing; variablesList is a complete list of all
+  // variables that are in the workspace currently.
+  QTreeWidgetItem *topLevelItem =
+    m_variablesTreeWidget->topLevelItem (topLevelItemIndex);
+
+  // First we check, if any variables that exist in the model tree have to be updated
+  // or created. So we walk the variablesList check against the tree.
+  foreach (SymbolRecord symbolRecord, symbolTable)
+  {
+    int childCount = topLevelItem->childCount ();
+    bool alreadyExists = false;
+    QTreeWidgetItem *child;
+
+    // Search for the corresponding item in the tree. If it has been found, child
+    // will contain the appropriate QTreeWidgetItem* pointing at it.
+    for (int i = 0; i < childCount; i++)
+      {
+        child = topLevelItem->child (i);
+        if (child->data (0, 0).toString () ==
+            QString (symbolRecord.name ().c_str ()))
+          {
+            alreadyExists = true;
+            break;
+          }
+      }
+
+    // If it already exists, just update it.
+    if (alreadyExists)
+      {
+        updateTreeEntry (child, symbolRecord);
+      }
+    else
+      {
+        // It does not exist, so create a new one and set the right values.
+        child = new QTreeWidgetItem ();
+        updateTreeEntry (child, symbolRecord);
+        topLevelItem->addChild (child);
+      }
+  }
+
+  // Check the tree against the list for deleted variables.
+  for (int i = 0; i < topLevelItem->childCount (); i++)
+    {
+      bool existsInVariableList = false;
+      QTreeWidgetItem *child = topLevelItem->child (i);
+      foreach (SymbolRecord symbolRecord, symbolTable)
+        {
+          if (QString (symbolRecord.name ().c_str ()) ==
+              child->data (0, 0).toString ())
+            {
+              existsInVariableList = true;
+            }
+        }
+
+      if (!existsInVariableList)
+        {
+          topLevelItem->removeChild (child);
+          delete child;
+          i--;
+        }
+    }
+}
+
+void
+WorkspaceView::fetchSymbolTable ()
+{
+  OctaveLink::instance ()->acquireSymbolTable();
+  QList < SymbolRecord > symbolTable = OctaveLink::instance ()->symbolTable();
+  updateFromSymbolTable (symbolTable);
+  OctaveLink::instance ()->releaseSymbolTable();
+}
+
+void
+WorkspaceView::handleVisibilityChanged (bool visible)
+{
+  if (visible)
+  emit activeChanged (true);
+}
+
+void
+WorkspaceView::closeEvent (QCloseEvent *event)
+{
+  emit activeChanged (false);
+  QDockWidget::closeEvent (event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gui/src/WorkspaceView.h	Fri Sep 30 12:34:37 2011 +0200
@@ -0,0 +1,52 @@
+/* OctaveGUI - A graphical user interface for Octave
+ * Copyright (C) 2011 Jacob Dawid (jacob.dawid@googlemail.com)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WORKSPACEVIEW_H
+#define WORKSPACEVIEW_H
+
+#include <QDockWidget>
+#include <QTreeWidget>
+#include <QSemaphore>
+#include "OctaveLink.h"
+
+class WorkspaceView:public QDockWidget
+{
+  Q_OBJECT
+public:
+  WorkspaceView (QWidget * parent = 0);
+
+public slots:
+  void fetchSymbolTable ();
+  void handleVisibilityChanged (bool visible);
+
+signals:
+  /** Custom signal that tells if a user has clicke away that dock widget. */
+  void activeChanged (bool active);
+
+protected:
+  void closeEvent (QCloseEvent *event);
+
+private:
+  void updateFromSymbolTable (QList < SymbolRecord > symbolTable);
+  void updateTreeEntry (QTreeWidgetItem * treeItem, SymbolRecord symbolRecord);
+  void updateScope (int topLevelItemIndex, QList < SymbolRecord > symbolTable);
+
+  QTreeWidget *m_variablesTreeWidget;
+  QSemaphore *m_updateSemaphore;
+};
+
+#endif // WORKSPACEVIEW_H
--- a/gui/src/backend/OctaveCallbackThread.cpp	Mon Sep 26 07:55:20 2011 +0200
+++ b/gui/src/backend/OctaveCallbackThread.cpp	Fri Sep 30 12:34:37 2011 +0200
@@ -39,7 +39,7 @@
   bool running = true;
   while (running)
     {
-      OctaveLink::instance ()->fetchSymbolTable ();
+      OctaveLink::instance ()->emitSymbolTableChanged();
       OctaveLink::instance ()->updateHistoryModel ();
       usleep (500000);
 
--- a/gui/src/backend/OctaveLink.cpp	Mon Sep 26 07:55:20 2011 +0200
+++ b/gui/src/backend/OctaveLink.cpp	Fri Sep 30 12:34:37 2011 +0200
@@ -114,34 +114,17 @@
   //m_octaveMainThread->wait();
 }
 
-void
-OctaveLink::fetchSymbolTable ()
+QList < SymbolRecord > OctaveLink::symbolTable ()
 {
-  m_symbolTableSemaphore->acquire ();
   m_symbolTableBuffer.clear ();
   std::list < SymbolRecord > allVariables = symbol_table::all_variables ();
   std::list < SymbolRecord >::iterator iterator;
   for (iterator = allVariables.begin (); iterator != allVariables.end ();
        iterator++)
-    m_symbolTableBuffer.append (iterator->dup ());
-  m_symbolTableSemaphore->release ();
-  emit symbolTableChanged ();
+    m_symbolTableBuffer.append (iterator->dup());
+  return m_symbolTableBuffer;
 }
 
-QList < SymbolRecord > OctaveLink::copyCurrentSymbolTable ()
-{
-  QList < SymbolRecord > m_symbolTableCopy;
-
-  // Generate a deep copy of the current symbol table.
-  m_symbolTableSemaphore->acquire ();
-  foreach (SymbolRecord symbolRecord, m_symbolTableBuffer)
-    m_symbolTableCopy.append (symbolRecord.dup ());
-  m_symbolTableSemaphore->release ();
-
-  return m_symbolTableCopy;
-}
-
-
 void
 OctaveLink::updateHistoryModel ()
 {
--- a/gui/src/backend/OctaveLink.h	Mon Sep 26 07:55:20 2011 +0200
+++ b/gui/src/backend/OctaveLink.h	Fri Sep 30 12:34:37 2011 +0200
@@ -96,6 +96,14 @@
 
   void launchOctave ();
   void terminateOctave ();
+  void acquireSymbolTable () { m_symbolTableSemaphore->acquire (); }
+  void releaseSymbolTable () { m_symbolTableSemaphore->release (); }
+
+  /**
+    * For performance reasons this is not thread safe. Before you use this,
+    * acquire a lock with acquireSymbolTable and releaseSymbolTable.
+    */
+  QList < SymbolRecord > symbolTable ();
 
   /**
     * Returns a copy of the current symbol table buffer.
@@ -103,22 +111,12 @@
     */
   QList < SymbolRecord > copyCurrentSymbolTable ();
 
-  void
-  updateHistoryModel ();
-
-  QStringListModel *
-  historyModel ();
-
-  /**
-    * Updates the current symbol table with new data
-    * from octave.
-    */
-  void
-  fetchSymbolTable ();
+  void updateHistoryModel ();
+  QStringListModel *historyModel ();
+  void emitSymbolTableChanged() { emit symbolTableChanged(); }
 
 signals:
-  void
-  symbolTableChanged ();
+  void symbolTableChanged ();
 
 private:
   OctaveLink ();