ctkVTKMagnifyWidgetTest2.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  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 <QApplication>
  16. #include <QCursor>
  17. #include <QHBoxLayout>
  18. #include <QIcon>
  19. #include <QSignalSpy>
  20. #include <QStyle>
  21. #include <QTimer>
  22. // CTK includes
  23. #include "ctkVTKMagnifyWidget.h"
  24. #include "ctkCommandLineParser.h"
  25. #include "ctkVTKSliceView.h"
  26. // VTK includes
  27. #include <vtkImageReader2Factory.h>
  28. #include <vtkImageReader2.h>
  29. #include <vtkImageData.h>
  30. #include <vtkSmartPointer.h>
  31. // STD includes
  32. #include <cstdlib>
  33. #include <iostream>
  34. //-----------------------------------------------------------------------------
  35. bool imageCompare(ctkVTKMagnifyWidget * magnify, QString baselineDirectory,
  36. QString baselineFilename)
  37. {
  38. QImage output = QPixmap::grabWidget(magnify).toImage();
  39. QImage baseline(baselineDirectory + "/" + baselineFilename);
  40. return output == baseline;
  41. }
  42. //-----------------------------------------------------------------------------
  43. // (Used to create baselines, not during testing).
  44. void imageSave(ctkVTKMagnifyWidget * magnify, QString baselineDirectory,
  45. QString baselineFilename)
  46. {
  47. QImage output = QPixmap::grabWidget(magnify).toImage();
  48. output.save(baselineDirectory + "/" + baselineFilename);
  49. }
  50. //-----------------------------------------------------------------------------
  51. bool runBaselineTest(int time, QApplication& app, ctkVTKMagnifyWidget * magnify,
  52. QWidget * underWidget, bool shouldBeUnder,
  53. QString baselineDirectory, QString baselineFilename,
  54. QString errorMessage)
  55. {
  56. QTimer::singleShot(time, &app, SLOT(quit()));
  57. if (app.exec() == EXIT_FAILURE)
  58. {
  59. std::cerr << "ctkVTKMagnifyWidget exec failed when "
  60. << qPrintable(errorMessage) << std::endl;
  61. return false;
  62. }
  63. if (underWidget->underMouse() != shouldBeUnder)
  64. {
  65. std::cerr << "ctkMagnifyWidget mouse position failed when "
  66. << qPrintable(errorMessage) << std::endl;
  67. return false;
  68. }
  69. if (!imageCompare(magnify, baselineDirectory, baselineFilename))
  70. {
  71. std::cerr << "ctkVTKMagnifyWidget baseline comparison failed when "
  72. << qPrintable(errorMessage) << "." << std::endl;
  73. return false;
  74. }
  75. return true;
  76. }
  77. //-----------------------------------------------------------------------------
  78. int ctkVTKMagnifyWidgetTest2(int argc, char * argv [] )
  79. {
  80. QApplication app(argc, argv);
  81. // Command line parser
  82. ctkCommandLineParser parser;
  83. parser.addArgument("", "-D", QVariant::String);
  84. parser.addArgument("", "-V", QVariant::String);
  85. parser.addArgument("", "-I", QVariant::String);
  86. bool ok = false;
  87. QHash<QString, QVariant> parsedArgs = parser.parseArguments(app.arguments(), &ok);
  88. if (!ok)
  89. {
  90. std::cerr << qPrintable(parser.errorString()) << std::endl;
  91. return EXIT_FAILURE;
  92. }
  93. QString dataDirectory = parsedArgs["-D"].toString();
  94. QString baselineDirectory = parsedArgs["-V"].toString();
  95. bool interactive = parsedArgs["-I"].toBool();
  96. // Create the parent widget
  97. QWidget parentWidget;
  98. QHBoxLayout layout(&parentWidget);
  99. // Magnify widget parameters (we want an odd widget size and odd bullsEye)
  100. int size = 341;
  101. bool showCursor = true;
  102. QColor cursorColor = Qt::yellow;
  103. ctkCursorPixmapWidget::CursorType cursorType
  104. = ctkCursorPixmapWidget::BullsEyeCursor;
  105. double magnification = 17;
  106. QColor marginColor = Qt::magenta;
  107. // Create the magnify widget
  108. ctkVTKMagnifyWidget * magnify = new ctkVTKMagnifyWidget(&parentWidget);
  109. magnify->setMinimumSize(size,size);
  110. magnify->setMaximumSize(size,size);
  111. magnify->setShowCursor(showCursor);
  112. magnify->setCursorColor(cursorColor);
  113. magnify->setCursorType(cursorType);
  114. magnify->setBullsEyeWidth(magnification);
  115. magnify->setMarginColor(marginColor);
  116. magnify->setMagnification(magnification);
  117. layout.addWidget(magnify);
  118. // Test magnify widget parameters
  119. if (magnify->showCursor() != showCursor)
  120. {
  121. std::cerr << "ctkVTKMagnifyWidget:setShowCursor failed. "
  122. << magnify->showCursor() << std::endl;
  123. return EXIT_FAILURE;
  124. }
  125. if (magnify->cursorColor() != cursorColor)
  126. {
  127. std::cerr << "ctkVTKMagnifyWidget:setCursorColor failed. "
  128. << qPrintable(magnify->cursorColor().name()) << std::endl;
  129. return EXIT_FAILURE;
  130. }
  131. if (magnify->cursorType() != cursorType)
  132. {
  133. std::cerr << "ctkVTKMagnifyWidget:setCursorType failed. "
  134. << magnify->cursorType() << std::endl;
  135. return EXIT_FAILURE;
  136. }
  137. if (magnify->bullsEyeWidth() != magnification)
  138. {
  139. std::cerr << "ctkVTKMagnifyWidget:setBullsEyeWidth failed. "
  140. << magnify->bullsEyeWidth() << std::endl;
  141. return EXIT_FAILURE;
  142. }
  143. if (magnify->marginColor() != marginColor)
  144. {
  145. std::cerr << "ctkVTKMagnifyWidget:setMarginColor failed. "
  146. << qPrintable(magnify->marginColor().name()) << std::endl;
  147. return EXIT_FAILURE;
  148. }
  149. if (magnify->magnification() != magnification)
  150. {
  151. std::cerr << "ctkVTKMagnifyWidget:setMagnification failed. "
  152. << magnify->magnification() << std::endl;
  153. return EXIT_FAILURE;
  154. }
  155. // The remainder is interactive, so abort now if command line args specify otherwise
  156. if (interactive)
  157. {
  158. return EXIT_SUCCESS;
  159. }
  160. // Add observed ctkVTKSliceViews (there are three, and the first two are observed)
  161. QList<ctkVTKSliceView *> allSliceViews;
  162. int numSliceViews = 3;
  163. for (int i = 0; i < numSliceViews; i++)
  164. {
  165. allSliceViews.append(new ctkVTKSliceView(&parentWidget));
  166. layout.addWidget(allSliceViews[i]);
  167. }
  168. // Observe the first two widgets
  169. magnify->observe(allSliceViews[0]->VTKWidget());
  170. magnify->observe(allSliceViews[1]->VTKWidget());
  171. if (!magnify->isObserved(allSliceViews[0]->VTKWidget()) ||
  172. !magnify->isObserved(allSliceViews[1]->VTKWidget()) ||
  173. magnify->isObserved(allSliceViews[2]->VTKWidget()) ||
  174. magnify->numberObserved() != 2)
  175. {
  176. std::cerr << "ctkVTKMagnifyWidget:observe(QVTKWidget*) failed. "
  177. << "Number observed = " << magnify->numberObserved() << std::endl;
  178. return EXIT_FAILURE;
  179. }
  180. QString imageFilename = dataDirectory + "/" + "computerIcon.png";
  181. // Instanciate the reader factory
  182. vtkSmartPointer<vtkImageReader2Factory> imageFactory =
  183. vtkSmartPointer<vtkImageReader2Factory>::New();
  184. // Instanciate an image reader
  185. vtkSmartPointer<vtkImageReader2> imageReader;
  186. imageReader.TakeReference(imageFactory->CreateImageReader2(imageFilename.toLatin1()));
  187. if (!imageReader)
  188. {
  189. std::cerr << "Failed to instanciate image reader using: "
  190. << qPrintable(imageFilename) << std::endl;
  191. return EXIT_FAILURE;
  192. }
  193. // Read image
  194. imageReader->SetFileName(imageFilename.toLatin1());
  195. imageReader->Update();
  196. vtkSmartPointer<vtkImageData> image = imageReader->GetOutput();
  197. // Setup the slice views
  198. for (int i = 0; i < numSliceViews; i++)
  199. {
  200. allSliceViews[i]->setRenderEnabled(true);
  201. allSliceViews[i]->setMinimumSize(350,350);
  202. allSliceViews[i]->setImageData(image);
  203. allSliceViews[i]->setHighlightedBoxColor(Qt::yellow);
  204. allSliceViews[i]->scheduleRender();
  205. }
  206. int time = 200;
  207. // Get cursor points of interest, used in the following tests
  208. parentWidget.move(0,0);
  209. parentWidget.show();
  210. QTimer::singleShot(time, &app, SLOT(quit()));
  211. if (app.exec() == EXIT_FAILURE)
  212. {
  213. std::cerr << "ctkVTKMagnifyWidget:show failed the first time." << std::endl;
  214. return EXIT_FAILURE;
  215. }
  216. QPoint insideSlice0 = allSliceViews[0]->mapToGlobal(
  217. QPoint(allSliceViews[0]->width()/2 + 100, allSliceViews[0]->height()/2 + 100));
  218. QPoint outside = parentWidget.mapToGlobal(
  219. QPoint(parentWidget.width(), parentWidget.height()));
  220. QPoint insideSlice1 = allSliceViews[1]->mapToGlobal(
  221. QPoint(allSliceViews[1]->width()/2 - 50, allSliceViews[1]->height() - 50));
  222. QPoint insideSlice1edge = allSliceViews[1]->mapToGlobal(
  223. QPoint(allSliceViews[1]->width() - 5, allSliceViews[1]->height() - 100));
  224. QPoint insideSlice2 = allSliceViews[2]->mapToGlobal(
  225. QPoint(allSliceViews[2]->width()/2, allSliceViews[2]->height()/2));
  226. QPoint insideSlice0bottomRightCorner = allSliceViews[0]->mapToGlobal(
  227. QPoint(allSliceViews[0]->width()-1, allSliceViews[0]->height()-1));
  228. QPoint insideSlice0topLeftCorner = allSliceViews[0]->mapToGlobal(
  229. QPoint(0,0));
  230. parentWidget.hide();
  231. // Make sure the magnify widget magnifies right away when shown with the cursor inside
  232. // an observed QVTKWidget
  233. QCursor::setPos(insideSlice0);
  234. parentWidget.show();
  235. if (!runBaselineTest(time, app, magnify, allSliceViews[0], true,
  236. baselineDirectory, "ctkVTKMagnifyWidgetTest2a.png",
  237. "magnify widget first shown with cursor inside observed widget"))
  238. {
  239. return EXIT_FAILURE;
  240. }
  241. parentWidget.hide();
  242. // Make sure the magnify widget shows blank right away when shown with the cursor
  243. // outside the observed QVTKWidgets
  244. QCursor::setPos(outside);
  245. parentWidget.show();
  246. if (!runBaselineTest(time, app, magnify, &parentWidget, false,
  247. baselineDirectory, "ctkVTKMagnifyWidgetTest2b.png",
  248. "magnify widget first shown with cursor outside observed widget"))
  249. {
  250. return EXIT_FAILURE;
  251. }
  252. // Test magnification after move to allSliceViews[1]
  253. QCursor::setPos(insideSlice1);
  254. if (!runBaselineTest(time, app, magnify, allSliceViews[1], true,
  255. baselineDirectory, "ctkVTKMagnifyWidgetTest2c.png",
  256. "cursor moved inside 2nd observed widget the first time"))
  257. {
  258. return EXIT_FAILURE;
  259. }
  260. // Test magnification after move within allSliceViews[1] close to border
  261. QCursor::setPos(insideSlice1edge);
  262. if (!runBaselineTest(time, app, magnify, allSliceViews[1], true,
  263. baselineDirectory, "ctkVTKMagnifyWidgetTest2d.png",
  264. "cursor moved inside 2nd observed widget the second time"))
  265. {
  266. return EXIT_FAILURE;
  267. }
  268. // Test magnification after move outside an observed widget (should be blank)
  269. QCursor::setPos(insideSlice2);
  270. if (!runBaselineTest(time, app, magnify, allSliceViews[2], true,
  271. baselineDirectory, "ctkVTKMagnifyWidgetTest2e.png",
  272. "cursor moved inside unobserved widget"))
  273. {
  274. return EXIT_FAILURE;
  275. }
  276. // Test magnification after move back inside an observed widget (at extreme bottom
  277. // right corner)
  278. QCursor::setPos(insideSlice0bottomRightCorner);
  279. if (!runBaselineTest(time, app, magnify, allSliceViews[0], true,
  280. baselineDirectory, "ctkVTKMagnifyWidgetTest2f.png",
  281. "cursor moved to bottom-right corner of observed widget"))
  282. {
  283. return EXIT_FAILURE;
  284. }
  285. // Test magnification after move back inside an observed widget (at extreme top left
  286. // corner)
  287. QCursor::setPos(insideSlice0topLeftCorner);
  288. if (!runBaselineTest(time, app, magnify, allSliceViews[0], true,
  289. baselineDirectory, "ctkVTKMagnifyWidgetTest2g.png",
  290. "cursor moved to top-left corner of observed widget"))
  291. {
  292. return EXIT_FAILURE;
  293. }
  294. return EXIT_SUCCESS;
  295. }