ctkVTKMagnifyView.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  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.apache.org/licenses/LICENSE-2.0.txt
  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 <QEvent>
  16. #include <QMouseEvent>
  17. #include <QPointF>
  18. #include <QTimerEvent>
  19. // CTK includes
  20. #include "ctkVTKMagnifyView.h"
  21. #include "ctkVTKMagnifyView_p.h"
  22. #include "ctkLogger.h"
  23. // VTK includes
  24. #if CTK_USE_QVTKOPENGLWIDGET
  25. #include <QVTKOpenGLWidget.h>
  26. #else
  27. #include <QVTKWidget.h>
  28. #endif
  29. #include <vtkMath.h>
  30. #include <vtkRenderWindow.h>
  31. #include <vtkUnsignedCharArray.h>
  32. // STD includes
  33. #include <cmath>
  34. //--------------------------------------------------------------------------
  35. static ctkLogger logger("org.commontk.visualization.vtk.widgets.ctkVTKMagnifyView");
  36. //--------------------------------------------------------------------------
  37. // --------------------------------------------------------------------------
  38. // ctkVTKMagnifyViewPrivate methods
  39. // --------------------------------------------------------------------------
  40. ctkVTKMagnifyViewPrivate::ctkVTKMagnifyViewPrivate(ctkVTKMagnifyView& object)
  41. : QObject(&object), q_ptr(&object)
  42. {
  43. #if CTK_USE_QVTKOPENGLWIDGET
  44. this->ObservedQVTKWidgets = QList<QVTKOpenGLWidget *>();
  45. #else
  46. this->ObservedQVTKWidgets = QList<QVTKWidget *>();
  47. #endif
  48. this->Magnification = 1.0;
  49. this->ObserveRenderWindowEvents = true;
  50. this->EventHandler.EventType = NoEvent;
  51. this->EventHandler.Position = QPointF(0,0);
  52. this->EventHandler.UpdateInterval = 20;
  53. this->EventHandler.TimerId = 0;
  54. }
  55. // --------------------------------------------------------------------------
  56. ctkVTKMagnifyViewPrivate::~ctkVTKMagnifyViewPrivate()
  57. {
  58. if (this->EventHandler.TimerId != 0)
  59. {
  60. this->killTimer(this->EventHandler.TimerId);
  61. }
  62. }
  63. // --------------------------------------------------------------------------
  64. void ctkVTKMagnifyViewPrivate::init()
  65. {
  66. // Start by removing the pixmap
  67. this->EventHandler.EventType = RemovePixmapEvent;
  68. this->removePixmap();
  69. // Start the timer
  70. this->restartTimer();
  71. }
  72. // --------------------------------------------------------------------------
  73. void ctkVTKMagnifyViewPrivate::restartTimer()
  74. {
  75. // Kill any old timers
  76. if (this->EventHandler.TimerId != 0)
  77. {
  78. this->killTimer(this->EventHandler.TimerId);
  79. this->EventHandler.TimerId = 0;
  80. }
  81. // Start timer if appropriate
  82. if (this->EventHandler.UpdateInterval != 0)
  83. {
  84. this->EventHandler.TimerId = this->startTimer(this->EventHandler.UpdateInterval);
  85. Q_ASSERT(this->EventHandler.TimerId);
  86. }
  87. // Not using any timers, process events as they come
  88. else
  89. {
  90. this->EventHandler.TimerId = 0;
  91. }
  92. }
  93. // --------------------------------------------------------------------------
  94. void ctkVTKMagnifyViewPrivate::resetEventHandler()
  95. {
  96. this->EventHandler.EventType = NoEvent;
  97. }
  98. // --------------------------------------------------------------------------
  99. void ctkVTKMagnifyViewPrivate::timerEvent(QTimerEvent * event)
  100. {
  101. Q_UNUSED(event);
  102. Q_ASSERT(event->timerId() == this->EventHandler.TimerId);
  103. if (this->EventHandler.EventType == UpdatePixmapEvent)
  104. {
  105. this->updatePixmap();
  106. }
  107. else if (this->EventHandler.EventType == RemovePixmapEvent)
  108. {
  109. this->removePixmap();
  110. }
  111. }
  112. // --------------------------------------------------------------------------
  113. void ctkVTKMagnifyViewPrivate::pushUpdatePixmapEvent()
  114. {
  115. if (this->EventHandler.Widget.isNull())
  116. {
  117. return;
  118. }
  119. this->pushUpdatePixmapEvent(
  120. this->EventHandler.Widget.data()->mapFromGlobal(QCursor::pos()));
  121. }
  122. // --------------------------------------------------------------------------
  123. void ctkVTKMagnifyViewPrivate::pushUpdatePixmapEvent(QPointF pos)
  124. {
  125. if (this->EventHandler.Widget.isNull())
  126. {
  127. return;
  128. }
  129. // Add this event to the queue
  130. this->EventHandler.EventType = UpdatePixmapEvent;
  131. this->EventHandler.Position = pos;
  132. // Process the event if we handle all events
  133. if (this->EventHandler.UpdateInterval == 0)
  134. {
  135. this->updatePixmap();
  136. }
  137. }
  138. // --------------------------------------------------------------------------
  139. void ctkVTKMagnifyViewPrivate::pushRemovePixmapEvent()
  140. {
  141. // Add this event to the queue
  142. this->EventHandler.EventType = RemovePixmapEvent;
  143. // Process the event if we handle all events
  144. if (this->EventHandler.UpdateInterval == 0)
  145. {
  146. this->removePixmap();
  147. }
  148. }
  149. // --------------------------------------------------------------------------
  150. #if CTK_USE_QVTKOPENGLWIDGET
  151. void ctkVTKMagnifyViewPrivate::connectRenderWindow(QVTKOpenGLWidget * widget)
  152. #else
  153. void ctkVTKMagnifyViewPrivate::connectRenderWindow(QVTKWidget * widget)
  154. #endif
  155. {
  156. Q_ASSERT(widget);
  157. Q_ASSERT(this->ObserveRenderWindowEvents);
  158. vtkRenderWindow * renderWindow = widget->GetRenderWindow();
  159. if (renderWindow)
  160. {
  161. this->qvtkConnect(renderWindow, vtkCommand::EndEvent,
  162. this, SLOT(pushUpdatePixmapEvent()));
  163. }
  164. }
  165. // --------------------------------------------------------------------------
  166. #if CTK_USE_QVTKOPENGLWIDGET
  167. void ctkVTKMagnifyViewPrivate::disconnectRenderWindow(QVTKOpenGLWidget * widget)
  168. #else
  169. void ctkVTKMagnifyViewPrivate::disconnectRenderWindow(QVTKWidget * widget)
  170. #endif
  171. {
  172. Q_ASSERT(widget);
  173. vtkRenderWindow * renderWindow = widget->GetRenderWindow();
  174. if (renderWindow)
  175. {
  176. this->qvtkDisconnect(renderWindow, vtkCommand::EndEvent,
  177. this, SLOT(pushUpdatePixmapEvent()));
  178. }
  179. }
  180. // --------------------------------------------------------------------------
  181. #if CTK_USE_QVTKOPENGLWIDGET
  182. void ctkVTKMagnifyViewPrivate::observe(QVTKOpenGLWidget * widget)
  183. #else
  184. void ctkVTKMagnifyViewPrivate::observe(QVTKWidget * widget)
  185. #endif
  186. {
  187. Q_ASSERT(widget);
  188. // If we are not already observing the widget, add it to the list and install
  189. // the public implementation as the event filter to handle mousing
  190. if (!this->ObservedQVTKWidgets.contains(widget))
  191. {
  192. this->ObservedQVTKWidgets.append(widget);
  193. Q_Q(ctkVTKMagnifyView);
  194. widget->installEventFilter(q);
  195. if (this->ObserveRenderWindowEvents)
  196. {
  197. this->connectRenderWindow(widget);
  198. }
  199. }
  200. }
  201. // --------------------------------------------------------------------------
  202. #if CTK_USE_QVTKOPENGLWIDGET
  203. void ctkVTKMagnifyViewPrivate::remove(QVTKOpenGLWidget * widget)
  204. #else
  205. void ctkVTKMagnifyViewPrivate::remove(QVTKWidget * widget)
  206. #endif
  207. {
  208. Q_ASSERT(widget);
  209. // If we are observing the widget, remove it from the list and remove the
  210. // public implementations event filtering
  211. if (this->ObservedQVTKWidgets.contains(widget))
  212. {
  213. Q_ASSERT(this->ObservedQVTKWidgets.count(widget) == 1);
  214. this->ObservedQVTKWidgets.removeOne(widget);
  215. Q_Q(ctkVTKMagnifyView);
  216. widget->removeEventFilter(q);
  217. if (this->ObserveRenderWindowEvents)
  218. {
  219. this->disconnectRenderWindow(widget);
  220. }
  221. }
  222. }
  223. // --------------------------------------------------------------------------
  224. void ctkVTKMagnifyViewPrivate::removePixmap()
  225. {
  226. Q_ASSERT(this->EventHandler.EventType == RemovePixmapEvent);
  227. Q_Q(ctkVTKMagnifyView);
  228. QPixmap nullPixmap;
  229. q->setPixmap(nullPixmap);
  230. q->update();
  231. this->resetEventHandler();
  232. }
  233. // -------------------------------------------------------------------------
  234. void ctkVTKMagnifyViewPrivate::updatePixmap()
  235. {
  236. Q_ASSERT(this->EventHandler.EventType == UpdatePixmapEvent);
  237. Q_ASSERT(!this->EventHandler.Widget.isNull());
  238. Q_Q(ctkVTKMagnifyView);
  239. // Retrieve buffer of given QVTKWidget from its render window
  240. vtkRenderWindow * renderWindow = this->EventHandler.Widget.data()->GetRenderWindow();
  241. if (!renderWindow)
  242. {
  243. return;
  244. }
  245. // Get the window size and mouse position, and do error checking
  246. QPointF pos = this->EventHandler.Position;
  247. int * windowSize = renderWindow->GetSize();
  248. QPointF mouseWindowPos(pos.x(), static_cast<double>(windowSize[1]-1)-pos.y());
  249. if (mouseWindowPos.x() < 0 || mouseWindowPos.x() >= windowSize[0] ||
  250. mouseWindowPos.y() < 0 || mouseWindowPos.y() >= windowSize[1])
  251. {
  252. return;
  253. }
  254. // Compute indices into the render window's data array
  255. // Given a magnification and the label's widget size, compute the number of
  256. // pixels we can show. We should round to get a larger integer extent, since
  257. // we will later adjust the pixmap's location in paintEvent().
  258. // Left-right and up-down are in the render window coordinate frame.
  259. // (which is different in the y-direction compared to Qt coordinates).
  260. QSizeF sizeToMagnify = QSizeF(q->size()) / this->Magnification;
  261. double posLeft = (mouseWindowPos.x() - ((sizeToMagnify.width()-1.0) / 2.0));
  262. double posRight = (mouseWindowPos.x() + ((sizeToMagnify.width()-1.0) / 2.0));
  263. double posBottom = (mouseWindowPos.y() - ((sizeToMagnify.height()-1.0) / 2.0));
  264. double posTop = (mouseWindowPos.y() + ((sizeToMagnify.height()-1.0) / 2.0));
  265. // Round to ints, for indexing into the pixel array
  266. int indexLeft = std::floor(posLeft);
  267. int indexRight = std::ceil(posRight);
  268. int indexBottom = std::floor(posBottom);
  269. int indexTop = std::ceil(posTop);
  270. // Handle when mouse is near the border
  271. int minLeft = 0;
  272. int maxRight = windowSize[0]-1;
  273. int minBottom = 0;
  274. int maxTop = windowSize[1]-1;
  275. bool overLeft = indexLeft < minLeft;
  276. bool overRight = indexRight > maxRight;
  277. bool overBottom = indexBottom < minBottom;
  278. bool overTop = indexTop > maxTop;
  279. // Ensure we don't access nonexistant indices
  280. if (overLeft)
  281. {
  282. indexLeft = minLeft;
  283. posLeft = minLeft;
  284. }
  285. if (overRight)
  286. {
  287. indexRight = maxRight;
  288. posRight = maxRight;
  289. }
  290. if (overBottom)
  291. {
  292. indexBottom = minBottom;
  293. posBottom = minBottom;
  294. }
  295. if (overTop)
  296. {
  297. indexTop = maxTop;
  298. posTop = maxTop;
  299. }
  300. // Error case
  301. if (indexLeft > indexRight || indexBottom > indexTop)
  302. {
  303. return;
  304. }
  305. // Setup the pixelmap's position in the label
  306. Qt::Alignment alignment;
  307. if (overLeft && !overRight)
  308. {
  309. alignment = Qt::AlignRight;
  310. }
  311. else if (overRight && !overLeft)
  312. {
  313. alignment = Qt::AlignLeft;
  314. }
  315. else
  316. {
  317. alignment = Qt::AlignLeft;
  318. }
  319. if (overBottom && !overTop)
  320. {
  321. alignment = alignment | Qt::AlignTop;
  322. }
  323. else if (overTop && !overBottom)
  324. {
  325. alignment = alignment | Qt::AlignBottom;
  326. }
  327. else
  328. {
  329. alignment = alignment | Qt::AlignTop;
  330. }
  331. q->setAlignment(alignment);
  332. // Retrieve the pixel data into a QImage (flip vertically to move from render
  333. // window coordinates to Qt coordinates)
  334. QSize actualSize(indexRight-indexLeft+1, indexTop-indexBottom+1);
  335. QImage image(actualSize.width(), actualSize.height(), QImage::Format_RGB32);
  336. vtkUnsignedCharArray * pixelData = vtkUnsignedCharArray::New();
  337. pixelData->SetArray(image.bits(), actualSize.width() * actualSize.height() * 4, 1);
  338. int front = renderWindow->GetDoubleBuffer();
  339. int success = renderWindow->GetRGBACharPixelData(
  340. indexLeft, indexBottom, indexRight, indexTop, front, pixelData);
  341. if (!success)
  342. {
  343. return;
  344. }
  345. pixelData->Delete();
  346. image = image.rgbSwapped();
  347. image = image.mirrored();
  348. // Scale the image to zoom, using FastTransformation to prevent smoothing
  349. QSize imageSize = actualSize * this->Magnification;
  350. image = image.scaled(imageSize, Qt::KeepAspectRatioByExpanding,
  351. Qt::FastTransformation);
  352. // Crop the magnified image to solve the problem of magnified partial pixels
  353. double errorLeft
  354. = (posLeft - static_cast<double>(indexLeft)) * this->Magnification;
  355. double errorRight
  356. = (static_cast<double>(indexRight) - posRight) * this->Magnification;
  357. double errorBottom
  358. = (posBottom - static_cast<double>(indexBottom)) * this->Magnification;
  359. double errorTop
  360. = (static_cast<double>(indexTop) - posTop) * this->Magnification;
  361. // When cropping the Qt image, the 'adjust' variables are in Qt coordinates,
  362. // not render window coordinates (bottom and top switch).
  363. int cropIndexLeft = vtkMath::Round(errorLeft);
  364. int cropIndexRight = imageSize.width() - vtkMath::Round(errorRight) - 1;
  365. int cropIndexTop = vtkMath::Round(errorTop);
  366. int cropIndexBottom = imageSize.height() - vtkMath::Round(errorBottom) - 1;
  367. // Handle case when label size and magnification are not both even or odd
  368. // (errorLeft/errorRight/errorBottom/errorTop will have fractional component,
  369. // so cropped image wouldn't be the correct size unless we adjust further).
  370. int requiredWidth = vtkMath::Round((posRight - posLeft + 1) * this->Magnification);
  371. int requiredHeight = vtkMath::Round((posTop - posBottom + 1) * this->Magnification);
  372. int actualWidth = cropIndexRight - cropIndexLeft + 1;
  373. int actualHeight = cropIndexBottom - cropIndexTop + 1;
  374. int diffWidth = requiredWidth - actualWidth;
  375. int diffHeight = requiredHeight - actualHeight;
  376. // Too wide
  377. if (diffWidth < 0 && cropIndexRight != imageSize.width()-1)
  378. {
  379. Q_ASSERT(actualWidth - requiredWidth <= 1);
  380. cropIndexRight += diffWidth;
  381. }
  382. // Too narrow
  383. else if (diffWidth > 0 && cropIndexLeft != 0)
  384. {
  385. Q_ASSERT(requiredWidth - actualWidth <= 1);
  386. cropIndexLeft -= diffWidth;
  387. }
  388. // Too tall
  389. if (diffHeight < 0 && cropIndexBottom != imageSize.height()-1)
  390. {
  391. Q_ASSERT(actualHeight - requiredHeight <= 1);
  392. cropIndexBottom += diffHeight;
  393. }
  394. // Too short
  395. else if (diffHeight > 0 && cropIndexTop != 0)
  396. {
  397. Q_ASSERT(requiredHeight - actualHeight <= 1);
  398. cropIndexTop -= diffHeight;
  399. }
  400. // Finally crop the QImage for display
  401. QRect cropRect(QPoint(cropIndexLeft, cropIndexTop),
  402. QPoint(cropIndexRight, cropIndexBottom));
  403. image = image.copy(cropRect);
  404. // Finally, set the pixelmap to the new one we have created and update
  405. q->setPixmap(QPixmap::fromImage(image));
  406. q->update();
  407. this->resetEventHandler();
  408. }
  409. //---------------------------------------------------------------------------
  410. // ctkVTKMagnifyView methods
  411. // --------------------------------------------------------------------------
  412. ctkVTKMagnifyView::ctkVTKMagnifyView(QWidget* parentWidget)
  413. : Superclass(parentWidget)
  414. , d_ptr(new ctkVTKMagnifyViewPrivate(*this))
  415. {
  416. Q_D(ctkVTKMagnifyView);
  417. d->init();
  418. }
  419. // --------------------------------------------------------------------------
  420. ctkVTKMagnifyView::~ctkVTKMagnifyView()
  421. {
  422. }
  423. // --------------------------------------------------------------------------
  424. CTK_GET_CPP(ctkVTKMagnifyView, double, magnification, Magnification)
  425. // --------------------------------------------------------------------------
  426. void ctkVTKMagnifyView::setMagnification(double newMagnification)
  427. {
  428. Q_D(ctkVTKMagnifyView);
  429. if (newMagnification == d->Magnification || newMagnification <= 0)
  430. {
  431. return;
  432. }
  433. d->Magnification = newMagnification;
  434. this->update();
  435. }
  436. // --------------------------------------------------------------------------
  437. CTK_GET_CPP(ctkVTKMagnifyView, bool,
  438. observeRenderWindowEvents, ObserveRenderWindowEvents)
  439. // --------------------------------------------------------------------------
  440. void ctkVTKMagnifyView::setObserveRenderWindowEvents(bool newObserve)
  441. {
  442. Q_D(ctkVTKMagnifyView);
  443. if (newObserve == d->ObserveRenderWindowEvents)
  444. {
  445. return;
  446. }
  447. d->ObserveRenderWindowEvents = newObserve;
  448. // Connect/disconnect observations on vtkRenderWindow EndEvents, depending
  449. // on whether we are switching from not-observing to observing or from
  450. // observing to not-observing
  451. #if CTK_USE_QVTKOPENGLWIDGET
  452. QList<QVTKOpenGLWidget *>::iterator it = d->ObservedQVTKWidgets.begin();
  453. #else
  454. QList<QVTKWidget *>::iterator it = d->ObservedQVTKWidgets.begin();
  455. #endif
  456. while (it != d->ObservedQVTKWidgets.end())
  457. {
  458. if (newObserve)
  459. {
  460. d->connectRenderWindow(*it);
  461. }
  462. else
  463. {
  464. d->disconnectRenderWindow(*it);
  465. }
  466. ++it;
  467. }
  468. }
  469. // --------------------------------------------------------------------------
  470. int ctkVTKMagnifyView::updateInterval() const
  471. {
  472. Q_D(const ctkVTKMagnifyView);
  473. return d->EventHandler.UpdateInterval;
  474. }
  475. // --------------------------------------------------------------------------
  476. void ctkVTKMagnifyView::setUpdateInterval(int newInterval)
  477. {
  478. Q_D(ctkVTKMagnifyView);
  479. if (newInterval == d->EventHandler.UpdateInterval || newInterval < 0)
  480. {
  481. return;
  482. }
  483. d->EventHandler.UpdateInterval = newInterval;
  484. d->restartTimer();
  485. }
  486. // --------------------------------------------------------------------------
  487. #if CTK_USE_QVTKOPENGLWIDGET
  488. void ctkVTKMagnifyView::observe(QVTKOpenGLWidget * widget)
  489. #else
  490. void ctkVTKMagnifyView::observe(QVTKWidget * widget)
  491. #endif
  492. {
  493. Q_D(ctkVTKMagnifyView);
  494. if (widget)
  495. {
  496. d->observe(widget);
  497. }
  498. }
  499. // --------------------------------------------------------------------------
  500. #if CTK_USE_QVTKOPENGLWIDGET
  501. void ctkVTKMagnifyView::observe(QList<QVTKOpenGLWidget *> widgets)
  502. #else
  503. void ctkVTKMagnifyView::observe(QList<QVTKWidget *> widgets)
  504. #endif
  505. {
  506. #if CTK_USE_QVTKOPENGLWIDGET
  507. foreach(QVTKOpenGLWidget * widget, widgets)
  508. #else
  509. foreach(QVTKWidget * widget, widgets)
  510. #endif
  511. {
  512. this->observe(widget);
  513. }
  514. }
  515. // --------------------------------------------------------------------------
  516. #if CTK_USE_QVTKOPENGLWIDGET
  517. bool ctkVTKMagnifyView::isObserved(QVTKOpenGLWidget * widget) const
  518. #else
  519. bool ctkVTKMagnifyView::isObserved(QVTKWidget * widget) const
  520. #endif
  521. {
  522. if (!widget)
  523. {
  524. return false;
  525. }
  526. Q_D(const ctkVTKMagnifyView);
  527. return d->ObservedQVTKWidgets.contains(widget);
  528. }
  529. // --------------------------------------------------------------------------
  530. int ctkVTKMagnifyView::numberObserved() const
  531. {
  532. Q_D(const ctkVTKMagnifyView);
  533. return d->ObservedQVTKWidgets.length();
  534. }
  535. // --------------------------------------------------------------------------
  536. bool ctkVTKMagnifyView::hasCursorInObservedWidget()const
  537. {
  538. Q_D(const ctkVTKMagnifyView);
  539. // checking underMouse is faster than
  540. // QApplication::widgetAt(QCursor::pos())
  541. #if CTK_USE_QVTKOPENGLWIDGET
  542. foreach(const QVTKOpenGLWidget* widget, d->ObservedQVTKWidgets)
  543. #else
  544. foreach(const QVTKWidget* widget, d->ObservedQVTKWidgets)
  545. #endif
  546. {
  547. if (widget->underMouse())
  548. {
  549. return true;
  550. }
  551. }
  552. return false;
  553. }
  554. // --------------------------------------------------------------------------
  555. #if CTK_USE_QVTKOPENGLWIDGET
  556. void ctkVTKMagnifyView::remove(QVTKOpenGLWidget * widget)
  557. #else
  558. void ctkVTKMagnifyView::remove(QVTKWidget * widget)
  559. #endif
  560. {
  561. Q_D(ctkVTKMagnifyView);
  562. if (widget)
  563. {
  564. d->remove(widget);
  565. }
  566. }
  567. // --------------------------------------------------------------------------
  568. #if CTK_USE_QVTKOPENGLWIDGET
  569. void ctkVTKMagnifyView::remove(QList<QVTKOpenGLWidget *> widgets)
  570. #else
  571. void ctkVTKMagnifyView::remove(QList<QVTKWidget *> widgets)
  572. #endif
  573. {
  574. #if CTK_USE_QVTKOPENGLWIDGET
  575. foreach(QVTKOpenGLWidget * widget, widgets)
  576. #else
  577. foreach(QVTKWidget * widget, widgets)
  578. #endif
  579. {
  580. this->remove(widget);
  581. }
  582. }
  583. // --------------------------------------------------------------------------
  584. bool ctkVTKMagnifyView::eventFilter(QObject * obj, QEvent * event)
  585. {
  586. #if CTK_USE_QVTKOPENGLWIDGET
  587. // The given object should be a QVTKWidget in our list
  588. QVTKOpenGLWidget * widget = static_cast<QVTKOpenGLWidget *>(obj);
  589. #else
  590. // The given object should be a QVTKWidget in our list
  591. QVTKWidget * widget = static_cast<QVTKWidget *>(obj);
  592. #endif
  593. Q_ASSERT(widget);
  594. Q_D(ctkVTKMagnifyView);
  595. Q_ASSERT(d->ObservedQVTKWidgets.contains(widget));
  596. d->EventHandler.Widget = widget;
  597. QEvent::Type eventType = event->type();
  598. // On mouse move, update the pixmap with the zoomed image
  599. if (eventType == QEvent::MouseMove)
  600. {
  601. QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
  602. Q_ASSERT(mouseEvent);
  603. #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
  604. d->pushUpdatePixmapEvent(mouseEvent->localPos());
  605. #else
  606. d->pushUpdatePixmapEvent(mouseEvent->posF());
  607. #endif
  608. }
  609. // On enter, update the pixmap with the zoomed image (required for zooming when
  610. // widget is created with mouse already within it), and emit signal of enter event
  611. else if (eventType == QEvent::Enter)
  612. {
  613. d->pushUpdatePixmapEvent();
  614. emit enteredObservedWidget(widget);
  615. }
  616. // On leave, fill the pixmap with a solid color and emit signal of leave event
  617. else if (eventType == QEvent::Leave)
  618. {
  619. d->pushRemovePixmapEvent();
  620. emit leftObservedWidget(widget);
  621. }
  622. return this->Superclass::eventFilter(obj, event);
  623. }