瀏覽代碼

ENH: Fasten ctkVTKConnection by not observing vtk delete events (optional).

ctkVTKConnection can now be used without ctkVTKObjectEventsObserver.
Use ctkVTKConnection::observeDeletion(false) to observe vtkCommand::DeleteEvent
and automatically disconnect.
Julien Finet 15 年之前
父節點
當前提交
023fbc3c60

+ 3 - 1
Libs/Visualization/VTK/Core/Testing/Cpp/CMakeLists.txt

@@ -41,6 +41,7 @@ CREATE_TEST_SOURCELIST(Tests ${KIT}CppTests.cpp
   ctkVTKCommandOptionsTest1.cpp
   ctkVTKConnectionTest1.cpp
   ctkVTKObjectTest1.cpp
+  ctkVTKObjectEventsObserverTest1.cpp
   #EXTRA_INCLUDE TestingMacros.h
   )
 
@@ -66,8 +67,9 @@ ENDMACRO( SIMPLE_TEST  )
 # Add Tests
 #
 
-SIMPLE_TEST( ctkVTKObjectTest1 )
 SIMPLE_TEST( ctkVTKConnectionTest1 )
+SIMPLE_TEST( ctkVTKObjectTest1 )
+SIMPLE_TEST( ctkVTKObjectEventsObserverTest1 )
 
 ADD_TEST( ctkVTKCommandOptionsTest1 ${KIT_TESTS}
           ctkVTKCommandOptionsTest1 --help )

+ 82 - 25
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKConnectionTest1.cpp

@@ -2,7 +2,8 @@
 // Qt includes
 #include <QApplication>
 #include <QDebug>
-#include <QWidget>
+#include <QList>
+#include <QTimer>
 
 // CTKVTK includes
 #include "ctkVTKConnection.h"
@@ -20,26 +21,57 @@
 
 void doit(vtkObject* obj, unsigned long event, void* client_data, void* param)
 {
-  QWidget* w = reinterpret_cast<QWidget*>(client_data);
-  w->setFocus();
+  QTimer* t = reinterpret_cast<QTimer*>(client_data);
+  t->stop();
 }
 
 int ctkVTKConnectionTest1( int argc, char * argv [] )
 {
   QApplication app(argc, argv);
-  vtkObject* obj = vtkObject::New();
-  QWidget topLevelWidget;
-
+  
   int objects = 1000;
   int events = 100;
   
+  vtkObject* obj = vtkObject::New();
+  vtkObject* obj2 = vtkObject::New();
+  vtkObject* obj3 = vtkObject::New();
+  vtkObject* obj4 = vtkObject::New();
+  vtkObject* obj5 = vtkObject::New();
+
+  QObject*   topObject = new QObject(0);
+  // It could be here any kind of Qt object, QTimer has a no op slot so use it
+  QTimer*    slotObject = new QTimer(topObject);
+  
   for (int i = 0; i < objects; ++i)
     {
-    ctkVTKConnection* objectTest = new ctkVTKConnection(&topLevelWidget);
-    objectTest->SetParameters(obj, vtkCommand::ModifiedEvent,
-                              &topLevelWidget, SLOT(setFocus()));
-    objectTest->setEnabled(true);
+    ctkVTKConnection* connection = new ctkVTKConnection(topObject);
+    connection->observeDeletion(false);
+    connection->setup(obj, vtkCommand::ModifiedEvent,
+                      slotObject, SLOT(stop()));
+
+    vtkCallbackCommand* callback = vtkCallbackCommand::New();
+    callback->SetClientData(slotObject);
+    callback->SetCallback(doit);
+    
+    obj2->AddObserver(vtkCommand::ModifiedEvent, callback);
+    callback->Delete();
+
+    ctkVTKConnection* connection2 = new ctkVTKConnection(topObject);
+    connection2->observeDeletion(true);
+    connection2->setup(obj3, vtkCommand::ModifiedEvent,
+                      slotObject, SLOT(stop()));
+
+    ctkVTKConnection* connection3 = new ctkVTKConnection(topObject);
+    connection3->observeDeletion(false);
+    connection3->setup(obj4, vtkCommand::ModifiedEvent,
+                      new QTimer(topObject), SLOT(stop()));
+    
+    ctkVTKConnection* connection4 = new ctkVTKConnection(topObject);
+    connection4->observeDeletion(true);
+    connection4->setup(obj5, vtkCommand::ModifiedEvent,
+                      slotObject, SLOT(stop()));
     }
+
   vtkSmartPointer<vtkTimerLog> timerLog = 
     vtkSmartPointer<vtkTimerLog>::New();
   
@@ -53,18 +85,8 @@ int ctkVTKConnectionTest1( int argc, char * argv [] )
   double t1 = timerLog->GetElapsedTime();
   qDebug() << events << "events listened by" << objects << "objects (ctkVTKConnection): " << t1 << "seconds";
 
-  obj->Delete();
+  // Callback only
 
-  vtkObject* obj2 = vtkObject::New();
-  for (int i = 0; i < objects; ++i)
-    {
-    vtkCallbackCommand* callback = vtkCallbackCommand::New();
-    callback->SetClientData(&topLevelWidget);
-    callback->SetCallback(doit);
-    
-    obj2->AddObserver(vtkCommand::ModifiedEvent, callback);
-    callback->Delete();
-    }
   vtkSmartPointer<vtkTimerLog> timerLog2 = 
     vtkSmartPointer<vtkTimerLog>::New();
   timerLog2->StartTimer();
@@ -78,12 +100,47 @@ int ctkVTKConnectionTest1( int argc, char * argv [] )
   qDebug() << events << "events listened by" << objects <<"objects (vtkCallbacks): " << t2 << "seconds";
   double ratio = t1 / t2;
   qDebug() << "ctkVTKConnection / vtkCallbacks: " << ratio;
-  // Ideally a ratio of 2 (a callback and a signal/slot connection is used 
-  // is used in ctkVTKConnection
-  if (ratio > 2.5)
+
+  vtkSmartPointer<vtkTimerLog> timerLog3 = 
+    vtkSmartPointer<vtkTimerLog>::New();
+  
+  timerLog3->StartTimer();
+  for (int i = 0; i < events; ++i)
     {
-    return EXIT_FAILURE;
+    obj3->Modified();
+    }
+  timerLog3->StopTimer();
+  
+  double t3 = timerLog3->GetElapsedTime();
+  qDebug() << events << "events listened by" << objects << "objects (observed ctkVTKConnection): " << t3 << "seconds";
+
+  vtkSmartPointer<vtkTimerLog> timerLog4 = 
+    vtkSmartPointer<vtkTimerLog>::New();
+  
+  timerLog4->StartTimer();
+  for (int i = 0; i < events; ++i)
+    {
+    obj4->Modified();
     }
+  timerLog4->StopTimer();
+  
+  double t4 = timerLog4->GetElapsedTime();
+  qDebug() << events << "events listened by" << objects << "objects (ctkVTKConnection, 1-1): " << t4 << "seconds";
+
+
+  obj->Delete();
   obj2->Delete();
+  obj3->Delete();
+
+  delete topObject;
+
+  obj4->Delete();
+  obj5->Delete();
+  
+  // Ideally a ratio ~= 1. but the ratio can be more in Debug mode... up to 2.
+  if (ratio > 2.)
+    {
+    return EXIT_FAILURE;
+    }
   return EXIT_SUCCESS;
 }

+ 58 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKObjectEventsObserverTest1.cpp

@@ -0,0 +1,58 @@
+
+// Qt includes
+#include <QApplication>
+#include <QDebug>
+#include <QList>
+#include <QTimer>
+
+// CTKVTK includes
+#include "ctkVTKObjectEventsObserver.h"
+
+// STD includes
+#include <cstdlib>
+#include <iostream>
+
+// VTK includes
+#include <vtkCallbackCommand.h>
+#include <vtkCommand.h>
+#include <vtkObject.h>
+#include <vtkSmartPointer.h>
+#include <vtkTimerLog.h>
+
+int ctkVTKObjectEventsObserverTest1( int argc, char * argv [] )
+{
+  QApplication app(argc, argv);
+  
+  int objects = 1000;
+  int events = 100;
+  
+  vtkObject* obj = vtkObject::New();
+  QObject*   topObject = new QObject(0);
+  
+  ctkVTKObjectEventsObserver* observer = new ctkVTKObjectEventsObserver(topObject);
+  for (int i = 0; i < objects; ++i)
+    {
+    QTimer*    slotObject = new QTimer(topObject);
+    observer->addConnection(obj, vtkCommand::ModifiedEvent,
+      slotObject, SLOT(stop()));
+    }
+
+  vtkSmartPointer<vtkTimerLog> timerLog = 
+    vtkSmartPointer<vtkTimerLog>::New();
+  
+  timerLog->StartTimer();
+  for (int i = 0; i < events; ++i)
+    {
+    obj->Modified();
+    }
+  timerLog->StopTimer();
+  
+  double t1 = timerLog->GetElapsedTime();
+  qDebug() << events << "events listened by" << objects << "objects (ctkVTKConnection): " << t1 << "seconds";
+
+  obj->Delete();
+
+  delete topObject;
+  
+  return EXIT_SUCCESS;
+}

+ 1 - 0
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKObjectTest1.cpp

@@ -20,3 +20,4 @@ int ctkVTKObjectTest1( int argc, char * argv [] )
     }
   return EXIT_SUCCESS;
 }
+

+ 12 - 5
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKObjectTestHelper.cpp

@@ -28,7 +28,8 @@ ctkVTKObjectTestPrivate::ctkVTKObjectTestPrivate()
 }
 
 //------------------------------------------------------------------------------
-ctkVTKObjectTest::ctkVTKObjectTest()
+ctkVTKObjectTest::ctkVTKObjectTest(QObject* parentObject)
+:QObject(parentObject)
 {
   CTK_INIT_PRIVATE(ctkVTKObjectTest);
 }
@@ -224,29 +225,35 @@ void ctkVTKObjectTest::resetSlotCalls()
 }
 
 //------------------------------------------------------------------------------
+void ctkVTKObjectTest::emitSignalEmitted()
+{
+  emit signalEmitted();
+}
+
+//------------------------------------------------------------------------------
 void ctkVTKObjectTest::onVTKObjectModifiedPublic()
 {
-  qDebug() << __FUNCTION__;
+  //qDebug() << __FUNCTION__;
   ctk_d()->PublicSlotCalled = true;
 }
 
 //------------------------------------------------------------------------------
 void ctkVTKObjectTest::deleteConnection()
 {
-  qDebug() << __FUNCTION__;
+  //qDebug() << __FUNCTION__;
   this->qvtkDisconnect(0, vtkCommand::NoEvent, 0, 0);
 }
 
 //------------------------------------------------------------------------------
 void ctkVTKObjectTest::onVTKObjectModifiedProtected()
 {
-  qDebug() << __FUNCTION__;
+  //qDebug() << __FUNCTION__;
   ctk_d()->ProtectedSlotCalled = true;
 }
 
 //------------------------------------------------------------------------------
 void ctkVTKObjectTest::onVTKObjectModifiedPrivate()
 {
-  qDebug() << __FUNCTION__;
+  //qDebug() << __FUNCTION__;
   ctk_d()->PrivateSlotCalled = true;
 }

+ 2 - 1
Libs/Visualization/VTK/Core/Testing/Cpp/ctkVTKObjectTestHelper.h

@@ -17,7 +17,7 @@ class ctkVTKObjectTest: public QObject
   Q_OBJECT
   QVTK_OBJECT
 public:
-  ctkVTKObjectTest();
+  ctkVTKObjectTest(QObject* parent = 0);
 
   bool test();
 
@@ -27,6 +27,7 @@ public:
 
   void resetSlotCalls();
 
+  void emitSignalEmitted();
 public slots:
   void onVTKObjectModifiedPublic();
   void deleteConnection();

+ 456 - 447
Libs/Visualization/VTK/Core/ctkVTKConnection.cpp

@@ -1,447 +1,456 @@
-/*=========================================================================
-
-  Library:   CTK
- 
-  Copyright (c) 2010  Kitware Inc.
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-      http://www.commontk.org/LICENSE
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- 
-=========================================================================*/
-
-// Qt includes
-#include <QDebug>
-#include <QRegExp>
-#include <QString>
-#include <QTextStream>
-
-// CTK includes
-#include "ctkVTKConnection.h"
-
-// VTK includes
-#include <vtkObject.h>
-#include <vtkSmartPointer.h>
-#include <vtkCallbackCommand.h>
-
-//-----------------------------------------------------------------------------
-QString convertPointerToString(void* pointer)
-{
-  QString pointerAsString;
-  QTextStream(&pointerAsString) << pointer;
-  return pointerAsString;
-}
-
-//-----------------------------------------------------------------------------
-class ctkVTKConnectionPrivate: public ctkPrivate<ctkVTKConnection>
-{
-public:
-  enum
-    {
-    ARG_UNKNOWN = 0,
-    ARG_VTKOBJECT_AND_VTKOBJECT,
-    ARG_VTKOBJECT_VOID_ULONG_VOID
-    };
-
-  typedef ctkVTKConnectionPrivate Self;
-  ctkVTKConnectionPrivate();
-  ~ctkVTKConnectionPrivate();
-
-  void connect();
-  void disconnect();
-
-  /// 
-  /// VTK Callback
-  static void DoCallback(vtkObject* vtk_obj, unsigned long event,
-                         void* client_data, void* call_data);
-
-  /// 
-  /// Called by 'DoCallback' to emit signal
-  void Execute(vtkObject* vtk_obj, unsigned long vtk_event, void* client_data, void* call_data);
-
-  vtkSmartPointer<vtkCallbackCommand> Callback;
-  vtkObject*                          VTKObject;
-  const QObject*                      QtObject;
-  unsigned long                       VTKEvent;
-  QString                             QtSlot;
-  float                               Priority;
-  int                                 SlotType;
-  bool                                Connected;
-  bool                                Blocked;
-  QString                             Id;
-  bool                                AboutToBeDeleted;
-};
-
-//-----------------------------------------------------------------------------
-// ctkVTKConnectionPrivate methods
-
-//-----------------------------------------------------------------------------
-ctkVTKConnectionPrivate::ctkVTKConnectionPrivate()
-{
-  this->Callback    = vtkSmartPointer<vtkCallbackCommand>::New();
-  this->Callback->SetCallback(ctkVTKConnectionPrivate::DoCallback);
-  this->Callback->SetClientData(this);
-  this->VTKObject   = 0;
-  this->QtObject    = 0;
-  this->VTKEvent    = vtkCommand::NoEvent;
-  this->Priority    = 0.0;
-  this->SlotType    = ARG_UNKNOWN;
-  this->Connected   = false;
-  this->Blocked     = false;
-  this->Id          = convertPointerToString(this);
-  this->AboutToBeDeleted = false;
-}
-
-//-----------------------------------------------------------------------------
-ctkVTKConnectionPrivate::~ctkVTKConnectionPrivate()
-{
-  /*
-  if(this->VTKObject && this->Connected)
-    {
-    this->VTKObject->RemoveObserver(this->Callback);
-    //Qt takes care of disconnecting slots
-    }
-  */
-
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnectionPrivate::connect()
-{
-  CTK_P(ctkVTKConnection);
-  
-  if (this->Connected) 
-    {
-    qDebug() << "ctkVTKConnection already connected.";
-    return; 
-    }
-
-  switch (this->SlotType)
-    {
-    case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
-      QObject::connect(p, SIGNAL(emitExecute(vtkObject*, vtkObject*)),
-                       this->QtObject, this->QtSlot.toLatin1().data());
-      break;
-    case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
-      QObject::connect(p, SIGNAL(emitExecute(vtkObject*, void*, unsigned long, void*)),
-                       this->QtObject, this->QtSlot.toLatin1().data());
-      break;
-    default:
-      Q_ASSERT(false);
-      qCritical() << "Failed to connect - "
-                  << "The slot (" << this->QtSlot <<  ") owned by "
-                  << "QObject(" << this->QtObject->objectName() << ")"
-                  << " seems to have a wrong signature.";
-      break;
-    }
-
-  // Make a connection between this and the vtk object
-  this->VTKObject->AddObserver(this->VTKEvent, this->Callback, this->Priority);
-
-  // If necessary, observe vtk DeleteEvent
-  if(this->VTKEvent != vtkCommand::DeleteEvent)
-    {
-    this->VTKObject->AddObserver(vtkCommand::DeleteEvent, this->Callback);
-    }
-
-  // Remove itself from its parent when vtkObject is deleted
-  QObject::connect(this->QtObject, SIGNAL(destroyed(QObject*)), 
-                   p, SLOT(deleteConnection()));
-
-  this->Connected = true;
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnectionPrivate::disconnect()
-{
-  CTK_P(ctkVTKConnection);
-  
-  if (!this->Connected) 
-    { 
-    Q_ASSERT(this->Connected);
-    return; 
-    }
-
-  this->VTKObject->RemoveObserver(this->Callback);
-
-  switch (this->SlotType)
-    {
-    case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
-      QObject::disconnect(p, SIGNAL(emitExecute(vtkObject*, vtkObject*)),
-                          this->QtObject,this->QtSlot.toLatin1().data());
-      break;
-    case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
-      QObject::disconnect(p, SIGNAL(emitExecute(vtkObject*, void*, unsigned long, void*)),
-                          this->QtObject, this->QtSlot.toLatin1().data());
-      break;
-    default:
-      Q_ASSERT(false);
-      qCritical() << "Failed to disconnect - "
-                  << "The slot (" << this->QtSlot <<  ") owned by "
-                  << "QObject(" << this->QtObject->objectName() << ")"
-                  << " seems to have a wrong signature.";
-      break;
-    }
-
-  QObject::disconnect(this->QtObject, SIGNAL(destroyed(QObject*)),
-                      p, SLOT(deleteConnection()));
-
-  this->Connected = false;
-}
-
-//-----------------------------------------------------------------------------
-// ctkVTKConnection methods
-
-//-----------------------------------------------------------------------------
-ctkVTKConnection::ctkVTKConnection(QObject* _parent):
-  Superclass(_parent)
-{
-  CTK_INIT_PRIVATE(ctkVTKConnection);
-}
-
-//-----------------------------------------------------------------------------
-ctkVTKConnection::~ctkVTKConnection()
-{
-  this->setEnabled(false);
-}
-
-//-----------------------------------------------------------------------------
-CTK_GET_CXX(ctkVTKConnection, QString, id, Id);
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnection::printAdditionalInfo()
-{
-  this->Superclass::dumpObjectInfo();
-
-  CTK_D(ctkVTKConnection);
-  
-  qDebug() << "ctkVTKConnection:" << this << endl
-           << "Id:" << d->Id << endl
-           << " VTKObject:" << d->VTKObject->GetClassName()
-             << "(" << d->VTKObject << ")" << endl
-           << " QtObject:" << d->QtObject << endl
-           << " VTKEvent:" << d->VTKEvent << endl
-           << " QtSlot:" << d->QtSlot << endl
-           << " SlotType:" << d->SlotType << endl
-           << " Priority:" << d->Priority << endl
-           << " Connected:" << d->Connected << endl
-           << " Blocked:" << d->Blocked;
-}
-
-//-----------------------------------------------------------------------------
-QString ctkVTKConnection::shortDescription()
-{
-  CTK_D(ctkVTKConnection);
-  
-  return Self::shortDescription(d->VTKObject, d->VTKEvent, d->QtObject, d->QtSlot);
-}
-
-//-----------------------------------------------------------------------------
-QString ctkVTKConnection::shortDescription(vtkObject* vtk_obj, unsigned long vtk_event,
-    const QObject* qt_obj, QString qt_slot)
-{
-  QString ret;
-  QTextStream ts( &ret );
-  ts << (vtk_obj ? vtk_obj->GetClassName() : "NULL") << " "
-     << vtk_event << " " << qt_obj << " " << qt_slot;
-  return ret;
-}
-
-//-----------------------------------------------------------------------------
-bool ctkVTKConnection::ValidateParameters(vtkObject* vtk_obj, unsigned long vtk_event,
-                                        const QObject* qt_obj, QString qt_slot)
-{
-  Q_UNUSED(vtk_event);
-  if (!vtk_obj)
-    {
-    return false;
-    }
-  if (!qt_obj)
-    {
-    return false;
-    }
-  if (qt_slot.isEmpty())
-    {
-    return false;
-    }
-  return true;
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnection::SetParameters(vtkObject* vtk_obj, unsigned long vtk_event,
-  const QObject* qt_obj, QString qt_slot, float priority)
-{
-  CTK_D(ctkVTKConnection);
-  
-  if (!Self::ValidateParameters(vtk_obj, vtk_event, qt_obj, qt_slot)) 
-    { 
-    return; 
-    }
-
-  d->VTKObject = vtk_obj;
-  d->QtObject = qt_obj;
-  d->VTKEvent = vtk_event;
-  d->QtSlot = qt_slot;
-  d->Priority = priority;
-
-  if (qt_slot.contains(QRegExp(QString("\\( ?vtkObject ?\\* ?, ?vtkObject ?\\* ?\\)"))))
-    {
-    d->SlotType = ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT;
-    }
-  else
-    {
-    d->SlotType = ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID;
-    }
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnection::setEnabled(bool enable)
-{
-  CTK_D(ctkVTKConnection);
-  
-  if (d->Connected == enable)
-    {
-    return;
-    }
-
-  if (enable)
-    {
-    d->connect();
-    }
-  else
-    {
-    d->disconnect();
-    }
-}
-
-//-----------------------------------------------------------------------------
-bool ctkVTKConnection::isEnabled()const
-{
-  CTK_D(const ctkVTKConnection);
-  return d->Connected;
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnection::setBlocked(bool block)
-{
-  CTK_D(ctkVTKConnection);
-  d->Blocked = block;
-}
-
-//-----------------------------------------------------------------------------
-bool ctkVTKConnection::isBlocked()const
-{
-  CTK_D(const ctkVTKConnection);
-  return d->Blocked;
-}
-
-//-----------------------------------------------------------------------------
-bool ctkVTKConnection::isEqual(vtkObject* vtk_obj, unsigned long vtk_event,
-    const QObject* qt_obj, QString qt_slot)const
-{
-  CTK_D(const ctkVTKConnection);
-  
-  if (d->VTKObject != vtk_obj)
-    {
-    return false;
-    }
-  if (vtk_event != vtkCommand::NoEvent && d->VTKEvent != vtk_event)
-    {
-    return false;
-    }
-  if (qt_obj && d->QtObject != qt_obj)
-    {
-    return false;
-    }
-  if (!qt_slot.isEmpty() && 
-      (QString(d->QtSlot).remove(' ').compare(
-        QString(qt_slot).remove(' ')) != 0))
-    {
-    return false;
-    }
-  return true;
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKConnectionPrivate::DoCallback(vtkObject* vtk_obj, unsigned long event,
-                                 void* client_data, void* call_data)
-{
-  ctkVTKConnectionPrivate* conn = static_cast<ctkVTKConnectionPrivate*>(client_data);
-  Q_ASSERT(conn);
-  conn->Execute(vtk_obj, event, client_data, call_data);
-}
-
-//-----------------------------------------------------------------------------
-// callback from VTK to emit signal
-void ctkVTKConnectionPrivate::Execute(vtkObject* vtk_obj, unsigned long vtk_event,
-  void* client_data, void* call_data)
-{
-  CTK_P(ctkVTKConnection);
-  
-  Q_ASSERT(this->Connected);
-  if (this->Blocked) 
-    { 
-    return; 
-    }
-  if (vtk_event == vtkCommand::DeleteEvent)
-    {
-    this->AboutToBeDeleted = true;
-    }
-
-  if(vtk_event != vtkCommand::DeleteEvent ||
-     (vtk_event == vtkCommand::DeleteEvent && this->VTKEvent == vtkCommand::DeleteEvent))
-    {
-    vtkObject* callDataAsVtkObject = 0;
-    switch (this->SlotType)
-      {
-      case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
-        if (this->VTKEvent == vtk_event)
-          {
-          callDataAsVtkObject = reinterpret_cast<vtkObject*>( call_data );
-          if (!callDataAsVtkObject)
-            {
-            qCritical() << "The VTKEvent(" << this->VTKEvent<< ") triggered by vtkObject("
-              << this->VTKObject->GetClassName() << ") "
-              << "doesn't return data of type vtkObject." << endl
-              << "The slot (" << this->QtSlot <<  ") owned by "
-              << "QObject(" << this->QtObject->objectName() << ")"
-              << " may be incorrect.";
-            }
-          emit p->emitExecute(vtk_obj, callDataAsVtkObject);
-          }
-        break;
-      case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
-        emit p->emitExecute(vtk_obj, call_data, vtk_event, client_data);
-        break;
-      default:
-        // Should never reach
-        qCritical() << "Unknown SlotType:" << this->SlotType;
-        return;
-        break;
-      }
-    }
-
-  if(vtk_event == vtkCommand::DeleteEvent)
-    {
-    this->AboutToBeDeleted = false;
-    p->deleteConnection();
-    }
-}
-
-void ctkVTKConnection::deleteConnection()
-{
-  CTK_D(ctkVTKConnection);
-  if (d->AboutToBeDeleted)
-    {
-    return;
-    }
-  delete this;
-}
+/*=========================================================================
+
+  Library:   CTK
+ 
+  Copyright (c) 2010  Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ 
+=========================================================================*/
+
+// Qt includes
+#include <QDebug>
+#include <QPointer>
+#include <QRegExp>
+#include <QString>
+#include <QTextStream>
+
+// CTK includes
+#include "ctkVTKConnection.h"
+
+// VTK includes
+#include <vtkObject.h>
+#include <vtkSmartPointer.h>
+#include <vtkCallbackCommand.h>
+
+//-----------------------------------------------------------------------------
+QString convertPointerToString(void* pointer)
+{
+  QString pointerAsString;
+  QTextStream(&pointerAsString) << pointer;
+  return pointerAsString;
+}
+
+//-----------------------------------------------------------------------------
+class ctkVTKConnectionPrivate: public ctkPrivate<ctkVTKConnection>
+{
+public:
+  enum
+    {
+    ARG_UNKNOWN = 0,
+    ARG_VTKOBJECT_AND_VTKOBJECT,
+    ARG_VTKOBJECT_VOID_ULONG_VOID
+    };
+
+  typedef ctkVTKConnectionPrivate Self;
+  ctkVTKConnectionPrivate();
+  ~ctkVTKConnectionPrivate();
+
+  void connect();
+  void disconnect();
+
+  /// 
+  /// VTK Callback
+  static void DoCallback(vtkObject* vtk_obj, unsigned long event,
+                         void* client_data, void* call_data);
+
+  /// 
+  /// Called by 'DoCallback' to emit signal
+  void execute(vtkObject* vtk_obj, unsigned long vtk_event, void* client_data, void* call_data);
+
+  vtkSmartPointer<vtkCallbackCommand> Callback;
+  vtkObject*                          VTKObject;
+  const QObject*                      QtObject;
+  unsigned long                       VTKEvent;
+  QString                             QtSlot;
+  float                               Priority;
+  int                                 SlotType;
+  bool                                Connected;
+  bool                                Blocked;
+  QString                             Id;
+  bool                                ObserveDeletion;
+};
+
+//-----------------------------------------------------------------------------
+// ctkVTKConnectionPrivate methods
+
+//-----------------------------------------------------------------------------
+ctkVTKConnectionPrivate::ctkVTKConnectionPrivate()
+{
+  this->Callback    = vtkSmartPointer<vtkCallbackCommand>::New();
+  this->Callback->SetCallback(ctkVTKConnectionPrivate::DoCallback);
+  this->Callback->SetClientData(this);
+  this->VTKObject   = 0;
+  this->QtObject    = 0;
+  this->VTKEvent    = vtkCommand::NoEvent;
+  this->Priority    = 0.0;
+  this->SlotType    = ARG_UNKNOWN;
+  this->Connected   = false;
+  this->Blocked     = false;
+  this->Id          = convertPointerToString(this);
+  this->ObserveDeletion = false;
+}
+
+//-----------------------------------------------------------------------------
+ctkVTKConnectionPrivate::~ctkVTKConnectionPrivate()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKConnectionPrivate::connect()
+{
+  CTK_P(ctkVTKConnection);
+  
+  if (this->Connected)
+    {
+    qDebug() << "ctkVTKConnection already connected.";
+    return;
+    }
+
+  switch (this->SlotType)
+    {
+    case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
+      QObject::connect(p, SIGNAL(emitExecute(vtkObject*, vtkObject*)),
+        this->QtObject, this->QtSlot.toLatin1().data(), Qt::AutoConnection);
+      break;
+    case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
+      QObject::connect(p, SIGNAL(emitExecute(vtkObject*, void*, unsigned long, void*)),
+                       this->QtObject, this->QtSlot.toLatin1().data(), Qt::AutoConnection);
+      break;
+    default:
+      Q_ASSERT(false);
+      qCritical() << "Failed to connect - "
+                  << "The slot (" << this->QtSlot <<  ") owned by "
+                  << "QObject(" << this->QtObject->objectName() << ")"
+                  << " seems to have a wrong signature.";
+      break;
+    }
+
+  // Make a connection between this and the vtk object
+  this->VTKObject->AddObserver(this->VTKEvent, this->Callback, this->Priority);
+
+  // If necessary, observe vtk DeleteEvent
+  if(this->ObserveDeletion)
+    {
+    // don't observe it twice
+    if (this->VTKEvent != vtkCommand::DeleteEvent)
+      {
+      this->VTKObject->AddObserver(vtkCommand::DeleteEvent, this->Callback);
+      }
+    // Remove itself from its parent when vtkObject is deleted
+    QObject::connect(this->QtObject, SIGNAL(destroyed(QObject*)), 
+                     p, SLOT(qobjectDeleted()));
+    }
+  this->Connected = true;
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKConnectionPrivate::disconnect()
+{
+  CTK_P(ctkVTKConnection);
+  
+  if (!this->Connected) 
+    { 
+    return; 
+    }
+
+  if (this->QtObject)
+    {
+    switch (this->SlotType)
+      {
+      case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
+        QObject::disconnect(p, SIGNAL(emitExecute(vtkObject*, vtkObject*)),
+                            this->QtObject,this->QtSlot.toLatin1().data());
+        break;
+      case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
+        QObject::disconnect(p, SIGNAL(emitExecute(vtkObject*, void*, unsigned long, void*)),
+                            this->QtObject, this->QtSlot.toLatin1().data());
+        break;
+      default:
+        Q_ASSERT(false);
+        qCritical() << "Failed to disconnect - "
+                    << "The slot (" << this->QtSlot <<  ") owned by "
+                    << "QObject(" << this->QtObject->objectName() << ")"
+                    << " seems to have a wrong signature.";
+        break;
+      }
+    }
+
+  if (this->VTKObject)
+    {
+    this->VTKObject->RemoveObserver(this->Callback);
+    }
+
+  if (this->ObserveDeletion && this->QtObject)
+    {
+    //this->VTKObject->AddObserver(vtkCommand::DeleteEvent, this->Callback); has already been removed
+    QObject::disconnect(this->QtObject, SIGNAL(destroyed(QObject*)),
+                        p, SIGNAL(isBroke()));
+    }
+
+  this->Connected = false;
+}
+
+//-----------------------------------------------------------------------------
+// ctkVTKConnection methods
+
+//-----------------------------------------------------------------------------
+ctkVTKConnection::ctkVTKConnection(QObject* _parent):
+  Superclass(_parent)
+{
+  CTK_INIT_PRIVATE(ctkVTKConnection);
+}
+
+//-----------------------------------------------------------------------------
+ctkVTKConnection::~ctkVTKConnection()
+{
+  CTK_D(ctkVTKConnection);
+  if (d->ObserveDeletion)
+    {
+    d->disconnect();
+    }
+}
+
+//-----------------------------------------------------------------------------
+QString ctkVTKConnection::id()const
+{
+  CTK_D(const ctkVTKConnection);
+  return d->Id;
+}
+
+//-----------------------------------------------------------------------------
+QObject* ctkVTKConnection::object()const
+{
+  CTK_D(const ctkVTKConnection);
+  return const_cast<QObject*>(d->QtObject);
+}
+
+//-----------------------------------------------------------------------------
+QDebug operator<<(QDebug dbg, const ctkVTKConnection& connection)
+{
+  const ctkVTKConnectionPrivate* d = connection.ctk_d();
+  dbg.nospace() << "ctkVTKConnection:" << &connection << endl
+                << "Id:" << d->Id << endl
+                << " VTKObject:" << d->VTKObject->GetClassName()
+                << "(" << d->VTKObject << ")" << endl
+                << " QtObject:" << d->QtObject << endl
+                << " VTKEvent:" << d->VTKEvent << endl
+                << " QtSlot:" << d->QtSlot << endl
+                << " SlotType:" << d->SlotType << endl
+                << " Priority:" << d->Priority << endl
+                << " Connected:" << d->Connected << endl
+                << " Blocked:" << d->Blocked;
+  return dbg.space();
+}
+
+//-----------------------------------------------------------------------------
+QString ctkVTKConnection::shortDescription()
+{
+  CTK_D(ctkVTKConnection);
+  
+  return Self::shortDescription(d->VTKObject, d->VTKEvent, d->QtObject, d->QtSlot);
+}
+
+//-----------------------------------------------------------------------------
+QString ctkVTKConnection::shortDescription(vtkObject* vtk_obj, unsigned long vtk_event,
+    const QObject* qt_obj, QString qt_slot)
+{
+  QString ret;
+  QTextStream ts( &ret );
+  ts << (vtk_obj ? vtk_obj->GetClassName() : "NULL") << " "
+     << vtk_event << " " << qt_obj << " " << qt_slot;
+  return ret;
+}
+
+//-----------------------------------------------------------------------------
+bool ctkVTKConnection::isValid(vtkObject* vtk_obj, unsigned long vtk_event,
+                               const QObject* qt_obj, QString qt_slot)
+{
+  Q_UNUSED(vtk_event);
+  if (!vtk_obj)
+    {
+    return false;
+    }
+  if (!qt_obj)
+    {
+    return false;
+    }
+  if (qt_slot.isEmpty())
+    {
+    return false;
+    }
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKConnection::setup(vtkObject* vtk_obj, unsigned long vtk_event,
+                             const QObject* qt_obj, QString qt_slot, 
+                             float priority)
+{
+  CTK_D(ctkVTKConnection);
+  
+  if (!Self::isValid(vtk_obj, vtk_event, qt_obj, qt_slot)) 
+    { 
+    return; 
+    }
+
+  d->VTKObject = vtk_obj;
+  d->QtObject = qt_obj;
+  d->VTKEvent = vtk_event;
+  d->QtSlot = qt_slot;
+  d->Priority = priority;
+
+  if (qt_slot.contains(QRegExp(QString("\\( ?vtkObject ?\\* ?, ?vtkObject ?\\* ?\\)"))))
+    {
+    d->SlotType = ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT;
+    }
+  else
+    {
+    d->SlotType = ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID;
+    }
+  d->connect();
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKConnection::setBlocked(bool block)
+{
+  CTK_D(ctkVTKConnection);
+  d->Blocked = block;
+}
+
+//-----------------------------------------------------------------------------
+bool ctkVTKConnection::isBlocked()const
+{
+  CTK_D(const ctkVTKConnection);
+  return d->Blocked;
+}
+
+//-----------------------------------------------------------------------------
+bool ctkVTKConnection::isEqual(vtkObject* vtk_obj, unsigned long vtk_event,
+    const QObject* qt_obj, QString qt_slot)const
+{
+  CTK_D(const ctkVTKConnection);
+  
+  if (d->VTKObject != vtk_obj)
+    {
+    return false;
+    }
+  if (vtk_event != vtkCommand::NoEvent && d->VTKEvent != vtk_event)
+    {
+    return false;
+    }
+  if (qt_obj && d->QtObject != qt_obj)
+    {
+    return false;
+    }
+  if (!qt_slot.isEmpty() && 
+      (QString(d->QtSlot).remove(' ').compare(
+        QString(qt_slot).remove(' ')) != 0))
+    {
+    return false;
+    }
+  return true;
+}
+
+//-----------------------------------------------------------------------------
+void ctkVTKConnectionPrivate::DoCallback(vtkObject* vtk_obj, unsigned long event,
+                                 void* client_data, void* call_data)
+{
+  ctkVTKConnectionPrivate* conn = reinterpret_cast<ctkVTKConnectionPrivate*>(client_data);
+  Q_ASSERT(conn);
+  conn->execute(vtk_obj, event, client_data, call_data);
+}
+
+//-----------------------------------------------------------------------------
+// callback from VTK to emit signal
+void ctkVTKConnectionPrivate::execute(vtkObject* vtk_obj, unsigned long vtk_event,
+  void* client_data, void* call_data)
+{
+  CTK_P(ctkVTKConnection);
+  
+  Q_ASSERT(this->Connected);
+  if (this->Blocked) 
+    { 
+    return; 
+    }
+
+  QPointer<ctkVTKConnection> connection(p);
+  if(!this->ObserveDeletion ||
+     vtk_event != vtkCommand::DeleteEvent ||
+     this->VTKEvent == vtkCommand::DeleteEvent)
+    {
+    vtkObject* callDataAsVtkObject = 0;
+    switch (this->SlotType)
+      {
+      case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
+        if (this->VTKEvent == vtk_event)
+          {
+          callDataAsVtkObject = reinterpret_cast<vtkObject*>( call_data );
+          if (!callDataAsVtkObject)
+            {
+            qCritical() << "The VTKEvent(" << this->VTKEvent<< ") triggered by vtkObject("
+              << this->VTKObject->GetClassName() << ") "
+              << "doesn't return data of type vtkObject." << endl
+              << "The slot (" << this->QtSlot <<  ") owned by "
+              << "QObject(" << this->QtObject->objectName() << ")"
+              << " may be incorrect.";
+            }
+          emit p->emitExecute(vtk_obj, callDataAsVtkObject);
+          }
+        break;
+      case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
+        emit p->emitExecute(vtk_obj, call_data, vtk_event, client_data);
+        break;
+      default:
+        // Should never reach
+        qCritical() << "Unknown SlotType:" << this->SlotType;
+        return;
+        break;
+      }
+    }
+
+  if (!connection.isNull() &&
+      vtk_event == vtkCommand::DeleteEvent)
+    {
+    p->vtkObjectDeleted();
+    }
+}
+
+void ctkVTKConnection::observeDeletion(bool enable)
+{
+  CTK_D(ctkVTKConnection);
+  d->ObserveDeletion = enable;
+}
+
+bool ctkVTKConnection::deletionObserved()const
+{
+  CTK_D(const ctkVTKConnection);
+  return d->ObserveDeletion;
+}
+
+void ctkVTKConnection::vtkObjectDeleted()
+{
+  CTK_D(ctkVTKConnection);
+  d->VTKObject = 0;
+  d->disconnect();
+  emit isBroke();
+}
+
+void ctkVTKConnection::qobjectDeleted()
+{
+  CTK_D(ctkVTKConnection);
+  d->QtObject = 0;
+  d->disconnect();
+  emit isBroke();
+}

+ 108 - 103
Libs/Visualization/VTK/Core/ctkVTKConnection.h

@@ -1,103 +1,108 @@
-/*=========================================================================
-
-  Library:   CTK
- 
-  Copyright (c) 2010  Kitware Inc.
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-      http://www.commontk.org/LICENSE
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
- 
-=========================================================================*/
-
-#ifndef __ctkVTKConnection_h
-#define __ctkVTKConnection_h
-
-// Qt includes
-#include <QObject>
-#include <QVector>
-
-// CTK includes
-#include <ctkPimpl.h>
-
-#include "CTKVisualizationVTKCoreExport.h"
-
-class vtkObject;
-class ctkVTKConnectionPrivate;
-
-class CTK_VISUALIZATION_VTK_CORE_EXPORT ctkVTKConnection : public QObject
-{
-Q_OBJECT
-
-public:
-  typedef QObject Superclass;
-  explicit ctkVTKConnection(QObject* parent);
-
-  /// 
-  virtual void printAdditionalInfo();
-  QString shortDescription();
-  static QString shortDescription(vtkObject* vtk_obj, unsigned long vtk_event,
-    const QObject* qt_obj, QString qt_slot = "");
-
-  /// 
-  void SetParameters(vtkObject* vtk_obj, unsigned long vtk_event,
-    const QObject* qt_obj, QString qt_slot, float priority = 0.f);
-
-  /// 
-  /// Check the validity of the parameters. Parameters must be valid to add 
-  /// a connection
-  static bool ValidateParameters(vtkObject* vtk_obj, unsigned long vtk_event,
-    const QObject* qt_obj, QString qt_slot);
-
-  /// 
-  /// Actually do the connection. Parameters must have been set prior to it
-  /// Disconnecting (enable = false) removes the connection.
-  void setEnabled(bool enable);
-  bool isEnabled()const;
-
-  /// 
-  /// Temporarilly block any signals/slots. If the event is fired, the slot
-  /// won't be called. You can restore the connection by calling SetBlocked
-  /// with block = false.
-  void setBlocked(bool block);
-  bool isBlocked()const;
-
-  /// 
-  bool isEqual(vtkObject* vtk_obj, unsigned long vtk_event,
-               const QObject* qt_obj, QString qt_slot)const;
-
-  /// 
-  /// Return a string uniquely identifying the connection within the current process
-  QString id()const;
-public slots:
-  ///
-  /// Safe deletion
-  void deleteConnection();
-
-signals:
-  /// 
-  /// The qt signal emited by the VTK Callback
-  /// The signal corresponding to the slot will be emited
-  void emitExecute(vtkObject* caller, vtkObject* call_data);
-
-  /// Note: even if the signal has a signature with 4 args, you can
-  /// connect it to a slot with less arguments as long as the types of the 
-  /// argument are matching:
-  /// connect(obj1,SIGNAL(signalFunc(A,B,C,D)),obj2,SLOT(slotFunc(A)));
-  void emitExecute(vtkObject* caller, void* call_data, unsigned long vtk_event, void* client_data);
-protected:
-  virtual ~ctkVTKConnection();
-
-private:
-  CTK_DECLARE_PRIVATE(ctkVTKConnection);
-};
-
-#endif
+/*=========================================================================
+
+  Library:   CTK
+ 
+  Copyright (c) 2010  Kitware Inc.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.commontk.org/LICENSE
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ 
+=========================================================================*/
+
+#ifndef __ctkVTKConnection_h
+#define __ctkVTKConnection_h
+
+// Qt includes
+#include <QObject>
+#include <QVector>
+
+// CTK includes
+#include <ctkPimpl.h>
+
+#include "CTKVisualizationVTKCoreExport.h"
+
+class vtkObject;
+class ctkVTKConnectionPrivate;
+
+class CTK_VISUALIZATION_VTK_CORE_EXPORT ctkVTKConnection : public QObject
+{
+Q_OBJECT
+
+public:
+  typedef QObject Superclass;
+  explicit ctkVTKConnection(QObject* parent);
+  virtual ~ctkVTKConnection();
+
+  ///
+  QString shortDescription();
+  static QString shortDescription(vtkObject* vtk_obj, unsigned long vtk_event,
+    const QObject* qt_obj, QString qt_slot = "");
+
+  /// 
+  void setup(vtkObject* vtk_obj, unsigned long vtk_event,
+    const QObject* qt_obj, QString qt_slot, float priority = 0.f);
+
+  /// 
+  /// Check the validity of the parameters. Parameters must be valid to add 
+  /// a connection
+  static bool isValid(vtkObject* vtk_obj, unsigned long vtk_event,
+    const QObject* qt_obj, QString qt_slot);
+
+  /// 
+  /// Temporarilly block any signals/slots. If the event is fired, the slot
+  /// won't be called. You can restore the connection by calling SetBlocked
+  /// with block = false.
+  void setBlocked(bool block);
+  bool isBlocked()const;
+
+  /// 
+  bool isEqual(vtkObject* vtk_obj, unsigned long vtk_event,
+               const QObject* qt_obj, QString qt_slot)const;
+
+  /// 
+  /// Return a string uniquely identifying the connection within the current process
+  QString  id()const;
+  QObject* object()const;
+
+  /// false by default, it is slower to observe vtk object deletion
+  void observeDeletion(bool enable);
+  bool deletionObserved()const;
+  
+signals:
+  /// 
+  /// The qt signal emited by the VTK Callback
+  /// The signal corresponding to the slot will be emited
+  void emitExecute(vtkObject* caller, vtkObject* call_data);
+
+  /// Note: even if the signal has a signature with 4 args, you can
+  /// connect it to a slot with less arguments as long as the types of the 
+  /// argument are matching:
+  /// connect(obj1,SIGNAL(signalFunc(A,B,C,D)),obj2,SLOT(slotFunc(A)));
+  void emitExecute(vtkObject* caller, void* call_data, unsigned long vtk_event, void* client_data);
+
+  /// The signal is fired when the observed vtk object or the receiving qt 
+  /// object is deleted. It can conveniently connected to the deleteLater 
+  /// slot
+  void isBroke();
+
+protected slots:
+  void vtkObjectDeleted();
+  void qobjectDeleted();
+
+private:
+  CTK_DECLARE_PRIVATE(ctkVTKConnection);
+  friend QDebug operator<<(QDebug dbg, const ctkVTKConnection& connection);
+};
+
+QDebug operator<<(QDebug dbg, const ctkVTKConnection& connection);
+
+#endif

+ 10 - 33
Libs/Visualization/VTK/Core/ctkVTKObjectEventsObserver.cpp

@@ -63,8 +63,8 @@ public:
     return ctk_p()->findChildren<ctkVTKConnection*>();
   }
   
-  bool                            AllEnabled;
-  bool                            AllBlocked;
+  bool AllBlocked;
+  bool ObserveDeletion;
 };
 
 //-----------------------------------------------------------------------------
@@ -83,39 +83,15 @@ void ctkVTKObjectEventsObserver::printAdditionalInfo()
   this->Superclass::dumpObjectInfo();
   CTK_D(ctkVTKObjectEventsObserver);
   qDebug() << "ctkVTKObjectEventsObserver:" << this << endl
-           << " AllEnabled:" << d->AllEnabled << endl
            << " AllBlocked:" << d->AllBlocked << endl
            << " Parent:" << (this->parent()?this->parent()->objectName():"NULL") << endl
            << " Connection count:" << d->connections().count();
 
   // Loop through all connection
-  foreach (ctkVTKConnection* connection, d->connections())
-    {
-    connection->printAdditionalInfo();
-    }
-}
-
-//-----------------------------------------------------------------------------
-bool ctkVTKObjectEventsObserver::allEnabled()const
-{
-  return ctk_d()->AllEnabled;
-}
-
-//-----------------------------------------------------------------------------
-void ctkVTKObjectEventsObserver::setAllEnabled(bool enable)
-{
-  CTK_D(ctkVTKObjectEventsObserver);
-  // FIXME: maybe a particular module has been enabled/disabled
-  if (d->AllEnabled == enable) 
-    { 
-    return; 
-    }
-  // Loop through VTKQtConnections to enable/disable
-  foreach(ctkVTKConnection* connection, d->connections())
+  foreach (const ctkVTKConnection* connection, d->connections())
     {
-    connection->setEnabled(enable);
+    qDebug() << *connection;
     }
-  d->AllEnabled = enable;
 }
 
 //-----------------------------------------------------------------------------
@@ -162,7 +138,7 @@ QString ctkVTKObjectEventsObserver::addConnection(vtkObject* vtk_obj, unsigned l
   const QObject* qt_obj, const char* qt_slot, float priority)
 {
   CTK_D(ctkVTKObjectEventsObserver);
-  if (!ctkVTKConnection::ValidateParameters(vtk_obj, vtk_event, qt_obj, qt_slot))
+  if (!ctkVTKConnection::isValid(vtk_obj, vtk_event, qt_obj, qt_slot))
     {
     qDebug() << "ctkVTKObjectEventsObserver::addConnection(...) - Invalid parameters - "
              << ctkVTKConnection::shortDescription(vtk_obj, vtk_event, qt_obj, qt_slot);
@@ -182,10 +158,10 @@ QString ctkVTKObjectEventsObserver::addConnection(vtkObject* vtk_obj, unsigned l
 
   // Instantiate a new connection, set its parameters and add it to the list
   ctkVTKConnection * connection = new ctkVTKConnection(this);
-  connection->SetParameters(vtk_obj, vtk_event, qt_obj, qt_slot, priority);
+  connection->observeDeletion(d->ObserveDeletion);
+  connection->setup(vtk_obj, vtk_event, qt_obj, qt_slot, priority);
 
   // If required, establish connection
-  connection->setEnabled(d->AllEnabled);
   connection->setBlocked(d->AllBlocked);
 
   return connection->id();
@@ -249,7 +225,7 @@ int ctkVTKObjectEventsObserver::removeConnection(vtkObject* vtk_obj, unsigned lo
   
   foreach (ctkVTKConnection* connection, connections)
     {
-    connection->deleteConnection();
+    delete connection;
     }
   return connections.count();
 }
@@ -260,8 +236,9 @@ int ctkVTKObjectEventsObserver::removeConnection(vtkObject* vtk_obj, unsigned lo
 //-----------------------------------------------------------------------------
 ctkVTKObjectEventsObserverPrivate::ctkVTKObjectEventsObserverPrivate()
 {
-  this->AllEnabled = true;
   this->AllBlocked = false;
+  // ObserveDeletion == false  hasn't been that well tested...
+  this->ObserveDeletion = true;
 }
 
 //-----------------------------------------------------------------------------

+ 0 - 5
Libs/Visualization/VTK/Core/ctkVTKObjectEventsObserver.h

@@ -50,11 +50,6 @@ public:
   virtual void printAdditionalInfo();
 
   /// 
-  /// Enable / Disable all ctkVTKConnections
-  void setAllEnabled( bool enable );
-  bool allEnabled()const;
-
-  /// 
   /// Add a connection, an Id allowing to uniquely identify the connection is also returned
   QString addConnection(vtkObject* vtk_obj, unsigned long vtk_event,
     const QObject* qt_obj, const char* qt_slot, float priority = 0.0);