From 46f2cf7aa39bda8301b22fcfddd43daf0dc13770 Mon Sep 17 00:00:00 2001
From: Leonardo Florez-Valencia <florez-l@javeriana.edu.co>
Date: Thu, 14 Jan 2016 17:21:57 -0500
Subject: [PATCH] Now it's broken :-(

---
 appli/CMakeLists.txt                          |   6 +-
 ...ineEditor.cxx => App_cpPipelineEditor.cxx} |  42 +-
 ...ipelineEditor.h => App_cpPipelineEditor.h} |  16 +-
 ...elineEditor.ui => App_cpPipelineEditor.ui} |  12 +-
 appli/cpPipelineEditor/CMakeLists.txt         | 129 ++--
 appli/cpPipelineEditor/QNEBlock.h             | 111 ----
 appli/cpPipelineEditor/QNEConnection.h        |  75 ---
 appli/cpPipelineEditor/QNEPort.h              | 215 -------
 appli/cpPipelineEditor/QNodesEditor.cxx       | 596 ------------------
 appli/cpPipelineEditor/QNodesEditor.h         | 158 -----
 appli/cpPipelineEditor/main.cxx               |   4 +-
 lib/CMakeLists.txt                            |   6 +
 lib/cpExtensions/DataStructures/Graph.h       |  79 ++-
 lib/cpExtensions/DataStructures/Graph.hxx     |  66 +-
 .../cpPipelineEditor/Block.cxx                | 145 +----
 lib/cpPipelineEditor/Block.h                  |  80 +++
 lib/cpPipelineEditor/CMakeLists.txt           |  50 ++
 .../cpPipelineEditor/Canvas.cxx               |  60 +-
 .../cpPipelineEditor/Canvas.h                 |  27 +-
 .../cpPipelineEditor/Connection.cxx           |  58 +-
 lib/cpPipelineEditor/Connection.h             |  50 ++
 lib/cpPipelineEditor/Editor.cxx               | 510 +++++++++++++++
 lib/cpPipelineEditor/Editor.h                 | 111 ++++
 .../cpPipelineEditor/Port.cxx                 | 122 ++--
 lib/cpPipelineEditor/Port.h                   | 190 ++++++
 lib/cpPlugins/Interface/Parameters.cxx        | 117 ++++
 lib/cpPlugins/Interface/Parameters.h          |   5 +
 lib/cpPlugins/Interface/Workspace.cxx         | 230 ++++---
 lib/cpPlugins/Interface/Workspace.h           |  75 ++-
 lib/cpPlugins/Interface/WorkspaceIO.cxx       | 152 ++---
 30 files changed, 1736 insertions(+), 1761 deletions(-)
 rename appli/cpPipelineEditor/{cpPipelineEditor.cxx => App_cpPipelineEditor.cxx} (88%)
 rename appli/cpPipelineEditor/{cpPipelineEditor.h => App_cpPipelineEditor.h} (73%)
 rename appli/cpPipelineEditor/{cpPipelineEditor.ui => App_cpPipelineEditor.ui} (94%)
 delete mode 100644 appli/cpPipelineEditor/QNEBlock.h
 delete mode 100644 appli/cpPipelineEditor/QNEConnection.h
 delete mode 100644 appli/cpPipelineEditor/QNEPort.h
 delete mode 100644 appli/cpPipelineEditor/QNodesEditor.cxx
 delete mode 100644 appli/cpPipelineEditor/QNodesEditor.h
 rename appli/cpPipelineEditor/QNEBlock.cxx => lib/cpPipelineEditor/Block.cxx (54%)
 create mode 100644 lib/cpPipelineEditor/Block.h
 create mode 100644 lib/cpPipelineEditor/CMakeLists.txt
 rename appli/cpPipelineEditor/QNodesEditorCanvas.cxx => lib/cpPipelineEditor/Canvas.cxx (86%)
 rename appli/cpPipelineEditor/QNodesEditorCanvas.h => lib/cpPipelineEditor/Canvas.h (57%)
 rename appli/cpPipelineEditor/QNEConnection.cxx => lib/cpPipelineEditor/Connection.cxx (51%)
 create mode 100644 lib/cpPipelineEditor/Connection.h
 create mode 100644 lib/cpPipelineEditor/Editor.cxx
 create mode 100644 lib/cpPipelineEditor/Editor.h
 rename appli/cpPipelineEditor/QNEPort.cxx => lib/cpPipelineEditor/Port.cxx (62%)
 create mode 100644 lib/cpPipelineEditor/Port.h

diff --git a/appli/CMakeLists.txt b/appli/CMakeLists.txt
index 6e0414c..1f50ec7 100644
--- a/appli/CMakeLists.txt
+++ b/appli/CMakeLists.txt
@@ -6,8 +6,12 @@ IF(BUILD_EXAMPLES)
   SUBDIRS(
     examples
     ImageMPR
-    cpPipelineEditor
     )
+  IF(USE_QT4)
+    SUBDIRS(
+      cpPipelineEditor
+      )
+  ENDIF(USE_QT4)
 ENDIF(BUILD_EXAMPLES)
 
 ## eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/cpPipelineEditor.cxx b/appli/cpPipelineEditor/App_cpPipelineEditor.cxx
similarity index 88%
rename from appli/cpPipelineEditor/cpPipelineEditor.cxx
rename to appli/cpPipelineEditor/App_cpPipelineEditor.cxx
index 6bda2a7..8c0a155 100644
--- a/appli/cpPipelineEditor/cpPipelineEditor.cxx
+++ b/appli/cpPipelineEditor/App_cpPipelineEditor.cxx
@@ -1,31 +1,31 @@
-#include "cpPipelineEditor.h"
-#include "ui_cpPipelineEditor.h"
+#include "App_cpPipelineEditor.h"
+#include "ui_App_cpPipelineEditor.h"
 
-#include "QNodesEditor.h"
+#include <cpPipelineEditor/Editor.h>
 
 #include <QFileDialog>
 #include <QMessageBox>
 #include <cpPlugins/Interface/Workspace.h>
 
 // -------------------------------------------------------------------------
-#define cpPipelineEditor_ConnectAction( ACTION )        \
+#define App_cpPipelineEditor_ConnectAction( ACTION )    \
   QObject::connect(                                     \
     this->m_UI->Action##ACTION, SIGNAL( triggered( ) ), \
     this, SLOT( _Action##ACTION( ) )                    \
     )
 
 // -------------------------------------------------------------------------
-#define cpPipelineEditor_ConnectButton( BUTTON )        \
+#define App_cpPipelineEditor_ConnectButton( BUTTON )    \
   QObject::connect(                                     \
     this->m_UI->Button##BUTTON, SIGNAL( clicked( ) ),   \
     this, SLOT( _Button##BUTTON( ) )                    \
     )
 
 // -------------------------------------------------------------------------
-cpPipelineEditor::
-cpPipelineEditor( int argc, char* argv[], QWidget* parent )
+App_cpPipelineEditor::
+App_cpPipelineEditor( int argc, char* argv[], QWidget* parent )
   : QMainWindow( parent ),
-    m_UI( new Ui::cpPipelineEditor ),
+    m_UI( new Ui::App_cpPipelineEditor ),
     m_Workspace( NULL )
 {
   this->m_UI->setupUi( this );
@@ -50,19 +50,19 @@ cpPipelineEditor( int argc, char* argv[], QWidget* parent )
 
   // Create an empty workspace
   this->m_Workspace = new cpPlugins::Interface::Workspace( );
-  this->m_Workspace->SetInterface( this->m_Plugins );
+  this->m_Workspace->SetPlugins( this->m_Plugins );
   this->m_UI->Canvas->editor( )->setWorkspace( this->m_Workspace );
 
   // Connect actions to slots
-  cpPipelineEditor_ConnectButton( LoadPluginsFile );
-  cpPipelineEditor_ConnectButton( LoadPluginsPath );
-  cpPipelineEditor_ConnectAction( OpenWorkspace );
-  cpPipelineEditor_ConnectAction( SaveWorkspace );
+  App_cpPipelineEditor_ConnectButton( LoadPluginsFile );
+  App_cpPipelineEditor_ConnectButton( LoadPluginsPath );
+  App_cpPipelineEditor_ConnectAction( OpenWorkspace );
+  App_cpPipelineEditor_ConnectAction( SaveWorkspace );
 }
 
 // -------------------------------------------------------------------------
-cpPipelineEditor::
-~cpPipelineEditor( )
+App_cpPipelineEditor::
+~App_cpPipelineEditor( )
 {
   delete this->m_UI;
   if( this->m_Workspace != NULL )
@@ -71,7 +71,7 @@ cpPipelineEditor::
 }
 
 // -------------------------------------------------------------------------
-void cpPipelineEditor::
+void App_cpPipelineEditor::
 _UpdateLoadedPlugins( )
 {
   auto& classes = this->m_Plugins->GetClasses( );
@@ -131,7 +131,7 @@ _UpdateLoadedPlugins( )
 }
 
 // -------------------------------------------------------------------------
-void cpPipelineEditor::
+void App_cpPipelineEditor::
 _ButtonLoadPluginsFile( )
 {
   QFileDialog dlg( this );
@@ -168,7 +168,7 @@ _ButtonLoadPluginsFile( )
 }
 
 // -------------------------------------------------------------------------
-void cpPipelineEditor::
+void App_cpPipelineEditor::
 _ButtonLoadPluginsPath( )
 {
   QFileDialog dlg( this );
@@ -191,7 +191,7 @@ _ButtonLoadPluginsPath( )
 }
 
 // -------------------------------------------------------------------------
-void cpPipelineEditor::
+void App_cpPipelineEditor::
 _ActionOpenWorkspace( )
 {
   QFileDialog dlg( this );
@@ -208,7 +208,7 @@ _ActionOpenWorkspace( )
   if( this->m_Workspace != NULL )
     delete this->m_Workspace;
   this->m_Workspace = new cpPlugins::Interface::Workspace( );
-  this->m_Workspace->SetInterface( this->m_Plugins );
+  this->m_Workspace->SetPlugins( this->m_Plugins );
   std::string err = this->m_Workspace->LoadWorkspace( fname );
   if( err != "" )
   {
@@ -225,7 +225,7 @@ _ActionOpenWorkspace( )
 }
 
 // -------------------------------------------------------------------------
-void cpPipelineEditor::
+void App_cpPipelineEditor::
 _ActionSaveWorkspace( )
 {
   if( this->m_Workspace == NULL )
diff --git a/appli/cpPipelineEditor/cpPipelineEditor.h b/appli/cpPipelineEditor/App_cpPipelineEditor.h
similarity index 73%
rename from appli/cpPipelineEditor/cpPipelineEditor.h
rename to appli/cpPipelineEditor/App_cpPipelineEditor.h
index 8117778..9d0d99a 100644
--- a/appli/cpPipelineEditor/cpPipelineEditor.h
+++ b/appli/cpPipelineEditor/App_cpPipelineEditor.h
@@ -1,5 +1,5 @@
-#ifndef __CPPIPELINEEDITOR__H__
-#define __CPPIPELINEEDITOR__H__
+#ifndef __APP_CPPIPELINEEDITOR__H__
+#define __APP_CPPIPELINEEDITOR__H__
 
 // Qt stuff
 #include <QMainWindow>
@@ -7,7 +7,7 @@
 // -------------------------------------------------------------------------
 namespace Ui
 {
-  class cpPipelineEditor;
+  class App_cpPipelineEditor;
 }
 
 namespace cpPlugins
@@ -21,21 +21,21 @@ namespace cpPlugins
 
 /**
  */
-class cpPipelineEditor
+class App_cpPipelineEditor
   : public QMainWindow
 {
   Q_OBJECT;
 
 public:
-  typedef cpPipelineEditor Self;
+  typedef App_cpPipelineEditor Self;
   typedef QMainWindow      Superclass;
 
 public:
-  explicit cpPipelineEditor(
+  explicit App_cpPipelineEditor(
     int argc, char* argv[],
     QWidget* parent = 0
     );
-  virtual ~cpPipelineEditor( );
+  virtual ~App_cpPipelineEditor( );
 
 protected:
   void _UpdateLoadedPlugins( );
@@ -47,7 +47,7 @@ protected slots:
   void _ActionSaveWorkspace( );
 
 private:
-  Ui::cpPipelineEditor* m_UI;
+  Ui::App_cpPipelineEditor* m_UI;
   cpPlugins::Interface::Workspace* m_Workspace;
   cpPlugins::Interface::Interface* m_Plugins;
 };
diff --git a/appli/cpPipelineEditor/cpPipelineEditor.ui b/appli/cpPipelineEditor/App_cpPipelineEditor.ui
similarity index 94%
rename from appli/cpPipelineEditor/cpPipelineEditor.ui
rename to appli/cpPipelineEditor/App_cpPipelineEditor.ui
index 5fa8eb0..faf9217 100644
--- a/appli/cpPipelineEditor/cpPipelineEditor.ui
+++ b/appli/cpPipelineEditor/App_cpPipelineEditor.ui
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
- <class>cpPipelineEditor</class>
- <widget class="QMainWindow" name="cpPipelineEditor">
+ <class>App_cpPipelineEditor</class>
+ <widget class="QMainWindow" name="App_cpPipelineEditor">
   <property name="geometry">
    <rect>
     <x>0</x>
@@ -122,7 +122,7 @@
         </item>
        </layout>
       </widget>
-      <widget class="PipelineEditor::QNodesEditorCanvas" name="Canvas" native="true">
+      <widget class="cpPipelineEditor::Canvas" name="Canvas" native="true">
        <property name="minimumSize">
         <size>
          <width>500</width>
@@ -182,9 +182,9 @@
  </widget>
  <customwidgets>
   <customwidget>
-   <class>PipelineEditor::QNodesEditorCanvas</class>
+   <class>cpPipelineEditor::Canvas</class>
    <extends>QWidget</extends>
-   <header>QNodesEditorCanvas.h</header>
+   <header>cpPipelineEditor/Canvas.h</header>
    <container>1</container>
   </customwidget>
  </customwidgets>
@@ -193,7 +193,7 @@
   <connection>
    <sender>ActionExit</sender>
    <signal>triggered()</signal>
-   <receiver>cpPipelineEditor</receiver>
+   <receiver>App_cpPipelineEditor</receiver>
    <slot>close()</slot>
    <hints>
     <hint type="sourcelabel">
diff --git a/appli/cpPipelineEditor/CMakeLists.txt b/appli/cpPipelineEditor/CMakeLists.txt
index 14874c5..8201381 100644
--- a/appli/cpPipelineEditor/CMakeLists.txt
+++ b/appli/cpPipelineEditor/CMakeLists.txt
@@ -1,79 +1,50 @@
-IF(USE_QT4)
-  SET(App_NAME "cpPipelineEditor")
-
-  ## ====================================================
-  ## = Source code, user interafaces and resources here =
-  ## ====================================================
-
-  SET(App_SOURCE_DIR "${PROJECT_SOURCE_DIR}/appli/${App_NAME}")
-  SET(App_BINARY_DIR "${PROJECT_BINARY_DIR}/appli/${App_NAME}")
-
-  SET(
-    App_QT_SOURCES
-    QNEBlock.cxx
-    QNEConnection.cxx
-    QNEPort.cxx
-    QNodesEditor.cxx
-    QNodesEditorCanvas.cxx
-    #QNEMainWindow.cxx
-    #Edge.cxx
-    #GraphCanvas.cxx
-    #Node.cxx
-    cpPipelineEditor.cxx
-    )
-  SET(
-    App_SOURCES
-    main.cxx
-    )
-  SET(
-    App_QT_HEADERS
-    QNodesEditor.h
-    QNodesEditorCanvas.h
-    #QNEMainWindow.h
-    #GraphCanvas.h
-    cpPipelineEditor.h
-    )
-  SET(
-    App_HEADERS
-    )
-  FILE(GLOB App_QT_UI  "${App_SOURCE_DIR}/*.ui")
-  FILE(GLOB App_QT_RES "${App_SOURCE_DIR}/*.qrc")
-
-  ## =====================
-  ## = Compilation rules =
-  ## =====================
-  INCLUDE_DIRECTORIES(
-    ${App_SOURCE_DIR}
-    ${App_BINARY_DIR}
-    )
-
-  QT4_WRAP_UI(App_QT_UI_Headers ${App_QT_UI})
-  QT4_WRAP_CPP(App_QT_HEADERS_MOC_SOURCES ${App_QT_HEADERS})
-  QT4_ADD_RESOURCES(App_QT_RES_SOURCES ${App_QT_RES})
-
-  SET(GUI_TYPE "")
-  IF(WIN32)
-    SET(GUI_TYPE WIN32)
-  ENDIF(WIN32)
-  IF(APPLE)
-    SET(GUI_TYPE MACOSX_BUNDLE)
-  ENDIF(APPLE)
-
-  ADD_EXECUTABLE(
-    ${App_NAME}
-    ${GUI_TYPE}
-    ${App_QT_UI_Headers}
-    ${App_SOURCES}
-    ${App_QT_SOURCES}
-    ${App_QT_HEADERS_MOC_SOURCES}
-    ${App_QT_RES_SOURCES}
-    )
-  TARGET_LINK_LIBRARIES(
-    ${App_NAME}
-    ${QT_LIBRARIES}
-    cpExtensions
-    cpPlugins_Interface
-	)
-ENDIF(USE_QT4)
-
-## eof - $RCSfile$
+SET(App_NAME "App_cpPipelineEditor")
+SET(Dir_NAME "cpPipelineEditor")
+
+## ====================================================
+## = Source code, user interafaces and resources here =
+## ====================================================
+
+SET(App_SOURCE_DIR "${PROJECT_SOURCE_DIR}/appli/${Dir_NAME}")
+SET(App_BINARY_DIR "${PROJECT_BINARY_DIR}/appli/${Dir_NAME}")
+SET(App_QT_SOURCES App_cpPipelineEditor.cxx)
+SET(App_SOURCES    main.cxx)
+SET(App_QT_HEADERS App_cpPipelineEditor.h)
+FILE(GLOB App_QT_UI  "${App_SOURCE_DIR}/*.ui")
+FILE(GLOB App_QT_RES "${App_SOURCE_DIR}/*.qrc")
+
+## =====================
+## = Compilation rules =
+## =====================
+INCLUDE_DIRECTORIES(
+  ${App_SOURCE_DIR}
+  ${App_BINARY_DIR}
+  )
+
+QT4_WRAP_UI(App_QT_UI_Headers ${App_QT_UI})
+QT4_WRAP_CPP(App_QT_HEADERS_MOC_SOURCES ${App_QT_HEADERS})
+QT4_ADD_RESOURCES(App_QT_RES_SOURCES ${App_QT_RES})
+
+SET(GUI_TYPE "")
+IF(WIN32)
+  SET(GUI_TYPE WIN32)
+ENDIF(WIN32)
+IF(APPLE)
+  SET(GUI_TYPE MACOSX_BUNDLE)
+ENDIF(APPLE)
+
+ADD_EXECUTABLE(
+  ${App_NAME}
+  ${GUI_TYPE}
+  ${App_QT_UI_Headers}
+  ${App_SOURCES}
+  ${App_QT_SOURCES}
+  ${App_QT_HEADERS_MOC_SOURCES}
+  ${App_QT_RES_SOURCES}
+  )
+TARGET_LINK_LIBRARIES(
+  ${App_NAME}
+  cpPipelineEditor
+  )
+
+# ## eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNEBlock.h b/appli/cpPipelineEditor/QNEBlock.h
deleted file mode 100644
index 8e95ce0..0000000
--- a/appli/cpPipelineEditor/QNEBlock.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef __PIPELINEEDITOR__QNEBLOCK__H__
-#define __PIPELINEEDITOR__QNEBLOCK__H__
-
-#include <QGraphicsPathItem>
-#include <cpPlugins/Interface/ProcessObject.h>
-
-namespace PipelineEditor
-{
-  class QNEPort;
-  class QNENamePort;
-  class QNETypePort;
-  class QNEInputPort;
-  class QNEOutputPort;
-  class QNEConnection;
-
-  class QNEBlock
-    : public QGraphicsPathItem
-  {
-  public:
-    typedef QNEBlock          Self;
-    typedef QGraphicsPathItem Superclass;
-    typedef cpPlugins::Interface::ProcessObject TFilter;
-  
-  public:
-    enum { Type = QGraphicsItem::UserType + 6 };
-
-    QNEBlock(
-      TFilter* filter,
-      QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL
-      );
-    virtual ~QNEBlock( );
-
-    void setNamePort( const QString& txt );
-    QNEInputPort* addInputPort( const QString& txt );
-    QNEOutputPort* addOutputPort( const QString& txt );
-
-    bool extendInputPort( const QString& txt, QNEConnection* conn );
-    bool extendOutputPort( const QString& txt, QNEConnection* conn );
-
-    QNEInputPort* inputPort( const QString& txt );
-    QNEOutputPort* outputPort( const QString& txt );
-
-    QString namePort( ) const;
-    const QNEInputPort* inputPort( const QString& txt ) const;
-    const QNEOutputPort* outputPort( const QString& txt ) const;
-    const QNEConnection* extendedInputPort( const QString& txt ) const;
-    const QNEConnection* extendedOutputPort( const QString& txt ) const;
-
-    inline int type( ) const
-      { return( this->Type ); }
-
-    virtual void paint(
-      QPainter* painter,
-      const QStyleOptionGraphicsItem* option,
-      QWidget* widget
-      );
-    
-  protected:
-    QVariant itemChange( GraphicsItemChange change, const QVariant& value );
-    void _setTypePort( const QString& txt );
-    void _configPort( QNEPort* port );
-
-    virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent* evt );
-
-  private:
-    int m_HorzMargin;
-    int m_VertMargin;
-    int m_Width;
-    int m_Height;
-
-    QNENamePort* m_NamePort;
-    QNETypePort* m_TypePort;
-    std::map< std::string, QNEInputPort* >  m_InputPorts;
-    std::map< std::string, QNEOutputPort* > m_OutputPorts;
-    std::map< std::string, QNEConnection* > m_ExtOutputPorts;
-    std::map< std::string, QNEConnection* > m_ExtInputPorts;
-
-    TFilter::Pointer m_Filter;
-  };
-
-} // ecapseman
-
-#endif // __PIPELINEEDITOR__QNEBLOCK__H__
-
-// eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNEConnection.h b/appli/cpPipelineEditor/QNEConnection.h
deleted file mode 100644
index bbed7dd..0000000
--- a/appli/cpPipelineEditor/QNEConnection.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef __PIPELINEEDITOR__QNECONNECTION__H__
-#define __PIPELINEEDITOR__QNECONNECTION__H__
-
-#include <QGraphicsPathItem>
-
-namespace PipelineEditor
-{
-  class QNEInputPort;
-  class QNEOutputPort;
-
-  /**
-   */
-  class QNEConnection
-    : public QGraphicsPathItem
-  {
-  public:
-    typedef QNEConnection     Self;
-    typedef QGraphicsPathItem Superclass;
-
-  public:
-    enum { Type = QGraphicsItem::UserType + 5 };
-
-    QNEConnection( QGraphicsItem* parent = 0, QGraphicsScene* scene = 0 );
-    virtual ~QNEConnection( );
-
-    void setPos1( const QPointF& p );
-    void setPos2( const QPointF& p );
-    void setPort1( QNEOutputPort* p );
-    void setPort2( QNEInputPort* p );
-    void updatePosFromPorts( );
-    void updatePath( );
-    QNEOutputPort* port1( ) const;
-    QNEInputPort* port2( ) const;
-
-    inline int type( ) const
-      { return( this->Type ); }
-
-  private:
-    QPointF m_Pos1;
-    QPointF m_Pos2;
-    QNEOutputPort* m_Port1;
-    QNEInputPort*  m_Port2;
-  };
-
-} // ecapseman
-
-#endif // __PIPELINEEDITOR__QNECONNECTION__H__
-
-// eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNEPort.h b/appli/cpPipelineEditor/QNEPort.h
deleted file mode 100644
index e10af5e..0000000
--- a/appli/cpPipelineEditor/QNEPort.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef __PIPELINEEDITOR__QNEPORT__H__
-#define __PIPELINEEDITOR__QNEPORT__H__
-
-#include <QGraphicsPathItem>
-
-namespace PipelineEditor
-{
-  class QNEBlock;
-  class QNEConnection;
-
-  /**
-   */
-  class QNEPort
-    : public QGraphicsPathItem
-  {
-  public:
-    typedef QNEPort Self;
-    typedef QGraphicsPathItem Superclass;
-
-    enum { Type = QGraphicsItem::UserType + 1 };
-
-  public:
-    QNEPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
-    virtual ~QNEPort( );
-
-    void setBlock( QNEBlock* b );
-    inline QNEBlock* block( ) const
-      { return( this->m_Block ); }
-
-    virtual void setName( const QString& n );
-    virtual void setExtendedName( const QString& n );
-    inline QString name( ) const
-      { return( this->m_Label->toPlainText( ) ); }
-    inline QString extendedName( ) const
-      { return( this->m_ExtendedLabel->toPlainText( ) ); }
-
-    inline int radius( ) const
-      { return( this->m_Radius ); }
-
-    inline bool isExtended( ) const
-      { return( this->m_IsExtended ); }
-    virtual void setExtend( bool extend );
-
-    virtual bool isConnected( QNEPort* other ) = 0;
-    inline int type( ) const
-      { return( this->Type ); }
-
-    virtual void paint(
-      QPainter* painter,
-      const QStyleOptionGraphicsItem* option,
-      QWidget* widget
-      );
-
-  protected:
-    virtual void _updateLabels( ) { }
-
-  protected:
-    QNEBlock* m_Block;
-
-    int  m_Radius;
-    int  m_Margin;
-    bool m_IsExtended;
-
-    QGraphicsTextItem* m_Label;
-    QGraphicsTextItem* m_ExtendedLabel;
-  };
-
-  /**
-   */
-  class QNENamePort
-    : public QNEPort
-  {
-  public:
-    typedef QNENamePort Self;
-    typedef QNEPort     Superclass;
-
-    enum { Type = Superclass::Type + 1 };
-
-  public:
-    QNENamePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
-    virtual ~QNENamePort( );
-
-    virtual bool isConnected( QNEPort* other );
-    inline int type( ) const
-      { return( this->Type ); }
-
-  protected:
-    virtual void _updateLabels( );
-  };
-
-  /**
-   */
-  class QNETypePort
-    : public QNEPort
-  {
-  public:
-    typedef QNETypePort Self;
-    typedef QNEPort     Superclass;
-
-    enum { Type = Superclass::Type + 2 };
-
-  public:
-    QNETypePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
-    virtual ~QNETypePort( );
-
-    virtual bool isConnected( QNEPort* other );
-    inline int type( ) const
-      { return( this->Type ); }
-
-  protected:
-    virtual void _updateLabels( );
-  };
-
-  /**
-   */
-  class QNEInputPort
-    : public QNEPort
-  {
-  public:
-    typedef QNEInputPort Self;
-    typedef QNEPort      Superclass;
-
-    enum { Type = Superclass::Type + 3 };
-
-  public:
-    QNEInputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
-    virtual ~QNEInputPort( );
-
-    virtual void setExtend( bool extend );
-
-    virtual bool isConnected( QNEPort* other );
-    inline int type( ) const
-      { return( this->Type ); }
-
-    void setConnection( QNEConnection* c );
-    inline QNEConnection* connection( )
-      { return( this->m_Connection ); }
-    inline const QNEConnection* connection( ) const
-      { return( this->m_Connection ); }
-    inline bool hasConnection( ) const
-      { return( this->m_Connection != NULL ); }
-
-  protected:
-    QVariant itemChange( GraphicsItemChange change, const QVariant& value );
-    virtual void _updateLabels( );
-
-  protected:
-    QNEConnection* m_Connection;
-  };
-
-  /**
-   */
-  class QNEOutputPort
-    : public QNEPort
-  {
-  public:
-    typedef QNEOutputPort Self;
-    typedef QNEPort       Superclass;
-
-    enum { Type = Superclass::Type + 4 };
-
-  public:
-    QNEOutputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
-    virtual ~QNEOutputPort( );
-
-    virtual void setExtend( bool extend );
-
-    virtual bool isConnected( QNEPort* other );
-    inline int type( ) const
-      { return( this->Type ); }
-
-    inline QVector< QNEConnection* >& connections( )
-      { return( this->m_Connections ); }
-    inline const QVector< QNEConnection* >& connections( ) const
-      { return( this->m_Connections ); }
-
-  protected:
-    QVariant itemChange( GraphicsItemChange change, const QVariant& value );
-    virtual void _updateLabels( );
-
-  protected:
-    QVector< QNEConnection* > m_Connections;
-  };
-
-} // ecapseman
-
-#endif // __PIPELINEEDITOR__QNEPORT__H__
-
-// eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNodesEditor.cxx b/appli/cpPipelineEditor/QNodesEditor.cxx
deleted file mode 100644
index 46508ca..0000000
--- a/appli/cpPipelineEditor/QNodesEditor.cxx
+++ /dev/null
@@ -1,596 +0,0 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "QNodesEditor.h"
-
-#include <QGraphicsScene>
-#include <QEvent>
-#include <QGraphicsSceneContextMenuEvent>
-#include <QGraphicsSceneDragDropEvent>
-#include <QGraphicsSceneHelpEvent>
-#include <QGraphicsSceneHoverEvent>
-#include <QGraphicsSceneMouseEvent>
-#include <QGraphicsSceneMoveEvent>
-#include <QGraphicsSceneResizeEvent>
-#include <QGraphicsSceneWheelEvent>
-#include <QInputDialog>
-
-#include "QNEPort.h"
-#include "QNEConnection.h"
-#include "QNEBlock.h"
-
-// -------------------------------------------------------------------------
-#define PipelineEditor_QNodesEditor_Callback_SWITCH( E, e )             \
-  case QEvent::E:                                                       \
-  {                                                                     \
-    Q##E##Event* evt = dynamic_cast< Q##E##Event* >( e );               \
-    if( evt != NULL )                                                   \
-      this->_##E##_cbk( evt );                                          \
-  }                                                                     \
-  break
-
-// -------------------------------------------------------------------------
-#define PipelineEditor_QNodesEditor_Callback_CODE( E )                  \
-  void PipelineEditor::QNodesEditor::_##E##_cbk( Q##E##Event* evt )
-
-// -------------------------------------------------------------------------
-PipelineEditor::QNodesEditor::
-QNodesEditor( QObject* parent )
- : Superclass( parent ),
-   m_Conn( NULL ),
-   m_Workspace( NULL )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor::QNodesEditor::
-~QNodesEditor( )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor::QNodesEditor::
-TWorkspace* PipelineEditor::QNodesEditor::
-workspace( )
-{
-  return( this->m_Workspace );
-}
-
-// -------------------------------------------------------------------------
-const PipelineEditor::QNodesEditor::
-TWorkspace* PipelineEditor::QNodesEditor::
-workspace( ) const
-{
-  return( this->m_Workspace );
-}
-
-// -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditor::
-setWorkspace( TWorkspace* ws )
-{
-  this->m_Workspace = ws;
-  this->m_Graph = TGraph::New( );
-
-  // Create blocks
-  auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
-  auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
-  for( ; vIt != vIt_end; ++vIt )
-  {
-    this->_CreateBlock(
-      dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),
-      QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) )
-      );
-
-  } // rof
-
-  // Add edges
-  auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
-  auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
-  for( ; rIt != rIt_end; ++rIt )
-  {
-    QNEBlock* orig = this->m_Graph->GetVertex( rIt->first );
-    auto cIt = rIt->second.begin( );
-    for( ; cIt != rIt->second.end( ); ++cIt )
-    {
-      QNEBlock* dest = this->m_Graph->GetVertex( cIt->first );
-      auto eIt = cIt->second.begin( );
-      for( ; eIt != cIt->second.end( ); ++eIt )
-      {
-        QNEOutputPort* op = orig->outputPort( eIt->first.c_str( ) );
-        QNEInputPort* ip = dest->inputPort( eIt->second.c_str( ) );
-        if( op == NULL || ip == NULL )
-          continue;
-
-        QNEConnection* c = new QNEConnection( 0, this->m_Scene );
-        c->setPort1( op );
-        c->setPort2( ip );
-        c->updatePosFromPorts( );
-        c->updatePath( );
-        this->m_Graph->AddConnection( rIt->first, cIt->first, c );
-
-      } // rof
-
-    } // rof
-
-  } // rof
-}
-
-// -------------------------------------------------------------------------
-std::string PipelineEditor::QNodesEditor::
-createFilter( const std::string& filter, const QPointF& pnt )
-{
-  std::string name = filter;
-  while( this->m_Workspace->HasFilter( name ) )
-    name += std::string( "_" );
-  if( this->m_Workspace->CreateFilter( filter, name ) )
-  {
-    this->_CreateBlock( this->m_Workspace->GetFilter( name ), pnt );
-    return( name );
-  }
-  else
-    return( "" );
-}
-
-// -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditor::
-install( QGraphicsScene* s )
-{
-  s->installEventFilter( this );
-  this->m_Scene = s;
-}
-
-// -------------------------------------------------------------------------
-QGraphicsItem* PipelineEditor::QNodesEditor::
-itemAt( const QPointF& pos )
-{
-  QList< QGraphicsItem* > items =
-    this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );
-
-  foreach( QGraphicsItem* item, items )
-    if( item->type( ) > QGraphicsItem::UserType )
-      return( item );
-  return( NULL );
-}
-
-// -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditor::
-_CreateBlock( TFilter* f, const QPointF& pnt )
-{
-  if( f == NULL )
-    return;
-
-  // Add block
-  QNEBlock* b = new QNEBlock( f, 0, this->m_Scene );
-  b->setPos( pnt );
-
-  // Keep a trace of this visual graph
-  this->m_Graph->SetVertex( f->GetName( ), b );
-}
-
-// -------------------------------------------------------------------------
-/* TODO
-void PipelineEditor::QNodesEditor::
-_DoubleClick( QGraphicsSceneMouseEvent* evt, QGraphicsItem* item )
-{
-  switch( evt->button( ) )
-  {
-  case Qt::LeftButton:
-  {
-    QNEBlock* block = dynamic_cast< QNEBlock* >( item );
-    QNEPort* port = dynamic_cast< QNEPort* >( item );
-    QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
-
-    if( block != NULL )
-    {
-      QString old_name = block->namePort( );
-      bool ok;
-      QString new_name =
-        QInputDialog::getText(
-          dynamic_cast< QWidget* >( this->parent( ) ),
-          "Change filter name",
-          "Filter name:",
-          QLineEdit::Normal,
-          old_name,
-          &ok
-          );
-      if( ok && !new_name.isEmpty( ) && old_name != new_name )
-      {
-        ok = this->m_Graph->RenameVertex(
-          old_name.toStdString( ),
-          new_name.toStdString( )
-          );
-        if( ok )
-        {
-          block->setNamePort( new_name );
-          this->m_Workspace->GetGraph( )->RenameVertex(
-            old_name.toStdString( ),
-            new_name.toStdString( )
-            );
-
-        } // fi
-
-      } // fi
-    }
-    else if( port != NULL )
-    {
-    }
-    else if( conn != NULL )
-    {
-    } // fi
-  }
-  break;
-     case Qt::RightButton:
-     {
-     }
-     break;
-     case Qt::MiddleButton:
-     {
-     }
-     break;
-  default:
-    break;
-  } // hctiws
-}
-  */
-
-// -------------------------------------------------------------------------
-bool PipelineEditor::QNodesEditor::
-eventFilter( QObject* o, QEvent* e )
-{
-  // Event type
-  switch( int( e->type( ) ) )
-  {
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneContextMenu, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDragEnter, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDragLeave, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDragMove, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneDrop, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHelp, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHoverEnter, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHoverLeave, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneHoverMove, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMouseDoubleClick, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMouseMove, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMousePress, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMouseRelease, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneMove, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneResize, e );
-    PipelineEditor_QNodesEditor_Callback_SWITCH( GraphicsSceneWheel, e );
-  default:
-    break;
-  } // hctiws
-
-  return( this->Superclass::eventFilter( o, e ) );
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneContextMenu )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDragEnter )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDragLeave )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDragMove )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneDrop )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHelp )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHoverEnter )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHoverLeave )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneHoverMove )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMouseDoubleClick )
-{
-  QGraphicsItem* item = this->itemAt( evt->scenePos( ) );
-  if( item == NULL )
-    return;
-
-  switch( evt->button( ) )
-  {
-  case Qt::LeftButton:
-  {
-    QNEBlock* block = dynamic_cast< QNEBlock* >( item );
-    QNEPort* port = dynamic_cast< QNEPort* >( item );
-    QNEConnection* conn = dynamic_cast< QNEConnection* >( item );
-
-    if( block != NULL )
-    {
-      QString old_name = block->namePort( );
-      bool ok;
-      QString new_name =
-        QInputDialog::getText(
-          dynamic_cast< QWidget* >( this->parent( ) ),
-          "Change filter name",
-          "Filter name:",
-          QLineEdit::Normal,
-          old_name,
-          &ok
-          );
-      if( ok && !new_name.isEmpty( ) && old_name != new_name )
-      {
-        ok = this->m_Graph->RenameVertex(
-          old_name.toStdString( ),
-          new_name.toStdString( )
-          );
-        if( ok )
-        {
-          block->setNamePort( new_name );
-          this->m_Workspace->GetGraph( )->RenameVertex(
-            old_name.toStdString( ),
-            new_name.toStdString( )
-            );
-
-        } // fi
-
-      } // fi
-    }
-    else if( port != NULL )
-    {
-      if( evt->modifiers( ) == Qt::ControlModifier )
-      {
-        port->setExtend( !( port->isExtended( ) ) );
-        QNEInputPort* in_port = dynamic_cast< QNEInputPort* >( port );
-        QNEOutputPort* out_port = dynamic_cast< QNEOutputPort* >( port );
-        if( port->isExtended( ) )
-        {
-          if( in_port != NULL )
-          {
-            this->m_Workspace->AddInputPort(
-              in_port->extendedName( ).toStdString( ),
-              in_port->block( )->namePort( ).toStdString( ),
-              in_port->name( ).toStdString( )
-              );
-          }
-          else if( out_port != NULL )
-          {
-          } // fi
-        }
-        else
-        {
-          if( in_port != NULL )
-          {
-          }
-          else if( out_port != NULL )
-          {
-          } // fi
-
-        } // fi
-        this->m_Scene->update( );
-      }
-      else if( evt->modifiers( ) == Qt::NoModifier )
-      {
-        if( port->isExtended( ) )
-        {
-          QString old_name = port->extendedName( );
-          bool ok;
-          QString new_name =
-            QInputDialog::getText(
-              dynamic_cast< QWidget* >( this->parent( ) ),
-              "Change filter name",
-              "Filter name:",
-              QLineEdit::Normal,
-              old_name,
-              &ok
-              );
-          if( ok && !new_name.isEmpty( ) && old_name != new_name )
-          {
-            // TODO: port->setExtendedName( new_name );
-            /* TODO
-               ok = this->m_Graph->RenameVertex(
-               old_name.toStdString( ),
-               new_name.toStdString( )
-               );
-               if( ok )
-               {
-               block->setNamePort( new_name );
-               this->m_Workspace->GetGraph( )->RenameVertex(
-               old_name.toStdString( ),
-               new_name.toStdString( )
-               );
-
-               } // fi
-            */
-          } // fi
-
-        } // fi
-
-      } // fi
-    }
-    else if( conn != NULL )
-    {
-    } // fi
-  }
-  break;
-  /* TODO:
-     case Qt::RightButton:
-     {
-     }
-     break;
-     case Qt::MiddleButton:
-     {
-     }
-     break;
-  */
-  default:
-    break;
-  } // hctiws
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMouseMove )
-{
-  if( this->m_Conn != NULL )
-  {
-    if( this->m_Conn->port1( ) == NULL )
-      this->m_Conn->setPos1( evt->scenePos( ) );
-    else if( this->m_Conn->port2( ) == NULL )
-      this->m_Conn->setPos2( evt->scenePos( ) );
-    this->m_Conn->updatePath( );
-
-  } // fi
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMousePress )
-{
-  QNEInputPort* in_port =
-    dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
-  QNEOutputPort* out_port =
-    dynamic_cast< QNEOutputPort* >( this->itemAt( evt->scenePos( ) ) );
-  if( in_port == NULL && out_port == NULL )
-    return;
-
-  switch( evt->button( ) )
-  {
-  case Qt::LeftButton:
-  {
-    if( out_port != NULL )
-    {
-      if( out_port->block( ) != NULL )
-      {
-        // Start new connection
-        this->m_Conn = new QNEConnection( 0, this->m_Scene );
-        this->m_Conn->setPort1( out_port );
-        this->m_Conn->setPos1( out_port->scenePos( ) );
-        this->m_Conn->setPos2( evt->scenePos( ) );
-        this->m_Conn->updatePosFromPorts( );
-        this->m_Conn->updatePath( );
-
-      } // fi
-
-    } // fi
-  }
-  break;
-  default:
-    break;
-
-  } // hctiws
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMouseRelease )
-{
-  if( this->m_Conn == NULL )
-    return;
-
-  switch( evt->button( ) )
-  {
-  case Qt::LeftButton:
-  {
-    QNEInputPort* port2 =
-      dynamic_cast< QNEInputPort* >( this->itemAt( evt->scenePos( ) ) );
-    if( port2 != NULL )
-    {
-      QNEOutputPort* port1 =
-        dynamic_cast< QNEOutputPort* >( this->m_Conn->port1( ) );
-      if( port1 != NULL )
-      {
-        if(
-          port1->block( ) != port2->block( ) &&
-          !port2->hasConnection( ) &&
-          !port1->isConnected( port2 ) &&
-          !port2->isExtended( )
-          )
-        {
-          this->m_Conn->setPos2( port2->scenePos( ) );
-          this->m_Conn->setPort2( port2 );
-          this->m_Conn->updatePosFromPorts( );
-          this->m_Conn->updatePath( );
-
-          this->m_Workspace->Connect(
-            port1->block( )->namePort( ).toStdString( ),
-            port2->block( )->namePort( ).toStdString( ),
-            port1->name( ).toStdString( ),
-            port2->name( ).toStdString( )
-            );
-          this->m_Graph->AddConnection(
-            port1->block( )->namePort( ).toStdString( ),
-            port2->block( )->namePort( ).toStdString( ),
-            this->m_Conn
-            );
-        }
-        else
-          delete this->m_Conn;
-      }
-      else
-        delete this->m_Conn;
-    }
-    else
-      delete this->m_Conn;
-    this->m_Conn = NULL;
-  }
-  break;
-  default:
-    break;
-  } // hctisw
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneMove )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneResize )
-{
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor_QNodesEditor_Callback_CODE( GraphicsSceneWheel )
-{
-}
-
-// eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNodesEditor.h b/appli/cpPipelineEditor/QNodesEditor.h
deleted file mode 100644
index d148bbe..0000000
--- a/appli/cpPipelineEditor/QNodesEditor.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef __PIPELINEEDITOR__QNODESEDITOR__H__
-#define __PIPELINEEDITOR__QNODESEDITOR__H__
-
-#include <QObject>
-#include <QPointF>
-#include <cpExtensions/DataStructures/Graph.h>
-#include <cpPlugins/Interface/Workspace.h>
-
-class QGraphicsScene;
-class QGraphicsSceneMouseEvent;
-class QGraphicsItem;
-class QGraphicsSceneContextMenuEvent;
-class QGraphicsSceneDragDropEvent;
-class QGraphicsSceneHelpEvent;
-class QGraphicsSceneHoverEvent;
-class QGraphicsSceneMouseEvent;
-class QGraphicsSceneMoveEvent;
-class QGraphicsSceneResizeEvent;
-class QGraphicsSceneWheelEvent;
-
-// -------------------------------------------------------------------------
-#define PipelineEditor_QNodesEditor_Callback_DCL( E )   \
-  void _##E##_cbk( Q##E##Event* e );
-
-namespace PipelineEditor
-{
-  class QNEConnection;
-  class QNEBlock;
-
-  /**
-   */
-  class QNodesEditor
-    : public QObject
-  {
-    Q_OBJECT;
-
-  public:
-    typedef QNodesEditor Self;
-    typedef QObject      Superclass;
-
-    typedef cpPlugins::Interface::Workspace TWorkspace;
-    typedef TWorkspace::TFilter             TFilter;
-    typedef
-      cpExtensions::DataStructures::
-      Graph< QNEBlock*, QNEConnection*, std::string > TGraph;
-
-  public:
-    explicit QNodesEditor( QObject* parent = 0 );
-    virtual ~QNodesEditor( );
-
-    TWorkspace* workspace( );
-    const TWorkspace* workspace( ) const;
-    void setWorkspace( TWorkspace* ws );
-
-    std::string createFilter(
-      const std::string& filter,
-      const QPointF& pnt = QPointF( qreal( 0 ), qreal( 0 ) )
-      );
-
-    void install( QGraphicsScene* s );
-    bool eventFilter( QObject* o, QEvent* e );
-
-  private:
-    QGraphicsItem* itemAt( const QPointF& pos );
-
-    inline void _CreateBlock( TFilter* f, const QPointF& pnt );
-
-  protected:
-    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragEnterEvent;
-    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragLeaveEvent;
-    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragMoveEvent;
-    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDropEvent;
-    typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverEnterEvent;
-    typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverMoveEvent;
-    typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverLeaveEvent;
-    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseDoubleClickEvent;
-    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseMoveEvent;
-    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMousePressEvent;
-    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseReleaseEvent;
-
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneContextMenu );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneDragEnter );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneDragLeave );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneDragMove );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneDrop );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneHelp );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneHoverEnter );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneHoverLeave );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneHoverMove );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneMouseDoubleClick );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneMouseMove );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneMousePress );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneMouseRelease );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneMove );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneResize );
-    PipelineEditor_QNodesEditor_Callback_DCL( GraphicsSceneWheel );
-
-  private:
-    QGraphicsScene* m_Scene;
-    QNEConnection* m_Conn;
-
-    TWorkspace* m_Workspace;
-    TGraph::Pointer m_Graph;
-  };
-
-} // ecapseman
-
-#endif // __PIPELINEEDITOR__QNODESEDITOR__H__
-
-// eof - $RCSfile$
-
-      /* TODO
-         case QEvent::GraphicsSceneContextMenu:
-         QGraphicsSceneContextMenuEvent* evt =
-         
-         case QEvent::GraphicsSceneDragEnter:
-         case QEvent::GraphicsSceneDragLeave:
-         case QEvent::GraphicsSceneDragMove:
-         case QEvent::GraphicsSceneDrop:
-         case QEvent::GraphicsSceneHelp:
-         case QEvent::GraphicsSceneHoverEnter:
-         case QEvent::GraphicsSceneHoverLeave:
-         case QEvent::GraphicsSceneHoverMove:
-         case QEvent::GraphicsSceneMouseDoubleClick:
-         case QEvent::GraphicsSceneMouseMove:
-         case QEvent::GraphicsSceneMousePress:
-         case QEvent::GraphicsSceneMouseRelease:
-         case QEvent::GraphicsSceneMove:
-         case QEvent::GraphicsSceneResize:
-         case QEvent::GraphicsSceneWheel:
-      */
-    
diff --git a/appli/cpPipelineEditor/main.cxx b/appli/cpPipelineEditor/main.cxx
index 3dfe464..52d821e 100644
--- a/appli/cpPipelineEditor/main.cxx
+++ b/appli/cpPipelineEditor/main.cxx
@@ -1,4 +1,4 @@
-#include "cpPipelineEditor.h"
+#include "App_cpPipelineEditor.h"
 #include <cstdlib>
 #include <QApplication>
 
@@ -6,7 +6,7 @@
 int main( int argc, char* argv[] )
 {
   QApplication a( argc, argv );
-  cpPipelineEditor w( argc, argv, NULL );
+  App_cpPipelineEditor w( argc, argv, NULL );
   w.show( );
 
   return( a.exec( ) );
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 05dcd2b..bc9f3fa 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -3,5 +3,11 @@ SUBDIRS(
   cpPlugins
   third_party
   )
+IF(USE_QT4)
+  SUBDIRS(
+    cpPipelineEditor
+    )
+ENDIF(USE_QT4)
+
 
 ## eof - $RCSfile$
diff --git a/lib/cpExtensions/DataStructures/Graph.h b/lib/cpExtensions/DataStructures/Graph.h
index 59679c8..db07f2e 100644
--- a/lib/cpExtensions/DataStructures/Graph.h
+++ b/lib/cpExtensions/DataStructures/Graph.h
@@ -11,7 +11,11 @@ namespace cpExtensions
 {
   namespace DataStructures
   {
-    /**
+    /** \brief A generic graph with templated index types.
+     *
+     *  @param V Vertex type.
+     *  @param C Cost type.
+     *  @param I Index type (it should be a strict weak ordering type).
      */
     template< class V, class C, class I = unsigned long >
     class Graph
@@ -27,29 +31,73 @@ namespace cpExtensions
       typedef C TCost;
       typedef I TIndex;
 
-      // Graph types
-      typedef std::map< I, V >          TVertices;
-      typedef std::vector< C >          TEdges;
-      typedef std::map< I, TEdges >     TMatrixRow;
-      typedef std::map< I, TMatrixRow > TMatrix;
+      // Base types
+      typedef std::map< TIndex, TVertex >    TVertices;
+      typedef std::vector< TCost >           TEdges;
+      typedef std::map< TIndex, TEdges >     TMatrixRow;
+      typedef std::map< TIndex, TMatrixRow > TMatrix;
 
     public:
       itkNewMacro( Self );
       itkTypeMacro( Graph, itk::LightObject );
 
     public:
+      /*! \brief Iterators over vertices.
+       *         These allow you to iterate over all of graph's vertices.
+       *
+       * Typical iteration should be done as:
+       *
+       *  TGraph g;
+       *  ...
+       *  TGraph::TVertices::[const_]iterator vIt = g.BeginVertices( );
+       *  for( ; vIt != g.EndVertices( ); ++vIt )
+       *  {
+       *    vIt->first;  --> this is the vertex's index <--
+       *    vIt->second; --> this is the vertex's value <--
+       *  }
+       */
       typename TVertices::iterator BeginVertices( );
       typename TVertices::iterator EndVertices( );
       typename TVertices::const_iterator BeginVertices( ) const;
       typename TVertices::const_iterator EndVertices( ) const;
 
+      /*! \brief Iterators over edges.
+       *         These allow you to iterate over all of graph's edges.
+       *
+       * Typical iteration should be done as:
+       *
+       *  TGraph g;
+       *  ...
+       *  TGraph::TMatrix::[const_]iterator mIt = g.BeginEdgesRows( );
+       *  for( ; mIt != g.EndEdgesRows( ); ++mIt )
+       *  {
+       *    mIt->first; --> this is the row index. <--
+       *    TGraph::TMatrixRow::[const_]iterator rIt = mIt->second.begin( );
+       *    for( ; rIt != mIt->second.end( ); ++rIt )
+       *    {
+       *      rIt->first;  --> this is the column index.
+       *      TGraph::TEdges::[const_]iterator eIt = rIt->second.begin( );
+       *      for( ; eIt != rIt->second.end( ); ++eIt )
+       *        *eIt; --> this is the cost between mIt->first and rIt->first
+       *    }
+       *  }
+       */
       typename TMatrix::iterator BeginEdgesRows( );
       typename TMatrix::iterator EndEdgetsRows( );
       typename TMatrix::const_iterator BeginEdgesRows( ) const;
       typename TMatrix::const_iterator EndEdgesRows( ) const;
 
+      /*! \brief Clear all vertices and edges.
+       */
       void Clear( );
 
+      /*! \brief Clear all edges.
+       */
+      void ClearEdges( );
+
+      /*! \brief Vertex manipulation methods.
+       *         Names are self-explanatory.
+       */
       bool HasVertexIndex( const I& index ) const;
       void SetVertex( const I& index, V& vertex );
       bool RenameVertex( const I& old_index, const I& new_index );
@@ -57,9 +105,22 @@ namespace cpExtensions
       V& GetVertex( const I& index );
       const V& GetVertex( const I& index ) const;
 
-      void AddConnection( const I& orig, const I& dest, const C& cost );
-      void RemoveConnection( const I& orig, const I& dest, const C& cost );
-
+      /*! \brief Edge manipulation methods.
+       *         Names are self-explanatory.
+       */
+      bool HasEdge( const I& orig, const I& dest ) const;
+      void AddEdge( const I& orig, const I& dest, const C& cost );
+      void RemoveEdge( const I& orig, const I& dest, const C& cost );
+      void RemoveEdges( const I& orig, const I& dest );
+      TEdges& GetEdges( const I& orig, const I& dest );
+      const TEdges& GetEdges( const I& orig, const I& dest ) const;
+
+      /*! \brief Returns graph's sinks.
+       *
+       *  A sink is a special vertex which does not have any "exiting" edges.
+       *
+       *  @return Sinks ordered by their index.
+       */
       std::set< I > GetSinks( ) const;
 
     protected:
diff --git a/lib/cpExtensions/DataStructures/Graph.hxx b/lib/cpExtensions/DataStructures/Graph.hxx
index ac9e029..7ca6d88 100644
--- a/lib/cpExtensions/DataStructures/Graph.hxx
+++ b/lib/cpExtensions/DataStructures/Graph.hxx
@@ -82,6 +82,14 @@ Clear( )
   this->m_Matrix.clear( );
 }
 
+// -------------------------------------------------------------------------
+template< class V, class C, class I >
+void cpExtensions::DataStructures::Graph< V, C, I >::
+ClearEdges( )
+{
+  this->m_Matrix.clear( );
+}
+
 // -------------------------------------------------------------------------
 template< class V, class C, class I >
 bool cpExtensions::DataStructures::Graph< V, C, I >::
@@ -108,8 +116,7 @@ RenameVertex( const I& old_index, const I& new_index )
   if( old_v != this->m_Vertices.end( ) && new_v == this->m_Vertices.end( ) )
   {
     // Replace vertex
-    typename TVertices::value_type new_entry( new_index, old_v->second );
-    new_v = this->m_Vertices.insert( new_entry ).first;
+    this->m_Vertices[ new_index ] = old_v->second;
     this->m_Vertices.erase( old_index );
 
     // Duplicate edges
@@ -215,10 +222,22 @@ GetVertex( const I& index ) const
   return( this->m_Vertices[ index ] );
 }
 
+// -------------------------------------------------------------------------
+template< class V, class C, class I >
+bool cpExtensions::DataStructures::Graph< V, C, I >::
+HasEdge( const I& orig, const I& dest ) const
+{
+  auto mIt = this->m_Matrix.find( orig );
+  if( mIt != this->m_Matrix.end( ) )
+    return( mIt->second.find( dest ) != mIt->second.end( ) );
+  else
+    return( false );
+}
+
 // -------------------------------------------------------------------------
 template< class V, class C, class I >
 void cpExtensions::DataStructures::Graph< V, C, I >::
-AddConnection( const I& orig, const I& dest, const C& cost )
+AddEdge( const I& orig, const I& dest, const C& cost )
 {
   this->m_Matrix[ orig ][ dest ].push_back( cost );
 }
@@ -226,7 +245,7 @@ AddConnection( const I& orig, const I& dest, const C& cost )
 // -------------------------------------------------------------------------
 template< class V, class C, class I >
 void cpExtensions::DataStructures::Graph< V, C, I >::
-RemoveConnection( const I& orig, const I& dest, const C& cost )
+RemoveEdge( const I& orig, const I& dest, const C& cost )
 {
   auto m = this->m_Matrix.find( orig );
   if( m != this->m_Matrix.end( ) )
@@ -253,6 +272,45 @@ RemoveConnection( const I& orig, const I& dest, const C& cost )
   } // fi
 }
 
+// -------------------------------------------------------------------------
+template< class V, class C, class I >
+void cpExtensions::DataStructures::Graph< V, C, I >::
+RemoveEdges( const I& orig, const I& dest )
+{
+  auto m = this->m_Matrix.find( orig );
+  if( m != this->m_Matrix.end( ) )
+  {
+    auto r = m->second.find( dest );
+    if( r != m->second.end( ) )
+    {
+      m->second.erase( r );
+      if( m->second.size( ) == 0 )
+        this->m_Matrix.erase( m );
+
+    } // fi
+
+  } // fi
+
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class I >
+typename cpExtensions::DataStructures::Graph< V, C, I >::
+TEdges& cpExtensions::DataStructures::Graph< V, C, I >::
+GetEdges( const I& orig, const I& dest )
+{
+  return( this->m_Matrix[ orig ][ dest ] );
+}
+
+// -------------------------------------------------------------------------
+template< class V, class C, class I >
+const typename cpExtensions::DataStructures::Graph< V, C, I >::
+TEdges& cpExtensions::DataStructures::Graph< V, C, I >::
+GetEdges( const I& orig, const I& dest ) const
+{
+  return( this->m_Matrix[ orig ][ dest ] );
+}
+
 // -------------------------------------------------------------------------
 template< class V, class C, class I >
 std::set< I > cpExtensions::DataStructures::Graph< V, C, I >::
diff --git a/appli/cpPipelineEditor/QNEBlock.cxx b/lib/cpPipelineEditor/Block.cxx
similarity index 54%
rename from appli/cpPipelineEditor/QNEBlock.cxx
rename to lib/cpPipelineEditor/Block.cxx
index 67f4a9b..96e60f8 100644
--- a/appli/cpPipelineEditor/QNEBlock.cxx
+++ b/lib/cpPipelineEditor/Block.cxx
@@ -1,30 +1,4 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "QNEBlock.h"
+#include "Block.h"
 
 #include <QPen>
 #include <QGraphicsScene>
@@ -32,12 +6,12 @@
 #include <QPainter>
 #include <QStyleOptionGraphicsItem>
 
-#include "QNEPort.h"
-#include "QNEConnection.h"
+#include "Port.h"
+#include "Connection.h"
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEBlock::
-QNEBlock( TFilter* filter, QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::Block::
+Block( TFilter* filter, QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene ),
     m_HorzMargin( 20 ),
     m_VertMargin( 5 ),
@@ -75,27 +49,26 @@ QNEBlock( TFilter* filter, QGraphicsItem* parent, QGraphicsScene* scene )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEBlock::
-~QNEBlock( )
+cpPipelineEditor::Block::
+~Block( )
 {
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEBlock::
+void cpPipelineEditor::Block::
 setNamePort( const QString& txt )
 {
   if( this->m_NamePort == NULL )
-    this->m_NamePort = new QNENamePort( this );
+    this->m_NamePort = new NamePort( this );
   this->m_NamePort->setName( txt );
-  this->m_Filter->SetName( txt.toStdString( ) );
   this->_configPort( this->m_NamePort );
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEInputPort* PipelineEditor::QNEBlock::
+cpPipelineEditor::InputPort* cpPipelineEditor::Block::
 addInputPort( const QString& txt )
 {
-  QNEInputPort* ip = new QNEInputPort( this );
+  InputPort* ip = new InputPort( this );
   ip->setExtendedName(
     (
       txt.toStdString( ) +
@@ -110,10 +83,10 @@ addInputPort( const QString& txt )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEOutputPort* PipelineEditor::QNEBlock::
+cpPipelineEditor::OutputPort* cpPipelineEditor::Block::
 addOutputPort( const QString& txt )
 {
-  QNEOutputPort* op = new QNEOutputPort( this );
+  OutputPort* op = new OutputPort( this );
   op->setExtendedName(
     (
       txt.toStdString( ) +
@@ -128,37 +101,7 @@ addOutputPort( const QString& txt )
 }
 
 // -------------------------------------------------------------------------
-bool PipelineEditor::QNEBlock::
-extendInputPort( const QString& txt, QNEConnection* conn )
-{
-  auto p = this->m_InputPorts.find( txt.toStdString( ) );
-  auto i = this->m_ExtInputPorts.find( txt.toStdString( ) );
-  if( p != this->m_InputPorts.end( ) && i == this->m_ExtInputPorts.end( ) )
-  {
-    this->m_ExtInputPorts[ txt.toStdString( ) ] = conn;
-    return( true );
-  }
-  else
-    return( false );
-}
-
-// -------------------------------------------------------------------------
-bool PipelineEditor::QNEBlock::
-extendOutputPort( const QString& txt, QNEConnection* conn )
-{
-  auto p = this->m_OutputPorts.find( txt.toStdString( ) );
-  auto i = this->m_ExtOutputPorts.find( txt.toStdString( ) );
-  if( p != this->m_OutputPorts.end( ) && i == this->m_ExtOutputPorts.end( ) )
-  {
-    this->m_ExtOutputPorts[ txt.toStdString( ) ] = conn;
-    return( true );
-  }
-  else
-    return( false );
-}
-
-// -------------------------------------------------------------------------
-PipelineEditor::QNEInputPort* PipelineEditor::QNEBlock::
+cpPipelineEditor::InputPort* cpPipelineEditor::Block::
 inputPort( const QString& txt )
 {
   auto i = this->m_InputPorts.find( txt.toStdString( ) );
@@ -169,7 +112,7 @@ inputPort( const QString& txt )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEOutputPort* PipelineEditor::QNEBlock::
+cpPipelineEditor::OutputPort* cpPipelineEditor::Block::
 outputPort( const QString& txt )
 {
   auto o = this->m_OutputPorts.find( txt.toStdString( ) );
@@ -180,14 +123,14 @@ outputPort( const QString& txt )
 }
 
 // -------------------------------------------------------------------------
-QString PipelineEditor::QNEBlock::
+QString cpPipelineEditor::Block::
 namePort( ) const
 {
   return( this->m_NamePort->name( ) );
 }
 
 // -------------------------------------------------------------------------
-const PipelineEditor::QNEInputPort* PipelineEditor::QNEBlock::
+const cpPipelineEditor::InputPort* cpPipelineEditor::Block::
 inputPort( const QString& txt ) const
 {
   auto i = this->m_InputPorts.find( txt.toStdString( ) );
@@ -198,7 +141,7 @@ inputPort( const QString& txt ) const
 }
 
 // -------------------------------------------------------------------------
-const PipelineEditor::QNEOutputPort* PipelineEditor::QNEBlock::
+const cpPipelineEditor::OutputPort* cpPipelineEditor::Block::
 outputPort( const QString& txt ) const
 {
   auto o = this->m_OutputPorts.find( txt.toStdString( ) );
@@ -209,29 +152,7 @@ outputPort( const QString& txt ) const
 }
 
 // -------------------------------------------------------------------------
-const PipelineEditor::QNEConnection* PipelineEditor::QNEBlock::
-extendedInputPort( const QString& txt ) const
-{
-  auto i = this->m_ExtInputPorts.find( txt.toStdString( ) );
-  if( i != this->m_ExtInputPorts.end( ) )
-    return( i->second );
-  else
-    return( NULL );
-}
-
-// -------------------------------------------------------------------------
-const PipelineEditor::QNEConnection* PipelineEditor::QNEBlock::
-extendedOutputPort( const QString& txt ) const
-{
-  auto i = this->m_ExtOutputPorts.find( txt.toStdString( ) );
-  if( i != this->m_ExtOutputPorts.end( ) )
-    return( i->second );
-  else
-    return( NULL );
-}
-
-// -------------------------------------------------------------------------
-void PipelineEditor::QNEBlock::
+void cpPipelineEditor::Block::
 paint(
   QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget
   )
@@ -254,25 +175,25 @@ paint(
 }
 
 // -------------------------------------------------------------------------
-QVariant PipelineEditor::QNEBlock::
+QVariant cpPipelineEditor::Block::
 itemChange( GraphicsItemChange change, const QVariant& value )
 {
   return( value );
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEBlock::
+void cpPipelineEditor::Block::
 _setTypePort( const QString& txt )
 {
   if( this->m_TypePort == NULL )
-    this->m_TypePort = new QNETypePort( this );
+    this->m_TypePort = new TypePort( this );
   this->m_TypePort->setName( txt );
   this->_configPort( this->m_TypePort );
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEBlock::
-_configPort( QNEPort* port )
+void cpPipelineEditor::Block::
+_configPort( Port* port )
 {
   port->setBlock( this );
 
@@ -297,28 +218,28 @@ _configPort( QNEPort* port )
   int y = -this->m_Height / 2 + this->m_VertMargin + port->radius( );
   foreach( QGraphicsItem* i, this->children( ) )
   {
-    QNEPort* p = dynamic_cast< QNEPort* >( i );
+    Port* p = dynamic_cast< Port* >( i );
     if( p == NULL )
       continue;
 
-    if( dynamic_cast< QNENamePort* >( i ) != NULL )
+    if( dynamic_cast< NamePort* >( i ) != NULL )
       i->setPos( -this->m_Width / 2 + port->radius( ), y );
-    else if( dynamic_cast< QNETypePort* >( i ) != NULL )
+    else if( dynamic_cast< TypePort* >( i ) != NULL )
     {
       i->setPos( -this->m_Width / 2 + port->radius( ), y );
       y += h;
     }
-    else if( dynamic_cast< QNEInputPort* >( i ) != NULL )
+    else if( dynamic_cast< InputPort* >( i ) != NULL )
       i->setPos( -this->m_Width / 2 - 2 * port->radius( ), y );
-    else if( dynamic_cast< QNEOutputPort* >( i ) != NULL )
+    else if( dynamic_cast< OutputPort* >( i ) != NULL )
       i->setPos( this->m_Width / 2, y );
 
     /* TODO
-       QNEPort* p = dynamic_cast< QNEPort* >( i );
+       Port* p = dynamic_cast< Port* >( i );
        if( p == NULL )
        continue;
 
-       if( dynamic_cast< QNEOutputPort* >( p ) != NULL )
+       if( dynamic_cast< OutputPort* >( p ) != NULL )
        p->setPos( this->m_Width / 2 + port->radius( ), y );
        else
        p->setPos( -this->m_Width / 2 - port->radius( ), y );
@@ -329,10 +250,10 @@ _configPort( QNEPort* port )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEBlock::
+void cpPipelineEditor::Block::
 mouseReleaseEvent( QGraphicsSceneMouseEvent* evt )
 {
-  if( this->m_Filter.IsNotNull( ) )
+  if( this->m_Filter != NULL )
     this->m_Filter->SetViewCoords(
       this->scenePos( ).x( ), this->scenePos( ).y( )
       );
diff --git a/lib/cpPipelineEditor/Block.h b/lib/cpPipelineEditor/Block.h
new file mode 100644
index 0000000..81de86f
--- /dev/null
+++ b/lib/cpPipelineEditor/Block.h
@@ -0,0 +1,80 @@
+#ifndef __CPPIPELINEEDITOR__BLOCK__H__
+#define __CPPIPELINEEDITOR__BLOCK__H__
+
+#include <cpPipelineEditor/cpPipelineEditor_Export.h>
+#include <QGraphicsPathItem>
+#include <cpPlugins/Interface/ProcessObject.h>
+
+namespace cpPipelineEditor
+{
+  class Port;
+  class NamePort;
+  class TypePort;
+  class InputPort;
+  class OutputPort;
+
+  /**
+   */
+  class cpPipelineEditor_EXPORT Block
+    : public QGraphicsPathItem
+  {
+  public:
+    typedef Block             Self;
+    typedef QGraphicsPathItem Superclass;
+    typedef cpPlugins::Interface::ProcessObject TFilter;
+  
+  public:
+    enum { Type = QGraphicsItem::UserType + 6 };
+
+    Block(
+      TFilter* filter,
+      QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL
+      );
+    virtual ~Block( );
+
+    void setNamePort( const QString& txt );
+    InputPort* addInputPort( const QString& txt );
+    OutputPort* addOutputPort( const QString& txt );
+
+    InputPort* inputPort( const QString& txt );
+    OutputPort* outputPort( const QString& txt );
+
+    QString namePort( ) const;
+    const InputPort* inputPort( const QString& txt ) const;
+    const OutputPort* outputPort( const QString& txt ) const;
+
+    inline int type( ) const
+      { return( this->Type ); }
+
+    virtual void paint(
+      QPainter* painter,
+      const QStyleOptionGraphicsItem* option,
+      QWidget* widget
+      );
+    
+  protected:
+    QVariant itemChange( GraphicsItemChange change, const QVariant& value );
+    void _setTypePort( const QString& txt );
+    void _configPort( Port* port );
+
+    virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent* evt );
+
+  private:
+    int m_HorzMargin;
+    int m_VertMargin;
+    int m_Width;
+    int m_Height;
+
+    NamePort* m_NamePort;
+    TypePort* m_TypePort;
+    std::map< std::string, InputPort* >  m_InputPorts;
+    std::map< std::string, OutputPort* > m_OutputPorts;
+
+    TFilter* m_Filter;
+  };
+
+} // ecapseman
+
+#endif // __CPPIPELINEEDITOR__BLOCK__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpPipelineEditor/CMakeLists.txt b/lib/cpPipelineEditor/CMakeLists.txt
new file mode 100644
index 0000000..263b4ac
--- /dev/null
+++ b/lib/cpPipelineEditor/CMakeLists.txt
@@ -0,0 +1,50 @@
+SET(LIBRARY_NAME cpPipelineEditor)
+
+## ===============
+## = Source code =
+## ===============
+
+FILE(GLOB LIB_HEADERS_H   "*.h")
+FILE(GLOB LIB_HEADERS_HPP "*.hpp")
+FILE(GLOB LIB_HEADERS_HXX "*.hxx")
+FILE(GLOB LIB_SOURCES_C   "*.c")
+FILE(GLOB LIB_SOURCES_CPP "*.cpp")
+FILE(GLOB LIB_SOURCES_CXX "*.cxx")
+SET(
+  LIB_QT_Headers
+  Canvas.h
+  Editor.h
+  )
+
+## =====================
+## = Compilation rules =
+## =====================
+
+QT4_WRAP_CPP(LIB_QT_Wrapped_MOC_Sources ${LIB_QT_Headers})
+
+ADD_LIBRARY(
+  ${LIBRARY_NAME}
+  ${LIBRARY_TYPE}
+  ${LIB_SOURCES_C}
+  ${LIB_SOURCES_CPP}
+  ${LIB_SOURCES_CXX}
+  ${LIB_QT_Wrapped_MOC_Sources}
+  )
+GENERATE_EXPORT_HEADER(
+  ${LIBRARY_NAME}
+  BASE_NAME ${LIBRARY_NAME}
+  EXPORT_MACRO_NAME ${LIBRARY_NAME}_EXPORT
+  EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/lib/${LIBRARY_NAME}/${LIBRARY_NAME}_Export.h
+  STATIC_DEFINE ${LIBRARY_NAME}_BUILT_AS_STATIC
+  )
+TARGET_LINK_LIBRARIES(
+  ${LIBRARY_NAME}
+  ${QT_LIBRARIES}
+  cpPlugins_Interface
+  )
+
+## ========================
+## -- Installation rules --
+## ========================
+
+## eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNodesEditorCanvas.cxx b/lib/cpPipelineEditor/Canvas.cxx
similarity index 86%
rename from appli/cpPipelineEditor/QNodesEditorCanvas.cxx
rename to lib/cpPipelineEditor/Canvas.cxx
index e5d914f..a5fcc3f 100644
--- a/appli/cpPipelineEditor/QNodesEditorCanvas.cxx
+++ b/lib/cpPipelineEditor/Canvas.cxx
@@ -1,16 +1,16 @@
-#include "QNodesEditorCanvas.h"
-#include "QNodesEditor.h"
-#include "QNEBlock.h"
-#include "QNEConnection.h"
-#include "QNEPort.h"
+#include "Canvas.h"
+#include "Editor.h"
+#include "Block.h"
+#include "Connection.h"
+#include "Port.h"
 
 #include <QDragEnterEvent>
 #include <QWheelEvent>
 #include <QTreeWidget>
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNodesEditorCanvas::
-QNodesEditorCanvas( QWidget* parent )
+cpPipelineEditor::Canvas::
+Canvas( QWidget* parent )
   : QGraphicsView( parent )
 {
   QGraphicsScene* scene = new QGraphicsScene( this );
@@ -18,27 +18,27 @@ QNodesEditorCanvas( QWidget* parent )
   this->setRenderHint( QPainter::Antialiasing );
   this->setAcceptDrops( true );
 
-  this->m_Editor = new QNodesEditor( this );
+  this->m_Editor = new Editor( this );
   this->m_Editor->install( scene );
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNodesEditorCanvas::
-~QNodesEditorCanvas( )
+cpPipelineEditor::Canvas::
+~Canvas( )
 {
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::
-QNodesEditor* PipelineEditor::QNodesEditorCanvas::
+cpPipelineEditor::
+Editor* cpPipelineEditor::Canvas::
 editor( )
 {
   return( this->m_Editor );
 }
 
 // -------------------------------------------------------------------------
-const PipelineEditor::
-QNodesEditor* PipelineEditor::QNodesEditorCanvas::
+const cpPipelineEditor::
+Editor* cpPipelineEditor::Canvas::
 editor( ) const
 {
   return( this->m_Editor );
@@ -46,20 +46,20 @@ editor( ) const
 
 // -------------------------------------------------------------------------
 /* TODO
-   void PipelineEditor::QNodesEditorCanvas::
+   void cpPipelineEditor::Canvas::
    keyPressEvent( QKeyEvent* event )
    {
    }
 
    // -------------------------------------------------------------------------
-   void PipelineEditor::QNodesEditorCanvas::
+   void cpPipelineEditor::Canvas::
    timerEvent( QTimerEvent* event )
    {
    }
 */
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 wheelEvent( QWheelEvent* event )
 {
   this->_scaleView(
@@ -68,7 +68,7 @@ wheelEvent( QWheelEvent* event )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 dragEnterEvent( QDragEnterEvent* event )
 {
   const QMimeData* mime = event->mimeData( );
@@ -77,19 +77,19 @@ dragEnterEvent( QDragEnterEvent* event )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 dragLeaveEvent( QDragLeaveEvent* event )
 {
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 dragMoveEvent( QDragMoveEvent* event )
 {
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 dropEvent( QDropEvent* event )
 {
   const QMimeData* mime = event->mimeData( );
@@ -109,7 +109,7 @@ dropEvent( QDropEvent* event )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 _scaleView( qreal scaleFactor )
 {
   qreal factor = this->transform( ).
@@ -123,16 +123,16 @@ _scaleView( qreal scaleFactor )
 
 // -------------------------------------------------------------------------
   /*
-void PipelineEditor::QNodesEditorCanvas::
+void cpPipelineEditor::Canvas::
 _createBlock( TFilter* f )
 {
   if( f == NULL )
     return;
 
   // Add block
-  QNEBlock* b = new QNEBlock( 0, this->scene( ) );
-  b->addPort( f->GetName( ), 0, QNEPort::NamePort );
-  b->addPort( f->GetClassName( ).c_str( ), 0, QNEPort::TypePort );
+  Block* b = new Block( 0, this->scene( ) );
+  b->addPort( f->GetName( ), 0, Port::NamePort );
+  b->addPort( f->GetClassName( ).c_str( ), 0, Port::TypePort );
 
   // Add input ports
   std::set< std::string > inputs;
@@ -152,16 +152,16 @@ _createBlock( TFilter* f )
   this->m_Graph->InsertVertex( f->GetName( ), b );
 
   // Add vertices and keep track of ports
-    std::map< std::string, std::map< std::string, QNEPort* > >
+    std::map< std::string, std::map< std::string, Port* > >
     in_ports, out_ports;
     auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
     auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
     for( ; vIt != vIt_end; ++vIt )
     {
     // Add block
-    QNEBlock* b = new QNEBlock( 0, scene );
-    b->addPort( vIt->second->GetName( ), 0, QNEPort::NamePort );
-    b->addPort( vIt->second->GetClassName( ).c_str( ), 0, QNEPort::TypePort );
+    Block* b = new Block( 0, scene );
+    b->addPort( vIt->second->GetName( ), 0, Port::NamePort );
+    b->addPort( vIt->second->GetClassName( ).c_str( ), 0, Port::TypePort );
 
     // Get filter
     auto f = dynamic_cast< TFilter* >( vIt->second.GetPointer( ) );
diff --git a/appli/cpPipelineEditor/QNodesEditorCanvas.h b/lib/cpPipelineEditor/Canvas.h
similarity index 57%
rename from appli/cpPipelineEditor/QNodesEditorCanvas.h
rename to lib/cpPipelineEditor/Canvas.h
index 2fec183..c327a69 100644
--- a/appli/cpPipelineEditor/QNodesEditorCanvas.h
+++ b/lib/cpPipelineEditor/Canvas.h
@@ -1,28 +1,29 @@
-#ifndef __PIPELINEEDITOR__QNODESEDITORCANVAS__H__
-#define __PIPELINEEDITOR__QNODESEDITORCANVAS__H__
+#ifndef __CPPIPELINEEDITOR__CANVAS__H__
+#define __CPPIPELINEEDITOR__CANVAS__H__
 
+#include <cpPipelineEditor/cpPipelineEditor_Export.h>
 #include <QtGui/QGraphicsView>
 
-namespace PipelineEditor
+namespace cpPipelineEditor
 {
   // Some other forward declarations
-  class QNEBlock;
-  class QNEConnection;
-  class QNodesEditor;
+  class Block;
+  class Connection;
+  class Editor;
 
   /**
    */
-  class QNodesEditorCanvas
+  class cpPipelineEditor_EXPORT Canvas
     : public QGraphicsView
   {
     Q_OBJECT;
 
   public:
-    QNodesEditorCanvas( QWidget* parent = 0 );
-    virtual ~QNodesEditorCanvas( );
+    Canvas( QWidget* parent = 0 );
+    virtual ~Canvas( );
 
-    QNodesEditor* editor( );
-    const QNodesEditor* editor( ) const;
+    Editor* editor( );
+    const Editor* editor( ) const;
 
   protected:
     /* TODO
@@ -39,11 +40,11 @@ namespace PipelineEditor
     void _scaleView( qreal scaleFactor );
 
   protected:
-    QNodesEditor* m_Editor;
+    Editor* m_Editor;
   };
 
 } // ecapseman
 
-#endif // __PIPELINEEDITOR__QNODESEDITORCANVAS__H__
+#endif // __CPPIPELINEEDITOR__CANVAS__H__
 
 // eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNEConnection.cxx b/lib/cpPipelineEditor/Connection.cxx
similarity index 51%
rename from appli/cpPipelineEditor/QNEConnection.cxx
rename to lib/cpPipelineEditor/Connection.cxx
index c79bb7e..59f66c0 100644
--- a/appli/cpPipelineEditor/QNEConnection.cxx
+++ b/lib/cpPipelineEditor/Connection.cxx
@@ -1,39 +1,13 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "QNEConnection.h"
-#include "QNEPort.h"
+#include "Connection.h"
+#include "Port.h"
 
 #include <QBrush>
 #include <QPen>
 #include <QGraphicsScene>
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEConnection::
-QNEConnection( QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::Connection::
+Connection( QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene )
 {
   this->setPen( QPen( Qt::black, 2 ) );
@@ -44,8 +18,8 @@ QNEConnection( QGraphicsItem* parent, QGraphicsScene* scene )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEConnection::
-~QNEConnection( )
+cpPipelineEditor::Connection::
+~Connection( )
 {
   if( this->m_Port1 != NULL )
     this->m_Port1->connections( ).
@@ -56,22 +30,22 @@ PipelineEditor::QNEConnection::
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEConnection::
+void cpPipelineEditor::Connection::
 setPos1( const QPointF& p )
 {
   this->m_Pos1 = p;
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEConnection::
+void cpPipelineEditor::Connection::
 setPos2( const QPointF& p )
 {
   this->m_Pos2 = p;
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEConnection::
-setPort1( QNEOutputPort* p )
+void cpPipelineEditor::Connection::
+setPort1( OutputPort* p )
 {
   if( p != NULL )
   {
@@ -82,8 +56,8 @@ setPort1( QNEOutputPort* p )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEConnection::
-setPort2( QNEInputPort* p )
+void cpPipelineEditor::Connection::
+setPort2( InputPort* p )
 {
   if( p != NULL )
   {
@@ -98,7 +72,7 @@ setPort2( QNEInputPort* p )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEConnection::
+void cpPipelineEditor::Connection::
 updatePosFromPorts( )
 {
   if( this->m_Port1 != NULL )
@@ -112,7 +86,7 @@ updatePosFromPorts( )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEConnection::
+void cpPipelineEditor::Connection::
 updatePath( )
 {
   QPainterPath p;
@@ -128,14 +102,14 @@ updatePath( )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEOutputPort* PipelineEditor::QNEConnection::
+cpPipelineEditor::OutputPort* cpPipelineEditor::Connection::
 port1( ) const
 {
   return( this->m_Port1 );
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEInputPort* PipelineEditor::QNEConnection::
+cpPipelineEditor::InputPort* cpPipelineEditor::Connection::
 port2( ) const
 {
   return( this->m_Port2 );
diff --git a/lib/cpPipelineEditor/Connection.h b/lib/cpPipelineEditor/Connection.h
new file mode 100644
index 0000000..b7eb26e
--- /dev/null
+++ b/lib/cpPipelineEditor/Connection.h
@@ -0,0 +1,50 @@
+#ifndef __CPPIPELINEEDITOR__CONNECTION__H__
+#define __CPPIPELINEEDITOR__CONNECTION__H__
+
+#include <cpPipelineEditor/cpPipelineEditor_Export.h>
+#include <QGraphicsPathItem>
+
+namespace cpPipelineEditor
+{
+  class InputPort;
+  class OutputPort;
+
+  /**
+   */
+  class cpPipelineEditor_EXPORT Connection
+    : public QGraphicsPathItem
+  {
+  public:
+    typedef Connection     Self;
+    typedef QGraphicsPathItem Superclass;
+
+  public:
+    enum { Type = QGraphicsItem::UserType + 5 };
+
+    Connection( QGraphicsItem* parent = 0, QGraphicsScene* scene = 0 );
+    virtual ~Connection( );
+
+    void setPos1( const QPointF& p );
+    void setPos2( const QPointF& p );
+    void setPort1( OutputPort* p );
+    void setPort2( InputPort* p );
+    void updatePosFromPorts( );
+    void updatePath( );
+    OutputPort* port1( ) const;
+    InputPort* port2( ) const;
+
+    inline int type( ) const
+      { return( this->Type ); }
+
+  private:
+    QPointF m_Pos1;
+    QPointF m_Pos2;
+    OutputPort* m_Port1;
+    InputPort*  m_Port2;
+  };
+
+} // ecapseman
+
+#endif // __CPPIPELINEEDITOR__CONNECTION__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpPipelineEditor/Editor.cxx b/lib/cpPipelineEditor/Editor.cxx
new file mode 100644
index 0000000..237bb58
--- /dev/null
+++ b/lib/cpPipelineEditor/Editor.cxx
@@ -0,0 +1,510 @@
+#include "Editor.h"
+
+#include <QGraphicsScene>
+#include <QEvent>
+#include <QGraphicsSceneContextMenuEvent>
+#include <QGraphicsSceneDragDropEvent>
+#include <QGraphicsSceneHelpEvent>
+#include <QGraphicsSceneHoverEvent>
+#include <QGraphicsSceneMouseEvent>
+#include <QGraphicsSceneMoveEvent>
+#include <QGraphicsSceneResizeEvent>
+#include <QGraphicsSceneWheelEvent>
+#include <QInputDialog>
+
+#include "Port.h"
+#include "Connection.h"
+#include "Block.h"
+
+// -------------------------------------------------------------------------
+#define cpPipelineEditor_Editor_Callback_SWITCH( E, e )                 \
+  case QEvent::GraphicsScene##E:                                        \
+  {                                                                     \
+    QGraphicsScene##E##Event* evt =                                     \
+      dynamic_cast< QGraphicsScene##E##Event* >( e );                   \
+    if( evt != NULL )                                                   \
+      this->_##E##_cbk( evt );                                          \
+  }                                                                     \
+  break;
+
+// -------------------------------------------------------------------------
+#define cpPipelineEditor_Editor_Callback_CODE( E )                      \
+  void cpPipelineEditor::Editor::_##E##_cbk( QGraphicsScene##E##Event* evt )
+
+// -------------------------------------------------------------------------
+cpPipelineEditor::Editor::
+Editor( QObject* parent )
+  : Superclass( parent ),
+    m_ActualConnection( NULL ),
+    m_Workspace( NULL )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor::Editor::
+~Editor( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor::Editor::
+TWorkspace* cpPipelineEditor::Editor::
+workspace( )
+{
+  return( this->m_Workspace );
+}
+
+// -------------------------------------------------------------------------
+const cpPipelineEditor::Editor::
+TWorkspace* cpPipelineEditor::Editor::
+workspace( ) const
+{
+  return( this->m_Workspace );
+}
+
+// -------------------------------------------------------------------------
+void cpPipelineEditor::Editor::
+setWorkspace( TWorkspace* ws )
+{
+  this->m_Workspace = ws;
+  this->m_Graph = TGraph::New( );
+
+  // Create blocks
+  auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
+  auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
+  for( ; vIt != vIt_end; ++vIt )
+    this->_createBlock(
+      dynamic_cast< TFilter* >( vIt->second.GetPointer( ) ),
+      QPointF( vIt->second->GetViewX( ), vIt->second->GetViewY( ) )
+      );
+
+  // Add edges
+  auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
+  auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
+  for( ; rIt != rIt_end; ++rIt )
+  {
+    Block* orig = this->m_Graph->GetVertex( rIt->first );
+    auto cIt = rIt->second.begin( );
+    for( ; cIt != rIt->second.end( ); ++cIt )
+    {
+      Block* dest = this->m_Graph->GetVertex( cIt->first );
+      auto eIt = cIt->second.begin( );
+      for( ; eIt != cIt->second.end( ); ++eIt )
+      {
+        OutputPort* op = orig->outputPort( eIt->first.c_str( ) );
+        InputPort* ip = dest->inputPort( eIt->second.c_str( ) );
+        if( op == NULL || ip == NULL )
+          continue;
+
+        Connection* c = new Connection( 0, this->m_Scene );
+        c->setPort1( op );
+        c->setPort2( ip );
+        c->updatePosFromPorts( );
+        c->updatePath( );
+        this->m_Graph->AddEdge( rIt->first, cIt->first, c );
+
+      } // rof
+
+    } // rof
+
+  } // rof
+}
+
+// -------------------------------------------------------------------------
+std::string cpPipelineEditor::Editor::
+createFilter( const std::string& filter, const QPointF& pnt )
+{
+  std::string name = filter;
+  while( this->m_Workspace->HasFilter( name ) )
+    name += std::string( "_" );
+  if( this->m_Workspace->CreateFilter( filter, name ) )
+  {
+    this->_createBlock( this->m_Workspace->GetFilter( name ), pnt );
+    return( name );
+  }
+  else
+    return( "" );
+}
+
+// -------------------------------------------------------------------------
+void cpPipelineEditor::Editor::
+install( QGraphicsScene* s )
+{
+  s->installEventFilter( this );
+  this->m_Scene = s;
+}
+
+// -------------------------------------------------------------------------
+QGraphicsItem* cpPipelineEditor::Editor::
+itemAt( const QPointF& pos )
+{
+  QList< QGraphicsItem* > items =
+    this->m_Scene->items( QRectF( pos - QPointF( 1, 1 ), QSize( 3, 3 ) ) );
+
+  foreach( QGraphicsItem* item, items )
+    if( item->type( ) > QGraphicsItem::UserType )
+      return( item );
+  return( NULL );
+}
+
+// -------------------------------------------------------------------------
+void cpPipelineEditor::Editor::
+_createBlock( TFilter* f, const QPointF& pnt )
+{
+  if( f == NULL )
+    return;
+
+  // Add block
+  Block* b = new Block( f, 0, this->m_Scene );
+  b->setPos( pnt );
+
+  // Keep a trace of this visual graph
+  this->m_Graph->SetVertex( f->GetName( ), b );
+}
+
+// -------------------------------------------------------------------------
+bool cpPipelineEditor::Editor::
+eventFilter( QObject* o, QEvent* e )
+{
+  // Event type
+  switch( int( e->type( ) ) )
+  {
+    cpPipelineEditor_Editor_Callback_SWITCH( ContextMenu, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( DragEnter, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( DragLeave, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( DragMove, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( Drop, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( Help, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( HoverEnter, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( HoverLeave, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( HoverMove, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( MouseDoubleClick, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( MouseMove, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( MousePress, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( MouseRelease, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( Move, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( Resize, e );
+    cpPipelineEditor_Editor_Callback_SWITCH( Wheel, e );
+  default:
+    break;
+  } // hctiws
+  return( this->Superclass::eventFilter( o, e ) );
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( ContextMenu )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( DragEnter )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( DragLeave )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( DragMove )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( Drop )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( Help )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( HoverEnter )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( HoverLeave )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( HoverMove )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( MouseDoubleClick )
+{
+  QGraphicsItem* item = this->itemAt( evt->scenePos( ) );
+  if( item == NULL )
+    return;
+
+  switch( evt->button( ) )
+  {
+  case Qt::LeftButton:
+  {
+    Block* block = dynamic_cast< Block* >( item );
+    Port* port = dynamic_cast< Port* >( item );
+    Connection* conn = dynamic_cast< Connection* >( item );
+
+    if( block != NULL )
+    {
+      QString old_name = block->namePort( );
+      bool ok;
+      QString new_name =
+        QInputDialog::getText(
+          dynamic_cast< QWidget* >( this->parent( ) ),
+          "Change filter name",
+          "Filter name:",
+          QLineEdit::Normal,
+          old_name,
+          &ok
+          );
+      if( ok && !new_name.isEmpty( ) && old_name != new_name )
+      {
+        ok = this->m_Graph->RenameVertex(
+          old_name.toStdString( ),
+          new_name.toStdString( )
+          );
+        if( ok )
+        {
+          block->setNamePort( new_name );
+          this->m_Workspace->RenameFilter(
+            old_name.toStdString( ),
+            new_name.toStdString( )
+            );
+
+        } // fi
+
+      } // fi
+    }
+    else if( port != NULL )
+    {
+      if( evt->modifiers( ) == Qt::ControlModifier )
+      {
+        port->setExtend( !( port->isExtended( ) ) );
+        InputPort* in_port = dynamic_cast< InputPort* >( port );
+        OutputPort* out_port = dynamic_cast< OutputPort* >( port );
+        if( port->isExtended( ) )
+        {
+          if( in_port != NULL )
+          {
+            this->m_Workspace->ExposeInputPort(
+              in_port->extendedName( ).toStdString( ),
+              in_port->block( )->namePort( ).toStdString( ),
+              in_port->name( ).toStdString( )
+              );
+          }
+          else if( out_port != NULL )
+          {
+            this->m_Workspace->ExposeOutputPort(
+              out_port->extendedName( ).toStdString( ),
+              out_port->block( )->namePort( ).toStdString( ),
+              out_port->name( ).toStdString( )
+              );
+
+          } // fi
+        }
+        else
+        {
+          if( in_port != NULL )
+            this->m_Workspace->HideInputPort(
+              in_port->extendedName( ).toStdString( )
+              );
+          else if( out_port != NULL )
+            this->m_Workspace->HideOutputPort(
+              out_port->extendedName( ).toStdString( )
+              );
+
+        } // fi
+        this->m_Scene->update( );
+      }
+      else if( evt->modifiers( ) == Qt::NoModifier )
+      {
+        if( port->isExtended( ) )
+        {
+          QString old_name = port->extendedName( );
+          bool ok;
+          QString new_name =
+            QInputDialog::getText(
+              dynamic_cast< QWidget* >( this->parent( ) ),
+              "Change filter name",
+              "Filter name:",
+              QLineEdit::Normal,
+              old_name,
+              &ok
+              );
+          if( ok && !new_name.isEmpty( ) && old_name != new_name )
+          {
+            port->setExtendedName( new_name );
+            InputPort* in_port = dynamic_cast< InputPort* >( port );
+            OutputPort* out_port = dynamic_cast< OutputPort* >( port );
+            if( in_port != NULL )
+              this->m_Workspace->
+                RenameExposedInputPort(
+                  old_name.toStdString( ),
+                  new_name.toStdString( )
+                  );
+            else if( out_port != NULL )
+              this->m_Workspace->
+                RenameExposedOutputPort(
+                  old_name.toStdString( ),
+                  new_name.toStdString( )
+                  );
+            this->m_Scene->update( );
+
+          } // fi
+
+        } // fi
+
+      } // fi
+    }
+    else if( conn != NULL )
+    {
+    } // fi
+  }
+  break;
+  /* TODO:
+     case Qt::RightButton:
+     {
+     }
+     break;
+     case Qt::MiddleButton:
+     {
+     }
+     break;
+  */
+  default:
+    break;
+  } // hctiws
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( MouseMove )
+{
+  if( this->m_ActualConnection != NULL )
+  {
+    if( this->m_ActualConnection->port1( ) == NULL )
+      this->m_ActualConnection->setPos1( evt->scenePos( ) );
+    else if( this->m_ActualConnection->port2( ) == NULL )
+      this->m_ActualConnection->setPos2( evt->scenePos( ) );
+    this->m_ActualConnection->updatePath( );
+
+  } // fi
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( MousePress )
+{
+  InputPort* in_port =
+    dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );
+  OutputPort* out_port =
+    dynamic_cast< OutputPort* >( this->itemAt( evt->scenePos( ) ) );
+  if( in_port == NULL && out_port == NULL )
+    return;
+
+  switch( evt->button( ) )
+  {
+  case Qt::LeftButton:
+  {
+    if( out_port != NULL )
+    {
+      if( out_port->block( ) != NULL )
+      {
+        // Start new connection
+        this->m_ActualConnection = new Connection( 0, this->m_Scene );
+        this->m_ActualConnection->setPort1( out_port );
+        this->m_ActualConnection->setPos1( out_port->scenePos( ) );
+        this->m_ActualConnection->setPos2( evt->scenePos( ) );
+        this->m_ActualConnection->updatePosFromPorts( );
+        this->m_ActualConnection->updatePath( );
+
+      } // fi
+
+    } // fi
+  }
+  break;
+  default:
+    break;
+
+  } // hctiws
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( MouseRelease )
+{
+  if( this->m_ActualConnection == NULL )
+    return;
+
+  switch( evt->button( ) )
+  {
+  case Qt::LeftButton:
+  {
+    InputPort* port2 =
+      dynamic_cast< InputPort* >( this->itemAt( evt->scenePos( ) ) );
+    if( port2 != NULL )
+    {
+      OutputPort* port1 =
+        dynamic_cast< OutputPort* >( this->m_ActualConnection->port1( ) );
+      if( port1 != NULL )
+      {
+        if(
+          port1->block( ) != port2->block( ) &&
+          !port2->hasConnection( ) &&
+          !port1->isConnected( port2 ) &&
+          !port2->isExtended( )
+          )
+        {
+          this->m_ActualConnection->setPos2( port2->scenePos( ) );
+          this->m_ActualConnection->setPort2( port2 );
+          this->m_ActualConnection->updatePosFromPorts( );
+          this->m_ActualConnection->updatePath( );
+
+          this->m_Workspace->Connect(
+            port1->block( )->namePort( ).toStdString( ),
+            port2->block( )->namePort( ).toStdString( ),
+            port1->name( ).toStdString( ),
+            port2->name( ).toStdString( )
+            );
+          this->m_Graph->AddEdge(
+            port1->block( )->namePort( ).toStdString( ),
+            port2->block( )->namePort( ).toStdString( ),
+            this->m_ActualConnection
+            );
+        }
+        else
+          delete this->m_ActualConnection;
+      }
+      else
+        delete this->m_ActualConnection;
+    }
+    else
+      delete this->m_ActualConnection;
+    this->m_ActualConnection = NULL;
+  }
+  break;
+  default:
+    break;
+  } // hctisw
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( Move )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( Resize )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPipelineEditor_Editor_Callback_CODE( Wheel )
+{
+}
+
+// eof - $RCSfile$
diff --git a/lib/cpPipelineEditor/Editor.h b/lib/cpPipelineEditor/Editor.h
new file mode 100644
index 0000000..51c8768
--- /dev/null
+++ b/lib/cpPipelineEditor/Editor.h
@@ -0,0 +1,111 @@
+#ifndef __CPPIPELINEEDITOR__EDITOR__H__
+#define __CPPIPELINEEDITOR__EDITOR__H__
+
+#include <cpPipelineEditor/cpPipelineEditor_Export.h>
+#include <cpExtensions/DataStructures/Graph.h>
+#include <cpPlugins/Interface/Workspace.h>
+#include <QObject>
+#include <QPointF>
+
+class QGraphicsScene;
+class QGraphicsSceneMouseEvent;
+class QGraphicsItem;
+class QGraphicsSceneContextMenuEvent;
+class QGraphicsSceneDragDropEvent;
+class QGraphicsSceneHelpEvent;
+class QGraphicsSceneHoverEvent;
+class QGraphicsSceneMouseEvent;
+class QGraphicsSceneMoveEvent;
+class QGraphicsSceneResizeEvent;
+class QGraphicsSceneWheelEvent;
+
+// -------------------------------------------------------------------------
+#define cpPipelineEditor_Editor_Callback_DCL( E )       \
+  void _##E##_cbk( QGraphicsScene##E##Event* e );
+
+namespace cpPipelineEditor
+{
+  class Connection;
+  class Block;
+
+  /**
+   */
+  class cpPipelineEditor_EXPORT Editor
+    : public QObject
+  {
+    Q_OBJECT;
+
+  public:
+    typedef Editor Self;
+    typedef QObject      Superclass;
+
+    typedef cpPlugins::Interface::Workspace TWorkspace;
+    typedef TWorkspace::TFilter             TFilter;
+    typedef
+      cpExtensions::DataStructures::
+      Graph< Block*, Connection*, std::string > TGraph;
+
+  public:
+    explicit Editor( QObject* parent = 0 );
+    virtual ~Editor( );
+
+    TWorkspace* workspace( );
+    const TWorkspace* workspace( ) const;
+    void setWorkspace( TWorkspace* ws );
+
+    std::string createFilter(
+      const std::string& filter,
+      const QPointF& pnt = QPointF( qreal( 0 ), qreal( 0 ) )
+      );
+
+    void install( QGraphicsScene* s );
+    bool eventFilter( QObject* o, QEvent* e );
+
+  private:
+    QGraphicsItem* itemAt( const QPointF& pos );
+
+    inline void _createBlock( TFilter* f, const QPointF& pnt );
+
+  protected:
+    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragEnterEvent;
+    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragLeaveEvent;
+    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDragMoveEvent;
+    typedef QGraphicsSceneDragDropEvent QGraphicsSceneDropEvent;
+    typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverEnterEvent;
+    typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverMoveEvent;
+    typedef QGraphicsSceneHoverEvent    QGraphicsSceneHoverLeaveEvent;
+    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseDoubleClickEvent;
+    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseMoveEvent;
+    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMousePressEvent;
+    typedef QGraphicsSceneMouseEvent    QGraphicsSceneMouseReleaseEvent;
+
+    cpPipelineEditor_Editor_Callback_DCL( ContextMenu );
+    cpPipelineEditor_Editor_Callback_DCL( DragEnter );
+    cpPipelineEditor_Editor_Callback_DCL( DragLeave );
+    cpPipelineEditor_Editor_Callback_DCL( DragMove );
+    cpPipelineEditor_Editor_Callback_DCL( Drop );
+    cpPipelineEditor_Editor_Callback_DCL( Help );
+    cpPipelineEditor_Editor_Callback_DCL( HoverEnter );
+    cpPipelineEditor_Editor_Callback_DCL( HoverLeave );
+    cpPipelineEditor_Editor_Callback_DCL( HoverMove );
+    cpPipelineEditor_Editor_Callback_DCL( MouseDoubleClick );
+    cpPipelineEditor_Editor_Callback_DCL( MouseMove );
+    cpPipelineEditor_Editor_Callback_DCL( MousePress );
+    cpPipelineEditor_Editor_Callback_DCL( MouseRelease );
+    cpPipelineEditor_Editor_Callback_DCL( Move );
+    cpPipelineEditor_Editor_Callback_DCL( Resize );
+    cpPipelineEditor_Editor_Callback_DCL( Wheel );
+
+  private:
+    QGraphicsScene* m_Scene;
+    Connection* m_ActualConnection;
+
+    TWorkspace* m_Workspace;
+    TGraph::Pointer m_Graph;
+  };
+
+} // ecapseman
+
+#endif // __CPPIPELINEEDITOR__EDITOR__H__
+
+// eof - $RCSfile$
diff --git a/appli/cpPipelineEditor/QNEPort.cxx b/lib/cpPipelineEditor/Port.cxx
similarity index 62%
rename from appli/cpPipelineEditor/QNEPort.cxx
rename to lib/cpPipelineEditor/Port.cxx
index 7b71975..ab478c2 100644
--- a/appli/cpPipelineEditor/QNEPort.cxx
+++ b/lib/cpPipelineEditor/Port.cxx
@@ -1,31 +1,5 @@
-/* Copyright (c) 2012, STANISLAW ADASZEWSKI
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-   * Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-   * Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-   * Neither the name of STANISLAW ADASZEWSKI nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-   DISCLAIMED. IN NO EVENT SHALL STANISLAW ADASZEWSKI BE LIABLE FOR ANY
-   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#include "QNEPort.h"
-#include "QNEConnection.h"
+#include "Port.h"
+#include "Connection.h"
 
 #include <QGraphicsScene>
 #include <QFontMetrics>
@@ -33,8 +7,8 @@
 #include <QPen>
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEPort::
-QNEPort( QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::Port::
+Port( QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene ),
     m_Radius( 5 ),
     m_Margin( 2 )
@@ -53,20 +27,20 @@ QNEPort( QGraphicsItem* parent, QGraphicsScene* scene )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEPort::
-~QNEPort( )
+cpPipelineEditor::Port::
+~Port( )
 {
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEPort::
-setBlock( QNEBlock* b )
+void cpPipelineEditor::Port::
+setBlock( Block* b )
 {
   this->m_Block = b;
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEPort::
+void cpPipelineEditor::Port::
 setName( const QString& n )
 {
   this->m_Label->setPlainText( n );
@@ -74,7 +48,7 @@ setName( const QString& n )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEPort::
+void cpPipelineEditor::Port::
 setExtendedName( const QString& n )
 {
   this->m_ExtendedLabel->setPlainText( n );
@@ -82,7 +56,7 @@ setExtendedName( const QString& n )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEPort::
+void cpPipelineEditor::Port::
 setExtend( bool extend )
 {
   // Do nothing!
@@ -91,7 +65,7 @@ setExtend( bool extend )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEPort::
+void cpPipelineEditor::Port::
 paint(
   QPainter* painter,
   const QStyleOptionGraphicsItem* option,
@@ -116,20 +90,20 @@ paint(
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNENamePort::
-QNENamePort( QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::NamePort::
+NamePort( QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene )
 {
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNENamePort::
-~QNENamePort( )
+cpPipelineEditor::NamePort::
+~NamePort( )
 {
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNENamePort::
+void cpPipelineEditor::NamePort::
 _updateLabels( )
 {
   QFont font( this->scene( )->font( ) );
@@ -140,27 +114,27 @@ _updateLabels( )
 }
 
 // -------------------------------------------------------------------------
-bool PipelineEditor::QNENamePort::
-isConnected( QNEPort* other )
+bool cpPipelineEditor::NamePort::
+isConnected( Port* other )
 {
   return( false );
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNETypePort::
-QNETypePort( QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::TypePort::
+TypePort( QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene )
 {
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNETypePort::
-~QNETypePort( )
+cpPipelineEditor::TypePort::
+~TypePort( )
 {
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNETypePort::
+void cpPipelineEditor::TypePort::
 _updateLabels( )
 {
   QFont font( this->scene( )->font( ) );
@@ -171,30 +145,30 @@ _updateLabels( )
 }
 
 // -------------------------------------------------------------------------
-bool PipelineEditor::QNETypePort::
-isConnected( QNEPort* other )
+bool cpPipelineEditor::TypePort::
+isConnected( Port* other )
 {
   return( false );
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEInputPort::
-QNEInputPort( QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::InputPort::
+InputPort( QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene ),
     m_Connection( NULL )
 {
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEInputPort::
-~QNEInputPort( )
+cpPipelineEditor::InputPort::
+~InputPort( )
 {
   if( this->m_Connection != NULL )
     delete this->m_Connection;
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEInputPort::
+void cpPipelineEditor::InputPort::
 _updateLabels( )
 {
   QFontMetrics fm( this->scene( )->font( ) );
@@ -206,7 +180,7 @@ _updateLabels( )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEInputPort::
+void cpPipelineEditor::InputPort::
 setExtend( bool extend )
 {
   if( this->m_Connection == NULL )
@@ -219,8 +193,8 @@ setExtend( bool extend )
 }
 
 // -------------------------------------------------------------------------
-bool PipelineEditor::QNEInputPort::
-isConnected( QNEPort* other )
+bool cpPipelineEditor::InputPort::
+isConnected( Port* other )
 {
   if( this->m_Connection != NULL )
     return(
@@ -232,14 +206,14 @@ isConnected( QNEPort* other )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEInputPort::
-setConnection( QNEConnection* c )
+void cpPipelineEditor::InputPort::
+setConnection( Connection* c )
 {
   this->m_Connection = c;
 }
 
 // -------------------------------------------------------------------------
-QVariant PipelineEditor::QNEInputPort::
+QVariant cpPipelineEditor::InputPort::
 itemChange( GraphicsItemChange change, const QVariant& value )
 {
   if( change == ItemScenePositionHasChanged )
@@ -256,22 +230,22 @@ itemChange( GraphicsItemChange change, const QVariant& value )
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEOutputPort::
-QNEOutputPort( QGraphicsItem* parent, QGraphicsScene* scene )
+cpPipelineEditor::OutputPort::
+OutputPort( QGraphicsItem* parent, QGraphicsScene* scene )
   : Superclass( parent, scene )
 {
 }
 
 // -------------------------------------------------------------------------
-PipelineEditor::QNEOutputPort::
-~QNEOutputPort( )
+cpPipelineEditor::OutputPort::
+~OutputPort( )
 {
-  foreach( QNEConnection* conn, this->m_Connections )
+  foreach( Connection* conn, this->m_Connections )
     delete conn;
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEOutputPort::
+void cpPipelineEditor::OutputPort::
 _updateLabels( )
 {
   QFontMetrics fm( this->scene( )->font( ) );
@@ -283,7 +257,7 @@ _updateLabels( )
 }
 
 // -------------------------------------------------------------------------
-void PipelineEditor::QNEOutputPort::
+void cpPipelineEditor::OutputPort::
 setExtend( bool extend )
 {
   this->m_IsExtended = extend;
@@ -291,8 +265,8 @@ setExtend( bool extend )
 }
 
 // -------------------------------------------------------------------------
-bool PipelineEditor::QNEOutputPort::
-isConnected( QNEPort* other )
+bool cpPipelineEditor::OutputPort::
+isConnected( Port* other )
 {
   auto i = this->m_Connections.begin( );
   bool conn = false;
@@ -302,12 +276,12 @@ isConnected( QNEPort* other )
 }
 
 // -------------------------------------------------------------------------
-QVariant PipelineEditor::QNEOutputPort::
+QVariant cpPipelineEditor::OutputPort::
 itemChange( GraphicsItemChange change, const QVariant& value )
 {
   if( change == ItemScenePositionHasChanged )
   {
-    foreach( QNEConnection* conn, this->m_Connections )
+    foreach( Connection* conn, this->m_Connections )
     {
       conn->updatePosFromPorts( );
       conn->updatePath( );
diff --git a/lib/cpPipelineEditor/Port.h b/lib/cpPipelineEditor/Port.h
new file mode 100644
index 0000000..0f64a4b
--- /dev/null
+++ b/lib/cpPipelineEditor/Port.h
@@ -0,0 +1,190 @@
+#ifndef __CPPIPELINEEDITOR__PORT__H__
+#define __CPPIPELINEEDITOR__PORT__H__
+
+#include <cpPipelineEditor/cpPipelineEditor_Export.h>
+#include <QGraphicsPathItem>
+
+namespace cpPipelineEditor
+{
+  class Block;
+  class Connection;
+
+  /**
+   */
+  class cpPipelineEditor_EXPORT Port
+    : public QGraphicsPathItem
+  {
+  public:
+    typedef Port Self;
+    typedef QGraphicsPathItem Superclass;
+
+    enum { Type = QGraphicsItem::UserType + 1 };
+
+  public:
+    Port( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
+    virtual ~Port( );
+
+    void setBlock( Block* b );
+    inline Block* block( ) const
+      { return( this->m_Block ); }
+
+    virtual void setName( const QString& n );
+    virtual void setExtendedName( const QString& n );
+    inline QString name( ) const
+      { return( this->m_Label->toPlainText( ) ); }
+    inline QString extendedName( ) const
+      { return( this->m_ExtendedLabel->toPlainText( ) ); }
+
+    inline int radius( ) const
+      { return( this->m_Radius ); }
+
+    inline bool isExtended( ) const
+      { return( this->m_IsExtended ); }
+    virtual void setExtend( bool extend );
+
+    virtual bool isConnected( Port* other ) = 0;
+    inline int type( ) const
+      { return( this->Type ); }
+
+    virtual void paint(
+      QPainter* painter,
+      const QStyleOptionGraphicsItem* option,
+      QWidget* widget
+      );
+
+  protected:
+    virtual void _updateLabels( ) { }
+
+  protected:
+    Block* m_Block;
+
+    int  m_Radius;
+    int  m_Margin;
+    bool m_IsExtended;
+
+    QGraphicsTextItem* m_Label;
+    QGraphicsTextItem* m_ExtendedLabel;
+  };
+
+  /**
+   */
+  class NamePort
+    : public Port
+  {
+  public:
+    typedef NamePort Self;
+    typedef Port     Superclass;
+
+    enum { Type = Superclass::Type + 1 };
+
+  public:
+    NamePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
+    virtual ~NamePort( );
+
+    virtual bool isConnected( Port* other );
+    inline int type( ) const
+      { return( this->Type ); }
+
+  protected:
+    virtual void _updateLabels( );
+  };
+
+  /**
+   */
+  class TypePort
+    : public Port
+  {
+  public:
+    typedef TypePort Self;
+    typedef Port     Superclass;
+
+    enum { Type = Superclass::Type + 2 };
+
+  public:
+    TypePort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
+    virtual ~TypePort( );
+
+    virtual bool isConnected( Port* other );
+    inline int type( ) const
+      { return( this->Type ); }
+
+  protected:
+    virtual void _updateLabels( );
+  };
+
+  /**
+   */
+  class InputPort
+    : public Port
+  {
+  public:
+    typedef InputPort Self;
+    typedef Port      Superclass;
+
+    enum { Type = Superclass::Type + 3 };
+
+  public:
+    InputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
+    virtual ~InputPort( );
+
+    virtual void setExtend( bool extend );
+
+    virtual bool isConnected( Port* other );
+    inline int type( ) const
+      { return( this->Type ); }
+
+    void setConnection( Connection* c );
+    inline Connection* connection( )
+      { return( this->m_Connection ); }
+    inline const Connection* connection( ) const
+      { return( this->m_Connection ); }
+    inline bool hasConnection( ) const
+      { return( this->m_Connection != NULL ); }
+
+  protected:
+    QVariant itemChange( GraphicsItemChange change, const QVariant& value );
+    virtual void _updateLabels( );
+
+  protected:
+    Connection* m_Connection;
+  };
+
+  /**
+   */
+  class OutputPort
+    : public Port
+  {
+  public:
+    typedef OutputPort Self;
+    typedef Port       Superclass;
+
+    enum { Type = Superclass::Type + 4 };
+
+  public:
+    OutputPort( QGraphicsItem* parent = NULL, QGraphicsScene* scene = NULL );
+    virtual ~OutputPort( );
+
+    virtual void setExtend( bool extend );
+
+    virtual bool isConnected( Port* other );
+    inline int type( ) const
+      { return( this->Type ); }
+
+    inline QVector< Connection* >& connections( )
+      { return( this->m_Connections ); }
+    inline const QVector< Connection* >& connections( ) const
+      { return( this->m_Connections ); }
+
+  protected:
+    QVariant itemChange( GraphicsItemChange change, const QVariant& value );
+    virtual void _updateLabels( );
+
+  protected:
+    QVector< Connection* > m_Connections;
+  };
+
+} // ecapseman
+
+#endif // __CPPIPELINEEDITOR__PORT__H__
+
+// eof - $RCSfile$
diff --git a/lib/cpPlugins/Interface/Parameters.cxx b/lib/cpPlugins/Interface/Parameters.cxx
index 52b2e47..1b23972 100644
--- a/lib/cpPlugins/Interface/Parameters.cxx
+++ b/lib/cpPlugins/Interface/Parameters.cxx
@@ -1,5 +1,6 @@
 #include <cpPlugins/Interface/Parameters.h>
 #include <cpPlugins/Interface/ProcessObject.h>
+#include <third_party/tinyxml/tinyxml.h>
 
 #include <sstream>
 
@@ -460,6 +461,122 @@ SetSelectedChoice( const TString& name, const TString& choice )
     return( false );
 }
 
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Parameters::
+ToXML( TiXmlElement* parent_elem ) const
+{
+  if( parent_elem == NULL )
+    return( false );
+
+  auto pIt = this->m_Parameters.begin( );
+  for( ; pIt != this->m_Parameters.end( ); ++pIt )
+  {
+    TiXmlElement* p = new TiXmlElement( "parameter" );
+    p->SetAttribute( "name", pIt->first.c_str( ) );
+    p->SetAttribute( "value", pIt->second.second.c_str( ) );
+    if( pIt->second.first == Self::String )
+      p->SetAttribute( "type", "String" );
+    else if( pIt->second.first == Self::Bool )
+      p->SetAttribute( "type", "Bool" );
+    else if( pIt->second.first == Self::Int )
+      p->SetAttribute( "type", "Int" );
+    else if( pIt->second.first == Self::Uint )
+      p->SetAttribute( "type", "Uint" );
+    else if( pIt->second.first == Self::Real )
+      p->SetAttribute( "type", "Real" );
+    else if( pIt->second.first == Self::Index )
+      p->SetAttribute( "type", "Index" );
+    else if( pIt->second.first == Self::Point )
+      p->SetAttribute( "type", "Point" );
+    else if( pIt->second.first == Self::Vector )
+      p->SetAttribute( "type", "Vector" );
+    else if( pIt->second.first == Self::StringList )
+      p->SetAttribute( "type", "StringList" );
+    else if( pIt->second.first == Self::BoolList )
+      p->SetAttribute( "type", "BoolList" );
+    else if( pIt->second.first == Self::IntList )
+      p->SetAttribute( "type", "IntList" );
+    else if( pIt->second.first == Self::UintList )
+      p->SetAttribute( "type", "UintList" );
+    else if( pIt->second.first == Self::RealList )
+      p->SetAttribute( "type", "RealList" );
+    else if( pIt->second.first == Self::IndexList )
+      p->SetAttribute( "type", "IndexList" );
+    else if( pIt->second.first == Self::PointList )
+      p->SetAttribute( "type", "PointList" );
+    else if( pIt->second.first == Self::VectorList )
+      p->SetAttribute( "type", "VectorList" );
+    else if( pIt->second.first == Self::Choices )
+      p->SetAttribute( "type", "Choices" );
+    parent_elem->LinkEndChild( p );
+
+  } // rof
+  return( true );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Parameters::
+FromXML( const TiXmlElement* filter_elem )
+{
+  this->m_Parameters.clear( );
+
+  const TiXmlElement* param = filter_elem->FirstChildElement( "parameter" );
+  bool ret = false;
+  while( param != NULL )
+  {
+    const char* param_name = param->Attribute( "name" );
+    const char* param_type = param->Attribute( "type" );
+    if( param_name != NULL && param_type != NULL )
+    {
+      TParameter value;
+      value.second = param->Attribute( "value" );
+
+      std::string param_type_str( param_type );
+      if( param_type_str == "Bool" )
+        value.first = Self::Bool;
+      else if( param_type_str == "Int" )
+        value.first = Self::Int;
+      else if( param_type_str == "Uint" )
+        value.first = Self::Uint;
+      else if( param_type_str == "Real" )
+        value.first = Self::Real;
+      else if( param_type_str == "Index" )
+        value.first = Self::Index;
+      else if( param_type_str == "Point" )
+        value.first = Self::Point;
+      else if( param_type_str == "Vector" )
+        value.first = Self::Vector;
+      else if( param_type_str == "StringList" )
+        value.first = Self::StringList;
+      else if( param_type_str == "BoolList" )
+        value.first = Self::BoolList;
+      else if( param_type_str == "IntList" )
+        value.first = Self::IntList;
+      else if( param_type_str == "UintList" )
+        value.first = Self::UintList;
+      else if( param_type_str == "RealList" )
+        value.first = Self::RealList;
+      else if( param_type_str == "IndexList" )
+        value.first = Self::IndexList;
+      else if( param_type_str == "PointList" )
+        value.first = Self::PointList;
+      else if( param_type_str == "VectorList" )
+        value.first = Self::VectorList;
+      else if( param_type_str == "Choices" )
+        value.first = Self::Choices;
+      else
+        value.first = Self::String;
+
+      this->m_Parameters[ param_name ] = value;
+
+    } // fi
+    param = param->NextSiblingElement( "parameter" );
+    ret = true;
+
+  } // elihw
+  return( ret );
+}
+
 // -------------------------------------------------------------------------
 cpPlugins::Interface::Parameters::
 Parameters( )
diff --git a/lib/cpPlugins/Interface/Parameters.h b/lib/cpPlugins/Interface/Parameters.h
index dfcfc79..d8a1f57 100644
--- a/lib/cpPlugins/Interface/Parameters.h
+++ b/lib/cpPlugins/Interface/Parameters.h
@@ -11,6 +11,8 @@
 #include <itkObject.h>
 #include <itkObjectFactory.h>
 
+class TiXmlElement;
+
 namespace cpPlugins
 {
   namespace Interface
@@ -204,6 +206,9 @@ namespace cpPlugins
 
       bool SetSelectedChoice( const TString& name, const TString& choice );
 
+      bool ToXML( TiXmlElement* parent_elem ) const;
+      bool FromXML( const TiXmlElement* filter_elem );
+
     protected:
       Parameters( );
       virtual ~Parameters( );
diff --git a/lib/cpPlugins/Interface/Workspace.cxx b/lib/cpPlugins/Interface/Workspace.cxx
index dfe66d9..be724ac 100644
--- a/lib/cpPlugins/Interface/Workspace.cxx
+++ b/lib/cpPlugins/Interface/Workspace.cxx
@@ -3,7 +3,7 @@
 // -------------------------------------------------------------------------
 cpPlugins::Interface::Workspace::
 Workspace( )
-  : m_Interface( NULL )
+  : m_Plugins( NULL )
 {
   this->m_Graph = TGraph::New( );
 }
@@ -16,26 +16,26 @@ cpPlugins::Interface::Workspace::
 
 // -------------------------------------------------------------------------
 cpPlugins::Interface::Workspace::
-TInterface* cpPlugins::Interface::Workspace::
-GetInterface( )
+TPlugins* cpPlugins::Interface::Workspace::
+GetPlugins( )
 {
-  return( this->m_Interface );
+  return( this->m_Plugins );
 }
 
 // -------------------------------------------------------------------------
-void cpPlugins::Interface::Workspace::
-SetInterface( TInterface* i )
+const cpPlugins::Interface::Workspace::
+TPlugins* cpPlugins::Interface::Workspace::
+GetPlugins( ) const
 {
-  if( this->m_Interface != i )
-    this->m_Interface = i;
+  return( this->m_Plugins );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::Interface::Workspace::
-Clear( )
+SetPlugins( TPlugins* i )
 {
-  if( this->m_Graph.IsNotNull( ) )
-    this->m_Graph->Clear( );
+  if( this->m_Plugins != i )
+    this->m_Plugins = i;
 }
 
 // -------------------------------------------------------------------------
@@ -54,17 +54,65 @@ GetGraph( ) const
   return( this->m_Graph );
 }
 
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+Clear( )
+{
+  if( this->m_Graph.IsNotNull( ) )
+    this->m_Graph->Clear( );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+ClearConnections( )
+{
+}
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Workspace::
+TFilter* cpPlugins::Interface::Workspace::
+GetFilter( const std::string& name )
+{
+  TFilter* f =
+    dynamic_cast< TFilter* >(
+      this->m_Graph->GetVertex( name ).GetPointer( )
+      );
+  return( f );
+}
+
+// -------------------------------------------------------------------------
+const cpPlugins::Interface::Workspace::
+TFilter* cpPlugins::Interface::Workspace::
+GetFilter( const std::string& name ) const
+{
+  const TFilter* f =
+    dynamic_cast< const TFilter* >(
+      this->m_Graph->GetVertex( name ).GetPointer( )
+      );
+  return( f );
+}
+
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+HasFilter( const std::string& name ) const
+{
+  if( this->m_Graph->HasVertexIndex( name ) )
+    return( this->GetFilter( name ) != NULL );
+  else
+    return( false );
+}
+
 // -------------------------------------------------------------------------
 bool cpPlugins::Interface::Workspace::
 CreateFilter( const std::string& filter, const std::string& name )
 {
-  if( this->m_Interface == NULL )
+  if( this->m_Plugins == NULL )
     return( false );
 
   // Get or create new filter from name
   if( !( this->m_Graph->HasVertexIndex( name ) ) )
   {
-    TFilter::Pointer f = this->m_Interface->CreateObject( filter );
+    TFilter::Pointer f = this->m_Plugins->CreateObject( filter );
     if( f.IsNotNull( ) )
     {
       f->SetName( name );
@@ -79,6 +127,26 @@ CreateFilter( const std::string& filter, const std::string& name )
     return( true );
 }
 
+// -------------------------------------------------------------------------
+bool cpPlugins::Interface::Workspace::
+RenameFilter( const std::string& old_name, const std::string& new_name )
+{
+  if( this->m_Graph->RenameVertex( old_name, new_name ) )
+  {
+    TFilter* f = this->GetFilter( new_name );
+    f->SetName( new_name );
+    return( true );
+  }
+  else
+    return( false );
+}
+
+// -------------------------------------------------------------------------
+void cpPlugins::Interface::Workspace::
+RemoveFilter( const std::string& name )
+{
+}
+
 // -------------------------------------------------------------------------
 bool cpPlugins::Interface::Workspace::
 Connect(
@@ -94,7 +162,7 @@ Connect(
 
   // Real connection
   dest->SetInput( input_name, orig->GetOutput< TData >( output_name ) );
-  this->m_Graph->AddConnection(
+  this->m_Graph->AddEdge(
     orig_filter, dest_filter,
     TConnection( output_name, input_name )
     );
@@ -105,8 +173,8 @@ Connect(
 bool cpPlugins::Interface::Workspace::
 Connect( TData* input_object, const std::string& input_name )
 {
-  auto port = this->m_InputPorts.find( input_name );
-  if( port != this->m_InputPorts.end( ) )
+  auto port = this->m_ExposedInputPorts.find( input_name );
+  if( port != this->m_ExposedInputPorts.end( ) )
   {
     TFilter* filter = this->GetFilter( port->second.first );
     if( filter != NULL )
@@ -122,99 +190,100 @@ Connect( TData* input_object, const std::string& input_name )
 }
 
 // -------------------------------------------------------------------------
-cpPlugins::Interface::Workspace::
-TParameters* cpPlugins::Interface::Workspace::
-GetParameters( const std::string& name )
+bool cpPlugins::Interface::Workspace::
+Reduce( const std::string& name )
 {
-  TFilter* f = this->GetFilter( name );
-  if( f != NULL )
-    return( f->GetParameters( ) );
-  else
-    return( NULL );
+  return( false );
 }
 
 // -------------------------------------------------------------------------
-const cpPlugins::Interface::Workspace::
-TParameters* cpPlugins::Interface::Workspace::
-GetParameters( const std::string& name ) const
+void cpPlugins::Interface::Workspace::
+ExposeInputPort(
+  const std::string& name,
+  const std::string& filter, const std::string& filter_input
+  )
 {
-  const TFilter* f = this->GetFilter( name );
-  if( f != NULL )
-    return( f->GetParameters( ) );
-  else
-    return( NULL );
+  this->m_ExposedInputPorts[ name ] = TExposedPort( filter, filter_input );
 }
 
 // -------------------------------------------------------------------------
-cpPlugins::Interface::Workspace::
-TFilter* cpPlugins::Interface::Workspace::
-GetFilter( const std::string& name )
+void cpPlugins::Interface::Workspace::
+ExposeOutputPort(
+  const std::string& name,
+  const std::string& filter, const std::string& filter_output
+  )
 {
-  TFilter* f =
-    dynamic_cast< TFilter* >(
-      this->m_Graph->GetVertex( name ).GetPointer( )
-      );
-  return( f );
+  this->m_ExposedOutputPorts[ name ] = TExposedPort( filter, filter_output );
 }
 
 // -------------------------------------------------------------------------
-const cpPlugins::Interface::Workspace::
-TFilter* cpPlugins::Interface::Workspace::
-GetFilter( const std::string& name ) const
+void cpPlugins::Interface::Workspace::
+HideInputPort( const std::string& name )
 {
-  const TFilter* f =
-    dynamic_cast< const TFilter* >(
-      this->m_Graph->GetVertex( name ).GetPointer( )
-      );
-  return( f );
+  auto i = this->m_ExposedInputPorts.find( name );
+  if( i != this->m_ExposedInputPorts.end( ) )
+    this->m_ExposedInputPorts.erase( i );
 }
 
 // -------------------------------------------------------------------------
-bool cpPlugins::Interface::Workspace::
-HasFilter( const std::string& name ) const
+void cpPlugins::Interface::Workspace::
+HideOutputPort( const std::string& name )
 {
-  if( this->m_Graph->HasVertexIndex( name ) )
-    return( this->GetFilter( name ) != NULL );
-  else
-    return( false );
+  auto i = this->m_ExposedOutputPorts.find( name );
+  if( i != this->m_ExposedOutputPorts.end( ) )
+    this->m_ExposedOutputPorts.erase( i );
 }
 
 // -------------------------------------------------------------------------
 bool cpPlugins::Interface::Workspace::
-Reduce( const std::string& name )
-{
-  return( false );
-}
-
-// -------------------------------------------------------------------------
-void cpPlugins::Interface::Workspace::
-AddInputPort(
-  const std::string& name,
-  const std::string& filter, const std::string& filter_input
+RenameExposedInputPort(
+  const std::string& old_name,
+  const std::string& new_name
   )
 {
-  std::cout << name << " " << filter << " " << filter_input << std::endl;
-
-  this->m_InputPorts[ name ] = TGlobalPort( filter, filter_input );
+  auto o = this->m_ExposedInputPorts.find( old_name );
+  auto n = this->m_ExposedInputPorts.find( new_name );
+  if(
+    o != this->m_ExposedInputPorts.end( ) &&
+    n == this->m_ExposedInputPorts.end( )
+    )
+  {
+    this->m_ExposedInputPorts[ new_name ] = o->second;
+    this->m_ExposedInputPorts.erase( o );
+  }
+  else
+    return( false );
 }
 
 // -------------------------------------------------------------------------
-void cpPlugins::Interface::Workspace::
-AddOutputPort(
-  const std::string& name,
-  const std::string& filter, const std::string& filter_output
+bool cpPlugins::Interface::Workspace::
+RenameExposedOutputPort(
+  const std::string& old_name,
+  const std::string& new_name
   )
 {
-  this->m_OutputPorts[ name ] = TGlobalPort( filter, filter_output );
+  auto o = this->m_ExposedOutputPorts.find( old_name );
+  auto n = this->m_ExposedOutputPorts.find( new_name );
+  if(
+    o != this->m_ExposedOutputPorts.end( ) &&
+    n == this->m_ExposedOutputPorts.end( )
+    )
+  {
+    this->m_ExposedOutputPorts[ new_name ] = o->second;
+    this->m_ExposedOutputPorts.erase( o );
+  }
+  else
+    return( false );
 }
 
 // -------------------------------------------------------------------------
+/* TODO
 cpPlugins::Interface::Workspace::
 TData* cpPlugins::Interface::Workspace::
 GetOutput( const std::string& name )
 {
-  auto port = this->m_OutputPorts.find( name );
-  if( port != this->m_OutputPorts.end( ) )
+  auto port = this->m_ExposedOutputPorts.find( name );
+  if( port != this->m_ExposedOutputPorts.end( ) )
   {
     TFilter* f = this->GetFilter( port->second.first );
     if( f != NULL )
@@ -231,8 +300,8 @@ const cpPlugins::Interface::Workspace::
 TData* cpPlugins::Interface::Workspace::
 GetOutput( const std::string& name ) const
 {
-  auto port = this->m_OutputPorts.find( name );
-  if( port != this->m_OutputPorts.end( ) )
+  auto port = this->m_ExposedOutputPorts.find( name );
+  if( port != this->m_ExposedOutputPorts.end( ) )
   {
     const TFilter* f = this->GetFilter( port->second.first );
     if( f != NULL )
@@ -248,19 +317,20 @@ GetOutput( const std::string& name ) const
 void cpPlugins::Interface::Workspace::
 ClearInputPorts( )
 {
-  this->m_InputPorts.clear( );
+  this->m_ExposedInputPorts.clear( );
 }
 
 // -------------------------------------------------------------------------
 void cpPlugins::Interface::Workspace::
 ClearOutputPorts( )
 {
-  this->m_OutputPorts.clear( );
+  this->m_ExposedOutputPorts.clear( );
 }
+*/
 
 // -------------------------------------------------------------------------
 std::string cpPlugins::Interface::Workspace::
-Execute( )
+Execute( QWidget* p )
 {
   // Find sinks
   std::set< std::string > sinks = this->m_Graph->GetSinks( );
@@ -269,7 +339,7 @@ Execute( )
   std::string err = "";
   for( auto sIt = sinks.begin( ); sIt != sinks.end( ); ++sIt )
   {
-    std::string lerr = this->Execute( *sIt, NULL );
+    std::string lerr = this->Execute( *sIt, p );
     if( lerr != "" )
       err += lerr + std::string( "\n" );
 
diff --git a/lib/cpPlugins/Interface/Workspace.h b/lib/cpPlugins/Interface/Workspace.h
index 919233f..1f2fada 100644
--- a/lib/cpPlugins/Interface/Workspace.h
+++ b/lib/cpPlugins/Interface/Workspace.h
@@ -16,12 +16,12 @@ namespace cpPlugins
 {
   namespace Interface
   {
-    /**
+    /** \brief A complex pipeline
      */
     class cpPlugins_Interface_EXPORT Workspace
     {
     public:
-      typedef cpPlugins::Interface::Interface     TInterface;
+      typedef cpPlugins::Interface::Interface     TPlugins;
       typedef cpPlugins::Interface::Object        TObject;
       typedef cpPlugins::Interface::ProcessObject TFilter;
       typedef cpPlugins::Interface::DataObject    TData;
@@ -29,8 +29,8 @@ namespace cpPlugins
 
       // Various types
       typedef std::set< std::string >               TStringContainer;
-      typedef std::pair< std::string, std::string > TGlobalPort;
-      typedef std::map< std::string, TGlobalPort >  TGlobalPorts;
+      typedef std::pair< std::string, std::string > TExposedPort;
+      typedef std::map< std::string, TExposedPort > TExposedPorts;
 
       // Graph type
       typedef std::pair< std::string, std::string > TConnection;
@@ -43,57 +43,82 @@ namespace cpPlugins
       virtual ~Workspace( );
 
       // Plugins management
-      TInterface* GetInterface( );
-      void SetInterface( TInterface* i );
+      TPlugins* GetPlugins( );
+      const TPlugins* GetPlugins( ) const;
+      void SetPlugins( TPlugins* i );
 
       // Workspace IO
       std::string LoadWorkspace( const std::string& fname );
       std::string SaveWorkspace( const std::string& fname ) const;
 
       // Graph management
-      void Clear( );
       TGraph* GetGraph( );
       const TGraph* GetGraph( ) const;
+
+      void Clear( );
+      void ClearConnections( );
+
+      // Filter management
+      TFilter* GetFilter( const std::string& name );
+      const TFilter* GetFilter( const std::string& name ) const;
+      bool HasFilter( const std::string& name ) const;
       bool CreateFilter( const std::string& filter, const std::string& name );
+      bool RenameFilter(
+        const std::string& old_name, const std::string& new_name
+        );
+      void RemoveFilter( const std::string& name );
+
+      // Connection management
       bool Connect(
         const std::string& orig_filter, const std::string& dest_filter,
-        const std::string& output_name,
-        const std::string& input_name
+        const std::string& output_name, const std::string& input_name
         );
-      bool Connect( TData* input_object, const std::string& input_name );
-      TParameters* GetParameters( const std::string& name );
-      const TParameters* GetParameters( const std::string& name ) const;
-      TFilter* GetFilter( const std::string& name );
-      const TFilter* GetFilter( const std::string& name ) const;
-      bool HasFilter( const std::string& name ) const;
+      bool Connect( TData* input_object, const std::string& exposed_port );
+      void RemoveConnection(
+        const std::string& dest_filter, const std::string& input_name
+        );
+      void RemoveConnection( const std::string& exposed_port );
+      void RemoveConnections( const std::string& dest_filter );
 
       // Graph reduction
       bool Reduce( const std::string& name );
-      void AddInputPort(
+      void ExposeInputPort(
         const std::string& name,
         const std::string& filter, const std::string& filter_input
         );
-      void AddOutputPort(
+      void ExposeOutputPort(
         const std::string& name,
         const std::string& filter, const std::string& filter_output
         );
-      TData* GetOutput( const std::string& name );
-      const TData* GetOutput( const std::string& name ) const;
-      void ClearInputPorts( );
-      void ClearOutputPorts( );
+      void HideInputPort( const std::string& name );
+      void HideOutputPort( const std::string& name );
+
+      bool RenameExposedInputPort(
+        const std::string& old_name,
+        const std::string& new_name
+        );
+      bool RenameExposedOutputPort(
+        const std::string& old_name,
+        const std::string& new_name
+        );
+
+      TData* GetExposedInput( const std::string& name );
+      const TData* GetExposedInput( const std::string& name ) const;
+      TData* GetExposedOutput( const std::string& name );
+      const TData* GetExposedOutput( const std::string& name ) const;
 
       // Pipeline execution
-      std::string Execute( );
+      std::string Execute( QWidget* p = NULL );
       std::string Execute( const std::string& name, QWidget* p = NULL );
 
     protected:
       // Plugins interface
-      TInterface* m_Interface;
+      TPlugins* m_Plugins;
 
       // Processing graph
       typename TGraph::Pointer m_Graph;
-      TGlobalPorts m_InputPorts;
-      TGlobalPorts m_OutputPorts;
+      TExposedPorts m_ExposedInputPorts;
+      TExposedPorts m_ExposedOutputPorts;
     };
 
   } // ecapseman
diff --git a/lib/cpPlugins/Interface/WorkspaceIO.cxx b/lib/cpPlugins/Interface/WorkspaceIO.cxx
index 7e7a2bd..1d0ea81 100644
--- a/lib/cpPlugins/Interface/WorkspaceIO.cxx
+++ b/lib/cpPlugins/Interface/WorkspaceIO.cxx
@@ -32,61 +32,7 @@ LoadWorkspace( const std::string& fname )
 
         // Read parameters
         TParameters* parameters = new_filter->GetParameters( );
-        parameters->Clear( );
-
-        TiXmlElement* param = filter->FirstChildElement( "parameter" );
-        while( param != NULL )
-        {
-          const char* param_name = param->Attribute( "name" );
-          const char* param_type = param->Attribute( "type" );
-          if( param_name != NULL && param_type != NULL )
-          {
-            std::string param_type_str( param_type );
-            const char* value = param->Attribute( "value" );
-            if( value != NULL )
-            {
-              if( param_type_str == "String" )
-                parameters->ConfigureAsString( param_name );
-              else if( param_type_str == "Bool" )
-                parameters->ConfigureAsBool( param_name );
-              else if( param_type_str == "Int" )
-                parameters->ConfigureAsInt( param_name );
-              else if( param_type_str == "Uint" )
-                parameters->ConfigureAsUint( param_name );
-              else if( param_type_str == "Real" )
-                parameters->ConfigureAsReal( param_name );
-              else if( param_type_str == "Index" )
-                parameters->ConfigureAsIndex( param_name );
-              else if( param_type_str == "Point" )
-                parameters->ConfigureAsPoint( param_name );
-              else if( param_type_str == "Vector" )
-                parameters->ConfigureAsVector( param_name );
-              else if( param_type_str == "StringList" )
-                parameters->ConfigureAsStringList( param_name );
-              else if( param_type_str == "BoolList" )
-                parameters->ConfigureAsBoolList( param_name );
-              else if( param_type_str == "IntList" )
-                parameters->ConfigureAsIntList( param_name );
-              else if( param_type_str == "UintList" )
-                parameters->ConfigureAsUintList( param_name );
-              else if( param_type_str == "RealList" )
-                parameters->ConfigureAsRealList( param_name );
-              else if( param_type_str == "IndexList" )
-                parameters->ConfigureAsIndexList( param_name );
-              else if( param_type_str == "PointList" )
-                parameters->ConfigureAsPointList( param_name );
-              else if( param_type_str == "VectorList" )
-                parameters->ConfigureAsVectorList( param_name );
-              else if( param_type_str == "Choices" )
-                parameters->ConfigureAsChoices( param_name );
-              parameters->SetString( param_name, value, false );
-
-            } // fi
-
-          } // fi
-          param = param->NextSiblingElement( "parameter" );
-
-        } // elihw
+        parameters->FromXML( filter );
       }
       else
         err
@@ -122,6 +68,33 @@ LoadWorkspace( const std::string& fname )
 
   } // elihw
 
+  // Read exposed inputs
+  TiXmlElement* port = root->FirstChildElement( "exposed_input_port" );
+  while( port != NULL )
+  {
+    this->ExposeInputPort(
+      port->Attribute( "port_name" ),
+      port->Attribute( "filter" ),
+      port->Attribute( "filter_port_name" )
+      );
+    port = connection->NextSiblingElement( "exposed_input_port" );
+
+  } // elihw
+
+  // Read exposed outputs
+#error ACA VOY
+  port = root->FirstChildElement( "exposed_output_port" );
+  while( port != NULL )
+  {
+    this->ExposeOutputPort(
+      port->Attribute( "port_name" ),
+      port->Attribute( "filter" ),
+      port->Attribute( "filter_port_name" )
+      );
+    port = connection->NextSiblingElement( "exposed_output_port" );
+
+  } // elihw
+
   // Finish and return
   delete doc;
   return( err.str( ) );
@@ -150,52 +123,8 @@ SaveWorkspace( const std::string& fname ) const
       e->SetAttribute( "ViewY", filter->GetViewY( ) );
 
       const TParameters* params = filter->GetParameters( );
-      std::vector< std::string > names;
-      params->GetNames( names );
-      for( auto nIt = names.begin( ); nIt != names.end( ); ++nIt )
-      {
-        TiXmlElement* p = new TiXmlElement( "parameter" );
-        p->SetAttribute( "name", nIt->c_str( ) );
-        if( params->HasString( *nIt ) )
-          p->SetAttribute( "type", "String" );
-        else if( params->HasBool( *nIt ) ) 
-          p->SetAttribute( "type", "Bool" );
-        else if( params->HasInt( *nIt ) )
-          p->SetAttribute( "type", "Int" );
-        else if( params->HasUint( *nIt ) )
-          p->SetAttribute( "type", "Uint" );
-        else if( params->HasReal( *nIt ) )
-          p->SetAttribute( "type", "Real" );
-        else if( params->HasIndex( *nIt ) )
-          p->SetAttribute( "type", "Index" );
-        else if( params->HasPoint( *nIt ) )
-          p->SetAttribute( "type", "Point" );
-        else if( params->HasVector( *nIt ) )
-          p->SetAttribute( "type", "Vector" );
-        else if( params->HasStringList( *nIt ) )
-          p->SetAttribute( "type", "StringList" );
-        else if( params->HasBoolList( *nIt ) )
-          p->SetAttribute( "type", "BoolList" );
-        else if( params->HasIntList( *nIt ) )
-          p->SetAttribute( "type", "IntList" );
-        else if( params->HasUintList( *nIt ) )
-          p->SetAttribute( "type", "UintList" );
-        else if( params->HasRealList( *nIt ) )
-          p->SetAttribute( "type", "RealList" );
-        else if( params->HasIndexList( *nIt ) )
-          p->SetAttribute( "type", "IndexList" );
-        else if( params->HasPointList( *nIt ) )
-          p->SetAttribute( "type", "PointList" );
-        else if( params->HasVectorList( *nIt ) )
-          p->SetAttribute( "type", "VectorList" );
-        else if( params->HasChoices( *nIt ) )
-          p->SetAttribute( "type", "Choices" );
-        p->SetAttribute(
-          "value", params->GetString( *nIt, false ).c_str( )
-          );
-        e->LinkEndChild( p );
+      params->ToXML( e );
 
-      } // rof
       root->LinkEndChild( e );
     }
     else if( data != NULL )
@@ -233,6 +162,29 @@ SaveWorkspace( const std::string& fname ) const
 
   } // rof
 
+  // Save exposed ports
+  auto eipIt = this->m_ExposedInputPorts.begin( );
+  for( ; eipIt != this->m_ExposedInputPorts.end( ); ++eipIt )
+  {
+    TiXmlElement* port = new TiXmlElement( "exposed_input_port" );
+    port->SetAttribute( "port_name", eipIt->first.c_str( ) );
+    port->SetAttribute( "filter", eipIt->second.first.c_str( ) );
+    port->SetAttribute( "filter_port_name", eipIt->second.second.c_str( ) );
+    root->LinkEndChild( port );
+
+  } // rof
+
+  auto eopIt = this->m_ExposedOutputPorts.begin( );
+  for( ; eopIt != this->m_ExposedOutputPorts.end( ); ++eopIt )
+  {
+    TiXmlElement* port = new TiXmlElement( "exposed_output_port" );
+    port->SetAttribute( "port_name", eopIt->first.c_str( ) );
+    port->SetAttribute( "filter", eopIt->second.first.c_str( ) );
+    port->SetAttribute( "filter_port_name", eopIt->second.second.c_str( ) );
+    root->LinkEndChild( port );
+
+  } // rof
+
   // Physical write and return
   doc->LinkEndChild( root );
   doc->SaveFile( fname.c_str( ) );
-- 
2.49.0