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/src/gui/dialog/pluginmanagerdialog.cc b/src/gui/dialog/pluginmanagerdialog.cc
index aec53c54b89cda24a14ece00e57a7eabebfbc1ec..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),