ctkVTKConnection.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. // Qt includes
  2. #include <QDebug>
  3. #include <QRegExp>
  4. #include <QString>
  5. #include <QTextStream>
  6. // CTK includes
  7. #include "ctkVTKConnection.h"
  8. // VTK includes
  9. #include <vtkObject.h>
  10. #include <vtkSmartPointer.h>
  11. #include <vtkCallbackCommand.h>
  12. //-----------------------------------------------------------------------------
  13. QString convertPointerToString(void* pointer)
  14. {
  15. QString pointerAsString;
  16. QTextStream(&pointerAsString) << pointer;
  17. return pointerAsString;
  18. }
  19. //-----------------------------------------------------------------------------
  20. class ctkVTKConnectionPrivate: public ctkPrivate<ctkVTKConnection>
  21. {
  22. public:
  23. enum
  24. {
  25. ARG_UNKNOWN = 0,
  26. ARG_VTKOBJECT_AND_VTKOBJECT,
  27. ARG_VTKOBJECT_VOID_ULONG_VOID
  28. };
  29. typedef ctkVTKConnectionPrivate Self;
  30. ctkVTKConnectionPrivate();
  31. ~ctkVTKConnectionPrivate();
  32. void connect();
  33. void disconnect();
  34. ///
  35. /// VTK Callback
  36. static void DoCallback(vtkObject* vtk_obj, unsigned long event,
  37. void* client_data, void* call_data);
  38. ///
  39. /// Called by 'DoCallback' to emit signal
  40. void Execute(vtkObject* vtk_obj, unsigned long vtk_event, void* client_data, void* call_data);
  41. vtkSmartPointer<vtkCallbackCommand> Callback;
  42. vtkObject* VTKObject;
  43. const QObject* QtObject;
  44. unsigned long VTKEvent;
  45. QString QtSlot;
  46. float Priority;
  47. int SlotType;
  48. bool Connected;
  49. bool Blocked;
  50. QString Id;
  51. bool AboutToBeDeleted;
  52. };
  53. //-----------------------------------------------------------------------------
  54. // ctkVTKConnectionPrivate methods
  55. //-----------------------------------------------------------------------------
  56. ctkVTKConnectionPrivate::ctkVTKConnectionPrivate()
  57. {
  58. this->Callback = vtkSmartPointer<vtkCallbackCommand>::New();
  59. this->Callback->SetCallback(ctkVTKConnectionPrivate::DoCallback);
  60. this->Callback->SetClientData(this);
  61. this->VTKObject = 0;
  62. this->QtObject = 0;
  63. this->VTKEvent = vtkCommand::NoEvent;
  64. this->Priority = 0.0;
  65. this->SlotType = ARG_UNKNOWN;
  66. this->Connected = false;
  67. this->Blocked = false;
  68. this->Id = convertPointerToString(this);
  69. this->AboutToBeDeleted = false;
  70. }
  71. //-----------------------------------------------------------------------------
  72. ctkVTKConnectionPrivate::~ctkVTKConnectionPrivate()
  73. {
  74. /*
  75. if(this->VTKObject && this->Connected)
  76. {
  77. this->VTKObject->RemoveObserver(this->Callback);
  78. //Qt takes care of disconnecting slots
  79. }
  80. */
  81. }
  82. //-----------------------------------------------------------------------------
  83. void ctkVTKConnectionPrivate::connect()
  84. {
  85. CTK_P(ctkVTKConnection);
  86. if (this->Connected)
  87. {
  88. qDebug() << "ctkVTKConnection already connected.";
  89. return;
  90. }
  91. switch (this->SlotType)
  92. {
  93. case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
  94. QObject::connect(p, SIGNAL(emitExecute(vtkObject*, vtkObject*)),
  95. this->QtObject, this->QtSlot.toLatin1().data());
  96. break;
  97. case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
  98. QObject::connect(p, SIGNAL(emitExecute(vtkObject*, void*, unsigned long, void*)),
  99. this->QtObject, this->QtSlot.toLatin1().data());
  100. break;
  101. default:
  102. Q_ASSERT(false);
  103. qCritical() << "Failed to connect - "
  104. << "The slot (" << this->QtSlot << ") owned by "
  105. << "QObject(" << this->QtObject->objectName() << ")"
  106. << " seems to have a wrong signature.";
  107. break;
  108. }
  109. // Make a connection between this and the vtk object
  110. this->VTKObject->AddObserver(this->VTKEvent, this->Callback, this->Priority);
  111. // If necessary, observe vtk DeleteEvent
  112. if(this->VTKEvent != vtkCommand::DeleteEvent)
  113. {
  114. this->VTKObject->AddObserver(vtkCommand::DeleteEvent, this->Callback);
  115. }
  116. // Remove itself from its parent when vtkObject is deleted
  117. QObject::connect(this->QtObject, SIGNAL(destroyed(QObject*)),
  118. p, SLOT(deleteConnection()));
  119. this->Connected = true;
  120. }
  121. //-----------------------------------------------------------------------------
  122. void ctkVTKConnectionPrivate::disconnect()
  123. {
  124. CTK_P(ctkVTKConnection);
  125. if (!this->Connected)
  126. {
  127. Q_ASSERT(this->Connected);
  128. return;
  129. }
  130. this->VTKObject->RemoveObserver(this->Callback);
  131. switch (this->SlotType)
  132. {
  133. case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
  134. QObject::disconnect(p, SIGNAL(emitExecute(vtkObject*, vtkObject*)),
  135. this->QtObject,this->QtSlot.toLatin1().data());
  136. break;
  137. case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
  138. QObject::disconnect(p, SIGNAL(emitExecute(vtkObject*, void*, unsigned long, void*)),
  139. this->QtObject, this->QtSlot.toLatin1().data());
  140. break;
  141. default:
  142. Q_ASSERT(false);
  143. qCritical() << "Failed to disconnect - "
  144. << "The slot (" << this->QtSlot << ") owned by "
  145. << "QObject(" << this->QtObject->objectName() << ")"
  146. << " seems to have a wrong signature.";
  147. break;
  148. }
  149. QObject::disconnect(this->QtObject, SIGNAL(destroyed(QObject*)),
  150. p, SLOT(deleteConnection()));
  151. this->Connected = false;
  152. }
  153. //-----------------------------------------------------------------------------
  154. // ctkVTKConnection methods
  155. //-----------------------------------------------------------------------------
  156. ctkVTKConnection::ctkVTKConnection(QObject* _parent):
  157. Superclass(_parent)
  158. {
  159. CTK_INIT_PRIVATE(ctkVTKConnection);
  160. }
  161. //-----------------------------------------------------------------------------
  162. ctkVTKConnection::~ctkVTKConnection()
  163. {
  164. this->setEnabled(false);
  165. }
  166. //-----------------------------------------------------------------------------
  167. CTK_GET_CXX(ctkVTKConnection, QString, id, Id);
  168. //-----------------------------------------------------------------------------
  169. void ctkVTKConnection::printAdditionalInfo()
  170. {
  171. this->Superclass::dumpObjectInfo();
  172. CTK_D(ctkVTKConnection);
  173. qDebug() << "ctkVTKConnection:" << this << endl
  174. << "Id:" << d->Id << endl
  175. << " VTKObject:" << d->VTKObject->GetClassName()
  176. << "(" << d->VTKObject << ")" << endl
  177. << " QtObject:" << d->QtObject << endl
  178. << " VTKEvent:" << d->VTKEvent << endl
  179. << " QtSlot:" << d->QtSlot << endl
  180. << " SlotType:" << d->SlotType << endl
  181. << " Priority:" << d->Priority << endl
  182. << " Connected:" << d->Connected << endl
  183. << " Blocked:" << d->Blocked;
  184. }
  185. //-----------------------------------------------------------------------------
  186. QString ctkVTKConnection::shortDescription()
  187. {
  188. CTK_D(ctkVTKConnection);
  189. return Self::shortDescription(d->VTKObject, d->VTKEvent, d->QtObject, d->QtSlot);
  190. }
  191. //-----------------------------------------------------------------------------
  192. QString ctkVTKConnection::shortDescription(vtkObject* vtk_obj, unsigned long vtk_event,
  193. const QObject* qt_obj, QString qt_slot)
  194. {
  195. QString ret;
  196. QTextStream ts( &ret );
  197. ts << (vtk_obj ? vtk_obj->GetClassName() : "NULL") << " "
  198. << vtk_event << " " << qt_obj << " " << qt_slot;
  199. return ret;
  200. }
  201. //-----------------------------------------------------------------------------
  202. bool ctkVTKConnection::ValidateParameters(vtkObject* vtk_obj, unsigned long vtk_event,
  203. const QObject* qt_obj, QString qt_slot)
  204. {
  205. Q_UNUSED(vtk_event);
  206. if (!vtk_obj)
  207. {
  208. return false;
  209. }
  210. if (!qt_obj)
  211. {
  212. return false;
  213. }
  214. if (qt_slot.isEmpty())
  215. {
  216. return false;
  217. }
  218. return true;
  219. }
  220. //-----------------------------------------------------------------------------
  221. void ctkVTKConnection::SetParameters(vtkObject* vtk_obj, unsigned long vtk_event,
  222. const QObject* qt_obj, QString qt_slot, float priority)
  223. {
  224. CTK_D(ctkVTKConnection);
  225. if (!Self::ValidateParameters(vtk_obj, vtk_event, qt_obj, qt_slot))
  226. {
  227. return;
  228. }
  229. d->VTKObject = vtk_obj;
  230. d->QtObject = qt_obj;
  231. d->VTKEvent = vtk_event;
  232. d->QtSlot = qt_slot;
  233. d->Priority = priority;
  234. if (qt_slot.contains(QRegExp(QString("\\( ?vtkObject ?\\* ?, ?vtkObject ?\\* ?\\)"))))
  235. {
  236. d->SlotType = ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT;
  237. }
  238. else
  239. {
  240. d->SlotType = ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID;
  241. }
  242. }
  243. //-----------------------------------------------------------------------------
  244. void ctkVTKConnection::setEnabled(bool enable)
  245. {
  246. CTK_D(ctkVTKConnection);
  247. if (d->Connected == enable)
  248. {
  249. return;
  250. }
  251. if (enable)
  252. {
  253. d->connect();
  254. }
  255. else
  256. {
  257. d->disconnect();
  258. }
  259. }
  260. //-----------------------------------------------------------------------------
  261. bool ctkVTKConnection::isEnabled()const
  262. {
  263. CTK_D(const ctkVTKConnection);
  264. return d->Connected;
  265. }
  266. //-----------------------------------------------------------------------------
  267. void ctkVTKConnection::setBlocked(bool block)
  268. {
  269. CTK_D(ctkVTKConnection);
  270. d->Blocked = block;
  271. }
  272. //-----------------------------------------------------------------------------
  273. bool ctkVTKConnection::isBlocked()const
  274. {
  275. CTK_D(const ctkVTKConnection);
  276. return d->Blocked;
  277. }
  278. //-----------------------------------------------------------------------------
  279. bool ctkVTKConnection::isEqual(vtkObject* vtk_obj, unsigned long vtk_event,
  280. const QObject* qt_obj, QString qt_slot)const
  281. {
  282. CTK_D(const ctkVTKConnection);
  283. if (d->VTKObject != vtk_obj)
  284. {
  285. return false;
  286. }
  287. if (vtk_event != vtkCommand::NoEvent && d->VTKEvent != vtk_event)
  288. {
  289. return false;
  290. }
  291. if (qt_obj && d->QtObject != qt_obj)
  292. {
  293. return false;
  294. }
  295. if (!qt_slot.isEmpty() &&
  296. (QString(d->QtSlot).remove(' ').compare(
  297. QString(qt_slot).remove(' ')) != 0))
  298. {
  299. return false;
  300. }
  301. return true;
  302. }
  303. //-----------------------------------------------------------------------------
  304. void ctkVTKConnectionPrivate::DoCallback(vtkObject* vtk_obj, unsigned long event,
  305. void* client_data, void* call_data)
  306. {
  307. ctkVTKConnectionPrivate* conn = static_cast<ctkVTKConnectionPrivate*>(client_data);
  308. Q_ASSERT(conn);
  309. conn->Execute(vtk_obj, event, client_data, call_data);
  310. }
  311. //-----------------------------------------------------------------------------
  312. // callback from VTK to emit signal
  313. void ctkVTKConnectionPrivate::Execute(vtkObject* vtk_obj, unsigned long vtk_event,
  314. void* client_data, void* call_data)
  315. {
  316. CTK_P(ctkVTKConnection);
  317. Q_ASSERT(this->Connected);
  318. if (this->Blocked)
  319. {
  320. return;
  321. }
  322. if (vtk_event == vtkCommand::DeleteEvent)
  323. {
  324. this->AboutToBeDeleted = true;
  325. }
  326. if(vtk_event != vtkCommand::DeleteEvent ||
  327. (vtk_event == vtkCommand::DeleteEvent && this->VTKEvent == vtkCommand::DeleteEvent))
  328. {
  329. vtkObject* callDataAsVtkObject = 0;
  330. switch (this->SlotType)
  331. {
  332. case ctkVTKConnectionPrivate::ARG_VTKOBJECT_AND_VTKOBJECT:
  333. if (this->VTKEvent == vtk_event)
  334. {
  335. callDataAsVtkObject = reinterpret_cast<vtkObject*>( call_data );
  336. if (!callDataAsVtkObject)
  337. {
  338. qCritical() << "The VTKEvent(" << this->VTKEvent<< ") triggered by vtkObject("
  339. << this->VTKObject->GetClassName() << ") "
  340. << "doesn't return data of type vtkObject." << endl
  341. << "The slot (" << this->QtSlot << ") owned by "
  342. << "QObject(" << this->QtObject->objectName() << ")"
  343. << " may be incorrect.";
  344. }
  345. emit p->emitExecute(vtk_obj, callDataAsVtkObject);
  346. }
  347. break;
  348. case ctkVTKConnectionPrivate::ARG_VTKOBJECT_VOID_ULONG_VOID:
  349. emit p->emitExecute(vtk_obj, call_data, vtk_event, client_data);
  350. break;
  351. default:
  352. // Should never reach
  353. qCritical() << "Unknown SlotType:" << this->SlotType;
  354. return;
  355. break;
  356. }
  357. }
  358. if(vtk_event == vtkCommand::DeleteEvent)
  359. {
  360. this->AboutToBeDeleted = false;
  361. p->deleteConnection();
  362. }
  363. }
  364. void ctkVTKConnection::deleteConnection()
  365. {
  366. CTK_D(ctkVTKConnection);
  367. if (d->AboutToBeDeleted)
  368. {
  369. return;
  370. }
  371. delete this;
  372. }