ctkVTKObjectEventsObserver.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.commontk.org/LICENSE
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QStringList>
  16. #include <QVariant>
  17. #include <QList>
  18. #include <QHash>
  19. #include <QDebug>
  20. // CTK includes
  21. #include "ctkVTKObjectEventsObserver.h"
  22. #include "ctkVTKConnection.h"
  23. // VTK includes
  24. #include <vtkObject.h>
  25. #include <vtkSmartPointer.h>
  26. //-----------------------------------------------------------------------------
  27. class ctkVTKObjectEventsObserverPrivate
  28. {
  29. Q_DECLARE_PUBLIC(ctkVTKObjectEventsObserver);
  30. protected:
  31. ctkVTKObjectEventsObserver* const q_ptr;
  32. public:
  33. ctkVTKObjectEventsObserverPrivate(ctkVTKObjectEventsObserver& object);
  34. ///
  35. /// Return a reference toward the corresponding connection or 0 if doesn't exist
  36. ctkVTKConnection* findConnection(const QString& id)const;
  37. ///
  38. /// Return a reference toward the corresponding connection or 0 if doesn't exist
  39. ctkVTKConnection* findConnection(vtkObject* vtk_obj, unsigned long vtk_event,
  40. const QObject* qt_obj, const char* qt_slot)const;
  41. ///
  42. /// Return all the references that match the given parameters
  43. QList<ctkVTKConnection*> findConnections(vtkObject* vtk_obj, unsigned long vtk_event,
  44. const QObject* qt_obj, const char* qt_slot)const;
  45. inline QList<ctkVTKConnection*> connections()const
  46. {
  47. Q_Q(const ctkVTKObjectEventsObserver);
  48. return q->findChildren<ctkVTKConnection*>();
  49. }
  50. bool AllBlocked;
  51. bool ObserveDeletion;
  52. };
  53. //-----------------------------------------------------------------------------
  54. // ctkVTKObjectEventsObserverPrivate methods
  55. //-----------------------------------------------------------------------------
  56. ctkVTKObjectEventsObserverPrivate::ctkVTKObjectEventsObserverPrivate(ctkVTKObjectEventsObserver& object)
  57. :q_ptr(&object)
  58. {
  59. this->AllBlocked = false;
  60. // ObserveDeletion == false hasn't been that well tested...
  61. this->ObserveDeletion = true;
  62. }
  63. //-----------------------------------------------------------------------------
  64. ctkVTKConnection*
  65. ctkVTKObjectEventsObserverPrivate::findConnection(const QString& id)const
  66. {
  67. foreach(ctkVTKConnection* connection, this->connections())
  68. {
  69. if (connection->id() == id)
  70. {
  71. return connection;
  72. }
  73. }
  74. return 0;
  75. }
  76. //-----------------------------------------------------------------------------
  77. ctkVTKConnection*
  78. ctkVTKObjectEventsObserverPrivate::findConnection(
  79. vtkObject* vtk_obj, unsigned long vtk_event,
  80. const QObject* qt_obj, const char* qt_slot)const
  81. {
  82. foreach (ctkVTKConnection* connection, this->connections())
  83. {
  84. if (connection->isEqual(vtk_obj, vtk_event, qt_obj, qt_slot))
  85. {
  86. return connection;
  87. }
  88. }
  89. return 0;
  90. }
  91. //-----------------------------------------------------------------------------
  92. QList<ctkVTKConnection*>
  93. ctkVTKObjectEventsObserverPrivate::findConnections(
  94. vtkObject* vtk_obj, unsigned long vtk_event,
  95. const QObject* qt_obj, const char* qt_slot)const
  96. {
  97. bool all_info = true;
  98. if(vtk_obj == NULL || qt_slot == NULL ||
  99. qt_obj == NULL || vtk_event == vtkCommand::NoEvent)
  100. {
  101. all_info = false;
  102. }
  103. QList<ctkVTKConnection*> foundConnections;
  104. // Loop through all connection
  105. foreach (ctkVTKConnection* connection, this->connections())
  106. {
  107. if (connection->isEqual(vtk_obj, vtk_event, qt_obj, qt_slot))
  108. {
  109. foundConnections.append(connection);
  110. if (all_info)
  111. {
  112. break;
  113. }
  114. }
  115. }
  116. return foundConnections;
  117. }
  118. //-----------------------------------------------------------------------------
  119. // ctkVTKObjectEventsObserver methods
  120. //-----------------------------------------------------------------------------
  121. ctkVTKObjectEventsObserver::ctkVTKObjectEventsObserver(QObject* _parent):Superclass(_parent)
  122. , d_ptr(new ctkVTKObjectEventsObserverPrivate(*this))
  123. {
  124. this->setProperty("QVTK_OBJECT", true);
  125. }
  126. //-----------------------------------------------------------------------------
  127. ctkVTKObjectEventsObserver::~ctkVTKObjectEventsObserver()
  128. {
  129. }
  130. //-----------------------------------------------------------------------------
  131. void ctkVTKObjectEventsObserver::printAdditionalInfo()
  132. {
  133. this->Superclass::dumpObjectInfo();
  134. Q_D(ctkVTKObjectEventsObserver);
  135. qDebug() << "ctkVTKObjectEventsObserver:" << this << endl
  136. << " AllBlocked:" << d->AllBlocked << endl
  137. << " Parent:" << (this->parent()?this->parent()->objectName():"NULL") << endl
  138. << " Connection count:" << d->connections().count();
  139. // Loop through all connection
  140. foreach (const ctkVTKConnection* connection, d->connections())
  141. {
  142. qDebug() << *connection;
  143. }
  144. }
  145. //-----------------------------------------------------------------------------
  146. QString ctkVTKObjectEventsObserver::addConnection(vtkObject* old_vtk_obj, vtkObject* vtk_obj,
  147. unsigned long vtk_event, const QObject* qt_obj, const char* qt_slot, float priority)
  148. {
  149. if (old_vtk_obj)
  150. {
  151. // Check that old_object and new_object are the same type
  152. // If you have a crash when accessing old_vtk_obj->GetClassName(), that means
  153. // old_vtk_obj has been deleted and you should probably have keep
  154. // old_vtk_obj into a vtkWeakPointer:
  155. // vtkWeakPointer<vtkObject> obj1 = myobj1;
  156. // this->addConnection(obj1, vtkCommand::Modified...)
  157. // myobj1->Delete();
  158. // vtkWeakPointer<vtkObject> obj2 = myobj2;
  159. // this->addConnection(obj1, obj2, vtkCommand::Modified...)
  160. // ...
  161. // Or just call addConnection with a new
  162. // vtk_obj of 0 before the vtk_obj is deleted.
  163. // vtkObject* obj1 = vtkObject::New();
  164. // this->addConnection(obj1, vtkCommand::Modified...)
  165. // this->addConnection(obj1, 0, vtkCommand::Modified...)
  166. // obj1->Delete();
  167. // vtkObject* obj2 = vtkObject::New();
  168. // this->addConnection(0, obj2, vtkCommand::Modified...)
  169. // ...
  170. if (vtk_obj && !vtk_obj->IsA(old_vtk_obj->GetClassName()))
  171. {
  172. qDebug() << "Previous vtkObject (type:" << old_vtk_obj->GetClassName() << ") to disconnect"
  173. << "and new vtkObject (type:" << vtk_obj->GetClassName() << ") to connect"
  174. << "have a different type.";
  175. return QString();
  176. }
  177. // Disconnect old vtkObject
  178. this->removeConnection(old_vtk_obj, vtk_event, qt_obj, qt_slot);
  179. }
  180. return this->addConnection(vtk_obj, vtk_event, qt_obj, qt_slot, priority);
  181. }
  182. //-----------------------------------------------------------------------------
  183. QString ctkVTKObjectEventsObserver::reconnection(vtkObject* vtk_obj,
  184. unsigned long vtk_event, const QObject* qt_obj,
  185. const char* qt_slot, float priority)
  186. {
  187. this->removeConnection(0, vtk_event, qt_obj, qt_slot);
  188. return this->addConnection(vtk_obj, vtk_event, qt_obj, qt_slot, priority);
  189. }
  190. //-----------------------------------------------------------------------------
  191. QString ctkVTKObjectEventsObserver::addConnection(vtkObject* vtk_obj, unsigned long vtk_event,
  192. const QObject* qt_obj, const char* qt_slot, float priority)
  193. {
  194. Q_D(ctkVTKObjectEventsObserver);
  195. // If no vtk_obj is provided, there is no way we can create a connection.
  196. if (!vtk_obj)
  197. {
  198. return QString();
  199. }
  200. if (!ctkVTKConnection::isValid(vtk_obj, vtk_event, qt_obj, qt_slot))
  201. {
  202. qDebug() << "ctkVTKObjectEventsObserver::addConnection(...) - Invalid parameters - "
  203. << ctkVTKConnection::shortDescription(vtk_obj, vtk_event, qt_obj, qt_slot);
  204. return QString();
  205. }
  206. // Check if such event is already observed
  207. if (this->containsConnection(vtk_obj, vtk_event, qt_obj, qt_slot))
  208. {
  209. // if you need to have more than 1 connection, then it's probably time to
  210. // add the same mechanism than Qt does: Qt::UniqueConnection
  211. //qWarning() << "ctkVTKObjectEventsObserver::addConnection - [vtkObject:"
  212. // << vtk_obj->GetClassName()
  213. // << ", event:" << vtk_event << "]"
  214. // << " is already connected with [qObject:" << qt_obj->objectName()
  215. // << ", slot:" << qt_slot << "]";
  216. return QString();
  217. }
  218. // Instantiate a new connection, set its parameters and add it to the list
  219. ctkVTKConnection * connection = new ctkVTKConnection(this);
  220. connection->observeDeletion(d->ObserveDeletion);
  221. connection->setup(vtk_obj, vtk_event, qt_obj, qt_slot, priority);
  222. // If required, establish connection
  223. connection->setBlocked(d->AllBlocked);
  224. return connection->id();
  225. }
  226. //-----------------------------------------------------------------------------
  227. bool ctkVTKObjectEventsObserver::blockAllConnections(bool block)
  228. {
  229. Q_D(ctkVTKObjectEventsObserver);
  230. if (d->AllBlocked == block)
  231. {
  232. return d->AllBlocked;
  233. }
  234. bool oldAllBlocked = d->AllBlocked;
  235. foreach (ctkVTKConnection* connection, d->connections())
  236. {
  237. connection->setBlocked(block);
  238. }
  239. d->AllBlocked = block;
  240. return oldAllBlocked;
  241. }
  242. //-----------------------------------------------------------------------------
  243. bool ctkVTKObjectEventsObserver::connectionsBlocked()const
  244. {
  245. Q_D(const ctkVTKObjectEventsObserver);
  246. return d->AllBlocked;
  247. }
  248. //-----------------------------------------------------------------------------
  249. bool ctkVTKObjectEventsObserver::blockConnection(const QString& id, bool blocked)
  250. {
  251. Q_D(ctkVTKObjectEventsObserver);
  252. ctkVTKConnection* connection = d->findConnection(id);
  253. if (connection == 0)
  254. {
  255. qWarning() << "no connection for id " << id;
  256. return false;
  257. }
  258. bool oldBlocked = connection->isBlocked();
  259. connection->setBlocked(blocked);
  260. return oldBlocked;
  261. }
  262. //-----------------------------------------------------------------------------
  263. int ctkVTKObjectEventsObserver::blockConnection(bool block, vtkObject* vtk_obj,
  264. unsigned long vtk_event, const QObject* qt_obj)
  265. {
  266. Q_D(ctkVTKObjectEventsObserver);
  267. if (!vtk_obj)
  268. {
  269. qDebug() << "ctkVTKObjectEventsObserver::blockConnectionRecursive"
  270. << "- Failed to " << (block?"block":"unblock") <<" connection"
  271. << "- vtkObject is NULL";
  272. return 0;
  273. }
  274. QList<ctkVTKConnection*> connections =
  275. d->findConnections(vtk_obj, vtk_event, qt_obj, 0);
  276. foreach (ctkVTKConnection* connection, connections)
  277. {
  278. connection->setBlocked(block);
  279. }
  280. return connections.size();
  281. }
  282. //-----------------------------------------------------------------------------
  283. int ctkVTKObjectEventsObserver::removeConnection(vtkObject* vtk_obj, unsigned long vtk_event,
  284. const QObject* qt_obj, const char* qt_slot)
  285. {
  286. Q_D(ctkVTKObjectEventsObserver);
  287. QList<ctkVTKConnection*> connections =
  288. d->findConnections(vtk_obj, vtk_event, qt_obj, qt_slot);
  289. foreach (ctkVTKConnection* connection, connections)
  290. {
  291. delete connection;
  292. }
  293. return connections.count();
  294. }
  295. //-----------------------------------------------------------------------------
  296. bool ctkVTKObjectEventsObserver::containsConnection(vtkObject* vtk_obj, unsigned long vtk_event,
  297. const QObject* qt_obj, const char* qt_slot)const
  298. {
  299. Q_D(const ctkVTKObjectEventsObserver);
  300. return (d->findConnection(vtk_obj, vtk_event, qt_obj, qt_slot) != 0);
  301. }