diff --git a/doc/opengl_primitives.png b/doc/opengl_primitives.png
deleted file mode 100644
index 1121812ad648f4cff422bffb0e2592d21b17406b..0000000000000000000000000000000000000000
Binary files a/doc/opengl_primitives.png and /dev/null differ
diff --git a/idl/gepetto/viewer/graphical-interface.idl b/idl/gepetto/viewer/graphical-interface.idl
index 609856d053572fe7f3ec01e28624320d5950c546..06a8fc75ce75df6dd0f2303683f5ce99e640f1f2 100644
--- a/idl/gepetto/viewer/graphical-interface.idl
+++ b/idl/gepetto/viewer/graphical-interface.idl
@@ -182,7 +182,7 @@ typedef sequence<Transform> TransformSeq;
     boolean setCurvePoints(in string curveName, in PositionSeq pos) raises (Error);
 
     /// \param mode The list of possible GL modes is provided in
-    ///             WindowsManager::setCurveMode.
+    ///             graphics::WindowsManager::setCurveMode.
     ///             From the GL modes, remove "GL_" and put it lower case.
     boolean setCurveMode (in string curveName, in string mode) raises (Error);
 
diff --git a/include/gepetto/gui/bodytreewidget.hh b/include/gepetto/gui/bodytreewidget.hh
index be9c6f9ef31ef0dff233f598ad8eef698ad6609a..a75411935fd1e5f9fc9ef3e17ea9f53de7fed44e 100644
--- a/include/gepetto/gui/bodytreewidget.hh
+++ b/include/gepetto/gui/bodytreewidget.hh
@@ -17,23 +17,6 @@
 #ifndef GEPETTO_GUI_BODYTREEWIDGET_HH
 #define GEPETTO_GUI_BODYTREEWIDGET_HH
 
-// This does not work because of qt meta-object compiler
-#define GEPETTO_GUI_BODYTREE_DECL_FEATURE(func, ArgType) \
-  public slots: \
-    void func (ArgType arg)
-#define GEPETTO_GUI_BODYTREE_IMPL_FEATURE(func, ArgType, OutType, WindowsManagerFunc) \
-  void BodyTreeWidget::func (ArgType arg) { \
-    WindowsManagerPtr_t wsm = MainWindow::instance()->osg(); \
-    foreach (const QModelIndex& index, view_->selectionModel ()->selectedIndexes ()) { \
-      const BodyTreeItem *item = dynamic_cast <const BodyTreeItem*> \
-        (model_->itemFromIndex (index)); \
-      if (item) wsm->WindowsManagerFunc (item->node()->getID(), \
-                                         convertTo<OutType>::from(arg)); \
-      else \
-        qDebug() << model_->itemFromIndex(index)->text() << "is not a BodyTreeItem"; \
-    } \
-  }
-
 #include <QWidget>
 #include <QTreeView>
 #include <QToolBox>
@@ -58,15 +41,11 @@ namespace gepetto {
 
       /// Init the widget.
       /// \param view tree view to display.
-      /// \param toolBox menu in the window
-      void init(QTreeView *view, QToolBox* toolBox);
+      /// \param propertyArea menu in the window
+      void init(QTreeView *view, QWidget *propertyArea);
 
       virtual ~BodyTreeWidget () {}
 
-      /// Display the value in the slider.
-      /// \param alpha alpha value to convert
-      void changeAlphaValue(const float& alpha);
-
       /// Get the body tree view.
       QTreeView* view ();
 
@@ -95,26 +74,6 @@ namespace gepetto {
       /// Get selected bodies
       QList<BodyTreeItem*> selectedBodies() const;
 
-      /// Set the transparency of currently selected body.
-      /// \param value value of the slider to convert
-      void setTransparency(int value);
-
-      /// Set the visibility mode of currently selected body.
-      /// \param arg visibility mode
-      void setVisibilityMode (QString arg);
-
-      /// Set the wireframe mode of currently selected body.
-      /// \param arg wireframe mode
-      void setWireFrameMode (QString arg);
-
-      /// Set the color of currently selected body.
-      /// \param color new color of the body
-      void setColor (QColor color);
-
-      /// Set the scale of currently selected body.
-      /// \param scale new scale of the body
-      void setScale (int scale);
-
       /// \}
 
     protected slots:
@@ -132,10 +91,12 @@ namespace gepetto {
       /// is updated.
       void handleSelectionEvent (const SelectionEvent* event);
 
+      void updatePropertyArea (BodyTreeItem* item);
+
       QTreeView* view_;
       QStandardItemModel* model_;
       WindowsManagerPtr_t osg_;
-      QToolBox* toolBox_;
+      QWidget* propertyArea_;
     };
   }
 }
diff --git a/include/gepetto/gui/dialog/pluginmanagerdialog.hh b/include/gepetto/gui/dialog/pluginmanagerdialog.hh
index fb5cf22558a8e03a68d86722fb65318ebfef1877..07bd30ab2dad5f274f7a8334aa553c65f1109fd2 100644
--- a/include/gepetto/gui/dialog/pluginmanagerdialog.hh
+++ b/include/gepetto/gui/dialog/pluginmanagerdialog.hh
@@ -67,12 +67,21 @@ namespace gepetto {
 
         void clearPlugins ();
 
+        bool declarePyPlugin (const QString& name);
+
+        bool loadPyPlugin (const QString& name);
+
+        bool unloadPyPlugin (const QString& name);
+
+        void clearPyPlugins ();
+
       private:
         template <typename Interface>
           static const Interface* const_instance_cast (const QPluginLoader* pl);
 
         QMap <QString, QPluginLoader*> plugins_;
         static QList <QDir> pluginDirs_;
+        QMap <QString, QString> pyplugins_;
     };
 
     class PluginManagerDialog : public QDialog
diff --git a/include/gepetto/gui/fwd.hh b/include/gepetto/gui/fwd.hh
index 1f08e99a8f587ca55d6ac0129ce933315f6eeffe..4b6c73bf3bd55280d6acee6cba602b81f3a969d1 100644
--- a/include/gepetto/gui/fwd.hh
+++ b/include/gepetto/gui/fwd.hh
@@ -17,6 +17,8 @@
 #ifndef GEPETTO_GUI_FWD_HH
 #define GEPETTO_GUI_FWD_HH
 
+#include <vector>
+
 #include <gepetto/viewer/macros.h>
 #include <gepetto/gui/config-dep.hh>
 
@@ -27,6 +29,7 @@ namespace gepetto {
     class PickHandler;
     class BodyTreeWidget;
     class BodyTreeItem;
+    typedef std::vector<BodyTreeItem*> BodyTreeItems_t;
     class ShortcutFactory;
     class SelectionHandler;
     class SelectionEvent;
diff --git a/include/gepetto/gui/tree-item.hh b/include/gepetto/gui/tree-item.hh
index af0cc5a58e70601a1c295e45365b729f8250ff3d..4380129ff5b887306ea71022e50ef7a0d9556a46 100644
--- a/include/gepetto/gui/tree-item.hh
+++ b/include/gepetto/gui/tree-item.hh
@@ -36,6 +36,7 @@ namespace gepetto {
 
       public:
         BodyTreeItem (QObject* parent, graphics::NodePtr_t node);
+        void initialize();
 
         virtual QStandardItem* clone () const;
 
@@ -49,7 +50,12 @@ namespace gepetto {
 
         void setParentGroup (const std::string& parent);
 
-        virtual ~BodyTreeItem() {};
+        QWidget* propertyEditors () const
+        {
+          return propertyEditors_;
+        }
+
+        virtual ~BodyTreeItem();
 
       public:
         void attachToWindow (unsigned int windowID);
@@ -64,12 +70,24 @@ namespace gepetto {
         void deleteLandmark ();
         QString text () const { return QStandardItem::text(); }
 
+    signals:
+        void requestInitialize();
+    private slots:
+        void doInitialize();
+
+        void setBoolProperty (bool value) const;
+        void setIntProperty (int value) const;
+        void setStringProperty (const QString& value) const;
+        void setFloatProperty (const double& value) const;
+        void setColorProperty (const QColor& value) const;
+
       private:
+        template <typename T> void setProperty(const QObject* sender, const T& value) const;
+
         graphics::NodePtr_t node_;
         std::string parentGroup_;
 
-        QSignalMapper vmMapper_;
-        QSignalMapper vizMapper_;
+        QWidget* propertyEditors_;
 
         friend class VisibilityItem;
     };
diff --git a/include/gepetto/gui/ui/mainwindow.ui b/include/gepetto/gui/ui/mainwindow.ui
index 5fafe64aa9fac7900688789b1ddc309af7a3aa32..605eaeda6fb82aa3d98b9a74c39716386f534507 100644
--- a/include/gepetto/gui/ui/mainwindow.ui
+++ b/include/gepetto/gui/ui/mainwindow.ui
@@ -37,7 +37,6 @@
    <property name="styleSheet">
     <string notr="true">image: url(:/img/gepetto.png);</string>
    </property>
-   <layout class="QVBoxLayout" name="verticalLayout_5"/>
   </widget>
   <widget class="QMenuBar" name="menuBar">
    <property name="geometry">
@@ -45,7 +44,7 @@
      <x>0</x>
      <y>0</y>
      <width>754</width>
-     <height>20</height>
+     <height>27</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuFile">
@@ -146,38 +145,15 @@
         <property name="widgetResizable">
          <bool>true</bool>
         </property>
-        <widget class="QWidget" name="scrollAreaWidgetContents">
+        <widget class="QWidget" name="propertyArea">
          <property name="geometry">
           <rect>
            <x>0</x>
            <y>0</y>
-           <width>254</width>
-           <height>127</height>
+           <width>252</width>
+           <height>133</height>
           </rect>
          </property>
-         <layout class="QVBoxLayout" name="verticalLayout_2">
-          <item>
-           <widget class="QToolBox" name="toolBox">
-            <property name="currentIndex">
-             <number>0</number>
-            </property>
-            <widget class="QWidget" name="Info">
-             <property name="geometry">
-              <rect>
-               <x>0</x>
-               <y>0</y>
-               <width>238</width>
-               <height>83</height>
-              </rect>
-             </property>
-             <attribute name="label">
-              <string>Transparency</string>
-             </attribute>
-             <layout class="QHBoxLayout" name="horizontalLayout"/>
-            </widget>
-           </widget>
-          </item>
-         </layout>
         </widget>
        </widget>
       </widget>
diff --git a/include/gepetto/gui/windows-manager.hh b/include/gepetto/gui/windows-manager.hh
index 0abaded93fd0f1c33c8abde9e0e2223f0bbb8659..0870fb5f3417c915a9235a4e9a64340f7cfd0e25 100644
--- a/include/gepetto/gui/windows-manager.hh
+++ b/include/gepetto/gui/windows-manager.hh
@@ -57,6 +57,8 @@ namespace gepetto {
         bool removeFromGroup (const std::string& nodeName, const std::string& groupName);
         bool deleteNode (const std::string& nodeName, bool all);
 
+        BodyTreeItems_t bodyTreeItems (const std::string& name) const;
+
         public slots:
           int createWindow(QString windowName);
       protected:
@@ -66,7 +68,6 @@ namespace gepetto {
         virtual void addGroup(const std::string& groupName, GroupNodePtr_t group, GroupNodePtr_t parent);
 
       private:
-        typedef std::vector<BodyTreeItem*> BodyTreeItems_t;
         typedef std::pair<BodyTreeItems_t, bool> BodyTreeItemsAndGroup_t;
         typedef std::map<std::string, BodyTreeItemsAndGroup_t> BodyTreeItemMap_t;
         BodyTreeWidget* bodyTree_;
diff --git a/include/gepetto/viewer/corba/windows-manager.hh b/include/gepetto/viewer/corba/windows-manager.hh
index a2de9af3f2647d93e9a31a63b8ebc584f0775984..09fb091f5cd2228b899c69e31fc0c8c85a42d755 100644
--- a/include/gepetto/viewer/corba/windows-manager.hh
+++ b/include/gepetto/viewer/corba/windows-manager.hh
@@ -181,7 +181,7 @@ namespace graphics {
       
             virtual bool setCurvePoints(const std::string& curveName, const Vec3ArrayPtr_t& pos);
 
-            /// \image html opengl_primitives.png
+            /// \param mode See LeafNodeLine::setMode for possible values
             virtual bool setCurveMode (const std::string& curveName, const GLenum mode);
             virtual bool setCurvePointsSubset (const std::string& curveName, const int first, const std::size_t count);
             virtual bool setCurveLineWidth (const std::string& curveName, const float& width);
diff --git a/plugins/pyqcustomplot/decorator.hh b/plugins/pyqcustomplot/decorator.hh
index b2ef2341bf087abbad4144c0621ade4491bdebf5..5cc8ce48561524b1188a6f4feed16ae0f41681d7 100644
--- a/plugins/pyqcustomplot/decorator.hh
+++ b/plugins/pyqcustomplot/decorator.hh
@@ -121,6 +121,10 @@ class QCustomPlotDecorator : public QObject
     {
       g->addData(keys,values);
     }
+    void addData (QCPGraph* g, const double &key, const double &value)
+    {
+      g->addData(key,value);
+    }
     void clearData (QCPGraph* o) { o->clearData (); }
     /// \}
 
diff --git a/src/gui/bodytreewidget.cc b/src/gui/bodytreewidget.cc
index dd62091282543ac2cf1063d4951affbed557e992..785f4f18d27093fd677684ebb1d5e3ac968a9cc8 100644
--- a/src/gui/bodytreewidget.cc
+++ b/src/gui/bodytreewidget.cc
@@ -29,65 +29,14 @@
 #include <QHBoxLayout>
 #include <QApplication>
 
-static void addSelector (QToolBox* tb, QString title, QStringList display, QStringList command,
-                         QObject* receiver, const char* slot) {
-  QWidget* newW = new QWidget();
-  newW->setObjectName(title);
-  QSignalMapper* mapper = new QSignalMapper (tb);
-  QHBoxLayout* layout = new QHBoxLayout(newW);
-  layout->setSpacing(6);
-  layout->setContentsMargins(11, 11, 11, 11);
-  layout->setObjectName(title + "_layout");
-  for (int i = 0; i < display.size(); ++i) {
-      QPushButton* button = new QPushButton(display[i], newW);
-      button->setObjectName(title + "_button_" + display[i]);
-      layout->addWidget (button);
-      mapper->setMapping(button, command[i]);
-      QObject::connect (button, SIGNAL(clicked(bool)), mapper, SLOT(map()));
-    }
-  receiver->connect (mapper, SIGNAL(mapped(QString)), slot);
-  tb->addItem(newW, title);
-}
-
-static void addColorSelector (QToolBox* tb, QString title, QObject* receiver, const char* slot) {
-  QWidget* newW = new QWidget();
-  newW->setObjectName(title);
-  QHBoxLayout* layout = new QHBoxLayout();
-  newW->setLayout(layout);
-  layout->setSpacing(6);
-  layout->setContentsMargins(11, 11, 11, 11);
-  layout->setObjectName(title + "_layout");
-  QPushButton* button = new QPushButton("Select color", newW);
-  button->setObjectName(title + "_buttonSelect");
-  layout->addWidget (button);
-
-  QColorDialog* colorDialog = new QColorDialog(newW);
-  colorDialog->setObjectName(title + "_colorDialog");
-  colorDialog->setOption(QColorDialog::ShowAlphaChannel, true);
-
-  colorDialog->connect(button, SIGNAL(clicked()), SLOT(open()));
-  receiver->connect (colorDialog, SIGNAL(colorSelected(QColor)), slot);
-  tb->addItem(newW, title);
-}
-
-static void addSlider (QToolBox* tb, QString title, QObject* receiver, const char* slot) {
-    QSlider* slider = new QSlider (Qt::Horizontal);
-    slider->setMinimum(0);
-    slider->setMaximum(100);
-    slider->setObjectName(title);
-
-  receiver->connect (slider, SIGNAL(valueChanged(int)), slot);
-  tb->addItem(slider, title);
-}
-
 namespace gepetto {
   namespace gui {
-    void BodyTreeWidget::init(QTreeView* view, QToolBox *toolBox)
+    void BodyTreeWidget::init(QTreeView* view, QWidget *propertyArea)
     {
       MainWindow* main = MainWindow::instance();
       osg_ = main->osg();
       view_ = view;
-      toolBox_ = toolBox;
+      propertyArea_ = propertyArea;
       model_  = new QStandardItemModel (this);
       view_->setModel(model_);
       view_->setSelectionMode(QAbstractItemView::ExtendedSelection);
@@ -97,18 +46,10 @@ namespace gepetto {
           SIGNAL (currentChanged(QModelIndex,QModelIndex)),
           SLOT (currentChanged(QModelIndex,QModelIndex)));
 
-      toolBox_->removeItem(0);
-      addSlider(toolBox_, "Transparency", this, SLOT(setTransparency(int)));
-      addSelector (toolBox_, "Visibility",
-                   QStringList () << "On" << "Always on top" << "Off",
-                   QStringList () << "ON" << "ALWAYS_ON_TOP" << "OFF",
-                   this, SLOT(setVisibilityMode(QString)));
-      addSelector (toolBox_, "Wireframe mode",
-                   QStringList () << "Fill" << "Both" << "Wireframe",
-                   QStringList () << "FILL" << "FILL_AND_WIREFRAME" << "WIREFRAME",
-                   this, SLOT(setWireFrameMode(QString)));
-      addColorSelector(toolBox_, "Color", this, SLOT(setColor(QColor)));
+/*
       addSlider(toolBox_, "Scale", this, SLOT(setScale(int)));
+*/
+      propertyArea_->setLayout (new QVBoxLayout);
     }
 
     QTreeView* BodyTreeWidget::view ()
@@ -118,24 +59,19 @@ namespace gepetto {
 
     void BodyTreeWidget::selectBodyByName(const QString bodyName)
     {
-      QList<QStandardItem*> matches;
-      if (!bodyName.isEmpty() && !bodyName.isNull()) {
-        matches = model_->findItems(bodyName, Qt::MatchFixedString
-            | Qt::MatchCaseSensitive
-            | Qt::MatchRecursive);
-      }
-      if (matches.empty()) {
-        qDebug () << "Body" << bodyName << "not found.";
-        view_->clearSelection();
-      } else {
-        view_->setCurrentIndex(matches.first()->index());
-      }
+      qDebug () << "Use std::string instead of QString";
+      return selectBodyByName (bodyName.toStdString());
     }
 
     void BodyTreeWidget::selectBodyByName (const std::string& bodyName)
     {
-      qDebug () << "Use QString instead of std::string";
-      return selectBodyByName (QString::fromStdString (bodyName));
+      BodyTreeItems_t bodies = osg_->bodyTreeItems (bodyName);
+      if (bodies.empty()) {
+        qDebug () << "Body" << bodyName.c_str() << "not found.";
+        view_->clearSelection();
+      } else {
+        view_->setCurrentIndex(bodies[0]->index());
+      }
     }
 
     void BodyTreeWidget::handleSelectionEvent (const SelectionEvent* event)
@@ -143,23 +79,25 @@ namespace gepetto {
       disconnect (view_->selectionModel(),
           SIGNAL (currentChanged(QModelIndex,QModelIndex)),
           this, SLOT (currentChanged(QModelIndex,QModelIndex)));
+      BodyTreeItem* item = NULL;
       if (event->node()) {
-        QList<QStandardItem*> matches;
-        matches = model_->findItems(event->nodeName(), Qt::MatchFixedString
-                                      | Qt::MatchCaseSensitive
-                                      | Qt::MatchRecursive);
+        BodyTreeItems_t matches = osg_->bodyTreeItems(event->node()->getID());
+
         if (matches.empty())
           view_->clearSelection();
         else {
+          item = matches[0];
           if (event->modKey() == Qt::ControlModifier)
-            view_->selectionModel()->setCurrentIndex
-                (matches.first()->index(),
+            view_->selectionModel()->setCurrentIndex (item->index(),
                  QItemSelectionModel::Toggle);
           else
-            view_->selectionModel()->select(matches.first()->index(), QItemSelectionModel::ClearAndSelect);
+            view_->selectionModel()->select          (item->index(),
+                QItemSelectionModel::ClearAndSelect);
+          view_->scrollTo (matches[0]->index());
         }
       } else
         view_->clearSelection();
+      updatePropertyArea(item);
       connect (view_->selectionModel(),
           SIGNAL (currentChanged(QModelIndex,QModelIndex)),
           SLOT (currentChanged(QModelIndex,QModelIndex)));
@@ -177,6 +115,19 @@ namespace gepetto {
       event->done();
     }
 
+    void BodyTreeWidget::updatePropertyArea (BodyTreeItem* item)
+    {
+      QLayoutItem *child;
+      while ((child = propertyArea_->layout()->takeAt(0)) != 0) {
+        if (child->widget() != NULL) {
+          child->widget()->setParent(NULL);
+        }
+      }
+      if (item != NULL) {
+        propertyArea_->layout()->addWidget(item->propertyEditors());
+      }
+    }
+
     void BodyTreeWidget::currentChanged (const QModelIndex &current,
         const QModelIndex &/*previous*/)
     {
@@ -188,6 +139,7 @@ namespace gepetto {
           qobject_cast <const QStandardItemModel*>
           (view_->model())->itemFromIndex(current)
          );
+      updatePropertyArea(item);
       if (item) {
         SelectionEvent *event = new SelectionEvent(SelectionEvent::FromBodyTree, item->node(), QApplication::keyboardModifiers());
         emitBodySelected(event);
@@ -223,18 +175,5 @@ namespace gepetto {
           contextMenu.exec(view_->mapToGlobal(pos));
         }
     }
-
-    void BodyTreeWidget::changeAlphaValue(const float& alpha)
-    {
-        QSlider *tr = qobject_cast<QSlider *>(toolBox_->widget(0));
-
-        tr->setValue((int)alpha * 100);
-    }
-
-    GEPETTO_GUI_BODYTREE_IMPL_FEATURE (setTransparency, int, int, setAlpha)
-    GEPETTO_GUI_BODYTREE_IMPL_FEATURE (setVisibilityMode, QString, std::string, setVisibility)
-    GEPETTO_GUI_BODYTREE_IMPL_FEATURE (setWireFrameMode, QString, std::string, setWireFrameMode)
-    GEPETTO_GUI_BODYTREE_IMPL_FEATURE (setColor, QColor, WindowsManager::Color_t, setColor)
-    GEPETTO_GUI_BODYTREE_IMPL_FEATURE (setScale, int, int, setScale)
   }
 }
diff --git a/src/gui/dialog/pluginmanagerdialog.cc b/src/gui/dialog/pluginmanagerdialog.cc
index 9d9d688f30ea82497cbe8e881f1d5d4914bb4f5b..822c7a84f16ab01da2469aa22238fc895ea10c8e 100644
--- a/src/gui/dialog/pluginmanagerdialog.cc
+++ b/src/gui/dialog/pluginmanagerdialog.cc
@@ -22,6 +22,7 @@
 
 #include "gepetto/gui/plugin-interface.hh"
 #include "gepetto/gui/mainwindow.hh"
+#include "gepetto/gui/pythonwidget.hh"
 
 #include <iostream>
 
@@ -144,6 +145,69 @@ namespace gepetto {
       }
     }
 
+    bool PluginManager::declarePyPlugin(const QString &name)
+    {
+      if (!pyplugins_.contains(name)) {
+        if (name.endsWith (".py")) {
+          QFileInfo fi (name);
+          QString moduleName = fi.baseName();
+          QString script;
+          if (fi.isAbsolute()) script = name;
+          else script = QDir::currentPath() + QDir::separator() + name;
+          pyplugins_[moduleName] = script;
+        } else
+          pyplugins_[name] = name;
+        return true;
+      }
+      qDebug () << "Python plugin" << name << "already declared.";
+      return false;
+    }
+
+    bool PluginManager::loadPyPlugin(const QString &name)
+    {
+      if (!pyplugins_.contains(name)) {
+        qDebug () << "Python plugin" << name << "not declared.";
+        return false;
+      }
+      MainWindow* main = MainWindow::instance();
+      const QString& pyfile = pyplugins_[name];
+
+#if GEPETTO_GUI_HAS_PYTHONQT
+      PythonWidget* pw = main->pythonWidget();
+      if (pyfile.endsWith (".py")) {
+        qDebug() << "Loading" << pyfile << "into module" << name;
+        pw->loadScriptPlugin (name, pyfile);
+      } else
+        pw->loadModulePlugin (name);
+      return true;
+#else
+      main->logError ("gepetto-viewer-corba was compiled without GEPETTO_GUI_HAS_"
+          "PYTHONQT flag. Cannot not load Python plugin " + name);
+      return false;
+#endif
+    }
+
+    bool PluginManager::unloadPyPlugin(const QString &name)
+    {
+      MainWindow* main = MainWindow::instance();
+#if GEPETTO_GUI_HAS_PYTHONQT
+      PythonWidget* pw = main->pythonWidget();
+      pw->unloadModulePlugin(name);
+      return true;
+#else
+      main->logError ("gepetto-viewer-corba was compiled without GEPETTO_GUI_HAS_"
+          "PYTHONQT flag. Cannot not unload Python plugin " + name);
+      return false;
+#endif
+    }
+
+    void PluginManager::clearPyPlugins()
+    {
+      foreach (QString p, pyplugins_.keys()) {
+        unloadPyPlugin(p);
+      }
+    }
+
     PluginManagerDialog::PluginManagerDialog(PluginManager *pm, QWidget *parent) :
       QDialog(parent),
       ui_(new ::Ui::PluginManagerDialog),
@@ -240,8 +304,10 @@ namespace gepetto {
                 version = "";
         if (p.value ()->isLoaded ()) {
           PluginInterface* pi = qobject_cast <PluginInterface*> (p.value()->instance());
-          name = pi->name();
-          // version = pi->version();
+          if (pi) {
+            name = pi->name();
+            // version = pi->version();
+          }
         }
         QIcon icon = pm_->icon (p.value());
 
diff --git a/src/gui/mainwindow.cc b/src/gui/mainwindow.cc
index 6907c93faa561edc4940babb12bbe2345b6aca08..dfb3676824fe71e4586abfa10fc29ddcea04dc56 100644
--- a/src/gui/mainwindow.cc
+++ b/src/gui/mainwindow.cc
@@ -61,7 +61,7 @@ namespace gepetto {
 
       // Setup the body tree view
       osgViewerManagers_ = WindowsManager::create(ui_->bodyTreeContent);
-      ui_->bodyTreeContent->init(ui_->bodyTree, ui_->toolBox);
+      ui_->bodyTreeContent->init(ui_->bodyTree, ui_->propertyArea);
 
       if (settings_->startGepettoCorbaServer) {
         osgServer_ = new CorbaServer (new ViewerServerProcess (
diff --git a/src/gui/tree-item.cc b/src/gui/tree-item.cc
index 47031ec53421aedd71e98788d9cce7124a877074..e6717701e3dde8468f48921f1d2ddda4ba2b86f6 100644
--- a/src/gui/tree-item.cc
+++ b/src/gui/tree-item.cc
@@ -17,6 +17,9 @@
 #include "gepetto/gui/tree-item.hh"
 
 #include <QDebug>
+#include <QLineEdit>
+#include <QColorDialog>
+#include <QFormLayout>
 
 #include <gepetto/viewer/group-node.h>
 
@@ -26,19 +29,196 @@
 
 namespace gepetto {
   namespace gui {
+    QWidget* boolPropertyEditor (BodyTreeItem* bti, const graphics::PropertyPtr_t prop)
+    {
+      QCheckBox* cb = new QCheckBox;
+      bool value;
+      /* bool success = */ prop->get(value);
+      cb->setChecked(value);
+      if (prop->hasWriteAccess())
+        bti->connect(cb, SIGNAL(toggled(bool)), SLOT(setBoolProperty(bool)));
+      else
+        cb->setEnabled(false);
+      return cb;
+    }
+
+    QWidget* enumPropertyEditor (BodyTreeItem* bti, const graphics::PropertyPtr_t prop)
+    {
+      const graphics::EnumProperty::Ptr_t enumProp = boost::dynamic_pointer_cast<graphics::EnumProperty> (prop);
+      const graphics::MetaEnum* enumMeta = enumProp->metaEnum();
+
+      QComboBox* cb = new QComboBox;
+      int value;
+      /* bool success = */ enumProp->get(value);
+      std::size_t indexSelected = 0;
+      for (std::size_t i = 0; i < enumMeta->values.size(); ++i)
+      {
+        cb->addItem(enumMeta->names[i].c_str(), enumMeta->values[i]);
+        if (value == enumMeta->values[i]) indexSelected = i;
+      }
+      cb->setCurrentIndex((int)indexSelected);
+      if (prop->hasWriteAccess())
+        bti->connect(cb, SIGNAL(currentIndexChanged(int)), SLOT(setIntProperty(int)));
+      else
+        cb->setEnabled(false);
+      return cb;
+    }
+
+    QWidget* stringPropertyEditor (BodyTreeItem* bti, const graphics::PropertyPtr_t prop)
+    {
+      QLineEdit* le = new QLineEdit;
+      std::string value;
+      /* bool success = */ prop->get(value);
+      le->setText(QString::fromStdString(value));
+      if (prop->hasWriteAccess())
+        bti->connect(le, SIGNAL(textChanged(QString)), SLOT(setStringProperty(QString)));
+      else
+        le->setReadOnly(true);
+      return le;
+    }
+
+    QWidget* floatPropertyEditor (BodyTreeItem* bti, const graphics::PropertyPtr_t prop)
+    {
+      QDoubleSpinBox* dsb = new QDoubleSpinBox;
+      float value;
+      /* bool success = */ prop->get(value);
+      dsb->setValue(value);
+      if (prop->hasWriteAccess())
+        bti->connect(dsb, SIGNAL(valueChanged(double)), SLOT(setFloatProperty(double)));
+      else
+        dsb->setEnabled(false);
+      return dsb;
+    }
+
+    QWidget* colorPropertyEditor (BodyTreeItem* bti, const graphics::PropertyPtr_t prop)
+    {
+      if (!prop->hasWriteAccess()) return NULL;
+      osgVector4 value;
+      /* bool success = */ prop->get(value);
+      QColor color;
+      color.setRgbF((qreal)value[0],(qreal)value[1],(qreal)value[2],(qreal)value[3]);
+
+      QPushButton* button = new QPushButton("Select color");
+      // Set icon for current color value
+
+      /// Color dialog should be opened in a different place
+      QColorDialog* colorDialog = new QColorDialog(color, MainWindow::instance());
+      colorDialog->setOption(QColorDialog::ShowAlphaChannel, true);
+
+      colorDialog->setProperty("propertyName", QString::fromStdString(prop->name()));
+      colorDialog->connect(button, SIGNAL(clicked()), SLOT(open()));
+      bti->connect (colorDialog, SIGNAL(colorSelected(QColor)), SLOT(setColorProperty(QColor)));
+
+      return button;
+    }
+
     BodyTreeItem::BodyTreeItem(QObject *parent, graphics::NodePtr_t node) :
       QObject (parent),
-      QStandardItem (QString (node->getID().c_str())),
-      node_ (node),
-      vmMapper_ (),
-      vizMapper_ ()
+      QStandardItem (QString::fromStdString (node->getID().substr(node->getID().find_last_of("/") + 1))),
+      node_ (node)
     {
       setEditable(false);
-      connect (&vmMapper_, SIGNAL (mapped (QString)), SLOT(setViewingMode(QString)));
-      connect (&vizMapper_, SIGNAL (mapped (QString)), SLOT(setVisibilityMode(QString)));
-      
-      const std::string & name = node->getID();
-      QStandardItem::setText(name.substr(name.find_last_of("/") + 1).c_str());
+    }
+
+    void BodyTreeItem::initialize ()
+    {
+      connect(this, SIGNAL(requestInitialize()), SLOT(doInitialize()));
+      emit requestInitialize();
+    }
+
+    void BodyTreeItem::doInitialize ()
+    {
+      propertyEditors_ = new QWidget();
+      BodyTreeWidget* bt = MainWindow::instance()->bodyTree();
+      if (propertyEditors_->thread() != bt->thread())
+        propertyEditors_->moveToThread(bt->thread());
+      QFormLayout* l = new QFormLayout(propertyEditors_);
+
+      l->addRow("Node name:", new QLabel (node_->getID().c_str()));
+
+      const graphics::PropertyMap_t& props = node_->properties();
+      for (graphics::PropertyMap_t::const_iterator _prop = props.begin();
+           _prop != props.end(); ++_prop)
+      {
+        const graphics::PropertyPtr_t prop = _prop->second;
+        if (!prop->hasReadAccess()) continue;
+
+        QString name = _prop->first.c_str();
+        QWidget* field = NULL;
+        if (prop->type() == "enum") {
+          field = enumPropertyEditor(this, prop);
+        } else if (prop->type() == "bool") {
+          field = boolPropertyEditor(this, prop);
+        } else if (prop->type() == "string") {
+          field = stringPropertyEditor(this, prop);
+        } else if (prop->type() == "float") {
+          field = floatPropertyEditor(this, prop);
+        } else if (prop->type() == "osgVector4") {
+          if (name.contains ("color", Qt::CaseInsensitive)) {
+            field = colorPropertyEditor (this, prop);
+          } else {
+            field = NULL;
+          }
+        }
+        if (field != NULL) {
+          field->setProperty("propertyName", name);
+          l->addRow(name + ':', field);
+        } else {
+          qDebug() << "Unhandled property" << name << "of type" << prop->type().c_str() << ".";
+        }
+      }
+      disconnect(SIGNAL(requestInitialize()));
+    }
+
+    template <typename T>
+    void BodyTreeItem::setProperty (const QObject* sender, const T& value) const
+    {
+      if (sender != NULL) {
+        QVariant nameVariant = sender->property("propertyName");
+        if (nameVariant.isValid()) {
+          std::string name = nameVariant.toString().toStdString();
+          boost::mutex::scoped_lock lock (MainWindow::instance()->osg()->osgFrameMutex());
+          node_->setProperty<T>(name, value);
+        } else {
+          qDebug() << "Sender has no property propertyName" << sender;
+        }
+      }
+    }
+
+    void BodyTreeItem::setBoolProperty (bool value) const
+    {
+      setProperty (QObject::sender(), value);
+    }
+
+    void BodyTreeItem::setIntProperty (int value) const
+    {
+      setProperty (QObject::sender(), value);
+    }
+
+    void BodyTreeItem::setStringProperty (const QString& value) const
+    {
+      setProperty (QObject::sender(), value.toStdString());
+    }
+
+    void BodyTreeItem::setFloatProperty (const double& value) const
+    {
+      setProperty (QObject::sender(), float(value));
+    }
+
+    void BodyTreeItem::setColorProperty (const QColor& value) const
+    {
+      osgVector4 c (
+          (float)value.redF(),
+          (float)value.greenF(),
+          (float)value.blueF(),
+          (float)value.alphaF());
+      setProperty (QObject::sender(), c);
+    }
+
+    BodyTreeItem::~BodyTreeItem()
+    {
+      if (propertyEditors_->parent() != NULL)
+        delete propertyEditors_;
     }
 
     QStandardItem* BodyTreeItem::clone() const
@@ -68,28 +248,6 @@ namespace gepetto {
         QAction* rfg = contextMenu->addAction (tr("Remove from group"));
         connect (rfg, SIGNAL (triggered()), SLOT (removeFromGroup ()));
       }
-      /// Viewing mode
-      QMenu* viewmode = contextMenu->addMenu(tr("Viewing mode"));
-      QAction* f  = viewmode->addAction ("Fill");
-      QAction* w  = viewmode->addAction ("Wireframe");
-      QAction* fw = viewmode->addAction ("Fill and Wireframe");
-      vmMapper_.setMapping (f , QString ("FILL"));
-      vmMapper_.setMapping (w , QString ("WIREFRAME"));
-      vmMapper_.setMapping (fw, QString ("FILL_AND_WIREFRAME"));
-      connect (f , SIGNAL(triggered()), &vmMapper_, SLOT (map()));
-      connect (w , SIGNAL(triggered()), &vmMapper_, SLOT (map()));
-      connect (fw, SIGNAL(triggered()), &vmMapper_, SLOT (map()));
-      /// Visibility mode
-      QMenu* vizmode = contextMenu->addMenu(tr("Visibility mode"));
-      QAction* on  = vizmode->addAction ("On");
-      QAction* aot = vizmode->addAction ("Always on top");
-      QAction* off = vizmode->addAction ("Off");
-      vizMapper_.setMapping (on , QString ("ON"));
-      vizMapper_.setMapping (aot, QString ("ALWAYS_ON_TOP"));
-      vizMapper_.setMapping (off, QString ("OFF"));
-      connect (on , SIGNAL(triggered()), &vizMapper_, SLOT (map()));
-      connect (aot, SIGNAL(triggered()), &vizMapper_, SLOT (map()));
-      connect (off, SIGNAL(triggered()), &vizMapper_, SLOT (map()));
     }
 
     void BodyTreeItem::setParentGroup(const std::string &parent)
diff --git a/src/gui/windows-manager.cc b/src/gui/windows-manager.cc
index 7e1b0f0a285ac8a44abb7056e61306f3f7f6f93f..83a2d91922730eb89c2306537a1876b80be69167 100644
--- a/src/gui/windows-manager.cc
+++ b/src/gui/windows-manager.cc
@@ -73,6 +73,7 @@ namespace gepetto {
         nodeItemMap_[groupName].second = true;
         if (bti->thread() != bodyTree_->thread())
           bti->moveToThread(bodyTree_->thread());
+        bti->initialize();
         bodyTree_->model()->appendRow(bti);
       }
     }
@@ -87,6 +88,7 @@ namespace gepetto {
         bti->setParentGroup(groupName);
         if (bti->thread() != bodyTree_->thread())
           bti->moveToThread(bodyTree_->thread());
+        bti->initialize();
         groups[i]->appendRow(bti);
       }
     }
@@ -147,6 +149,14 @@ namespace gepetto {
       return ret;
     }
 
+    BodyTreeItems_t WindowsManager::bodyTreeItems (const std::string& name) const
+    {
+      BodyTreeItemMap_t::const_iterator _btis = nodeItemMap_.find(name);
+      if (_btis != nodeItemMap_.end())
+        return _btis->second.first;
+      return BodyTreeItems_t();
+    }
+
     void WindowsManager::deleteBodyItem(const std::string& nodeName)
     {
       BodyTreeItemMap_t::iterator _nodes = nodeItemMap_.find(nodeName);