ctkCmdLineModuleQtCustomizationTest.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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 <QList>
  16. #include <QString>
  17. #include <QComboBox>
  18. #include <QUiLoader>
  19. #include <QApplication>
  20. // CTK includes
  21. #include "ctkCmdLineModuleManager.h"
  22. #include "ctkCmdLineModuleFrontendQtGui.h"
  23. #include "ctkCmdLineModuleBackendFunctionPointer.h"
  24. #include "ctkCmdLineModuleParameter.h"
  25. #include "ctkCmdLineModuleParameterGroup.h"
  26. #include "ctkCmdLineModuleDescription.h"
  27. #include "ctkCmdLineModuleXslTransform.h"
  28. #include "ctkCmdLineModuleFuture.h"
  29. #include "ctkTest.h"
  30. // ----------------------------------------------------------------------------
  31. struct MyImageData : public ctk::CmdLineModuleBackendFunctionPointer::ImageType
  32. {
  33. MyImageData(const QString& path = QString())
  34. : Path(path)
  35. {}
  36. QString Label;
  37. QString Path;
  38. };
  39. Q_DECLARE_METATYPE(MyImageData)
  40. Q_DECLARE_METATYPE(const MyImageData*)
  41. // ----------------------------------------------------------------------------
  42. namespace ctk {
  43. namespace CmdLineModuleBackendFunctionPointer {
  44. template<>
  45. QString GetParameterTypeName<MyImageData>()
  46. {
  47. return "image";
  48. }
  49. }}
  50. // ----------------------------------------------------------------------------
  51. class MyImageComboBox : public QComboBox
  52. {
  53. Q_OBJECT
  54. public:
  55. Q_PROPERTY(QString currentLabel READ currentLabel WRITE setCurrentLabel)
  56. Q_PROPERTY(QString currentPath READ currentPath WRITE setCurrentPath)
  57. Q_PROPERTY(const MyImageData* currentImage READ currentImage)
  58. MyImageComboBox(QWidget* parent = 0)
  59. : QComboBox(parent)
  60. {
  61. imageData << MyImageData("/path/to/image1")
  62. << MyImageData("/path/to/image2")
  63. << MyImageData("/path/to/image3");
  64. this->addItem("Image 1");
  65. this->addItem("Image 2");
  66. this->addItem("Image 3");
  67. }
  68. QString currentLabel() const
  69. {
  70. return this->imageData.at(this->currentIndex()).Label;
  71. }
  72. void setCurrentLabel(const QString& label)
  73. {
  74. for(int i = 0; i < imageData.size(); ++i)
  75. {
  76. if (imageData[i].Label == label)
  77. {
  78. this->setCurrentIndex(i);
  79. break;
  80. }
  81. }
  82. }
  83. QString currentPath() const
  84. {
  85. return this->imageData.at(this->currentIndex()).Path;
  86. }
  87. void setCurrentPath(const QString& path)
  88. {
  89. this->imageData[this->currentIndex()].Path = path;
  90. }
  91. const MyImageData* currentImage() const
  92. {
  93. return &this->imageData.at(this->currentIndex());
  94. }
  95. private:
  96. QList<MyImageData> imageData;
  97. };
  98. // ----------------------------------------------------------------------------
  99. class MyQtGuiFrontend : public ctkCmdLineModuleFrontendQtGui
  100. {
  101. public:
  102. MyQtGuiFrontend(const ctkCmdLineModuleReference& moduleRef)
  103. : ctkCmdLineModuleFrontendQtGui(moduleRef)
  104. {}
  105. QUiLoader* uiLoader() const
  106. {
  107. struct MyUiLoader : public QUiLoader {
  108. QStringList availableWidgets() const
  109. {
  110. return QUiLoader::availableWidgets() << "MyImageComboBox";
  111. }
  112. QWidget* createWidget(const QString& className, QWidget* parent, const QString& name)
  113. {
  114. if (className == "MyImageComboBox")
  115. {
  116. MyImageComboBox* comboBox = new MyImageComboBox(parent);
  117. comboBox->setObjectName(name);
  118. comboBox->setCurrentIndex(1);
  119. return comboBox;
  120. }
  121. return QUiLoader::createWidget(className, parent, name);
  122. }
  123. };
  124. static MyUiLoader myUiLoader;
  125. return &myUiLoader;
  126. }
  127. ctkCmdLineModuleXslTransform* xslTransform() const
  128. {
  129. static bool initialized = false;
  130. ctkCmdLineModuleXslTransform* transform = ctkCmdLineModuleFrontendQtGui::xslTransform();
  131. if (!initialized)
  132. {
  133. transform->bindVariable("imageInputWidget", "MyImageComboBox");
  134. transform->bindVariable("imageValueProperty", "currentLabel");
  135. static QFile extraXsl(":/MyImageComboBoxTest.xsl");
  136. transform->setXslExtraTransformation(&extraXsl);
  137. initialized = true;
  138. }
  139. return transform;
  140. }
  141. QVariant value(const QString &parameter, int role = LocalResourceRole) const
  142. {
  143. if (role == UserRole)
  144. {
  145. ctkCmdLineModuleParameter param = this->moduleReference().description().parameter(parameter);
  146. if (param.channel() == "input" && param.tag() == "image")
  147. {
  148. return this->customValue(parameter, "currentImage");
  149. }
  150. return QVariant();
  151. }
  152. else if (role == LocalResourceRole)
  153. {
  154. return this->customValue(parameter, "currentPath");
  155. }
  156. else
  157. {
  158. return ctkCmdLineModuleFrontendQtGui::value(parameter, role);
  159. }
  160. }
  161. void setValue(const QString &parameter, const QVariant &value, int role = DisplayRole)
  162. {
  163. if (role == LocalResourceRole)
  164. {
  165. this->setCustomValue(parameter, value, "currentPath");
  166. }
  167. else
  168. {
  169. ctkCmdLineModuleFrontendQtGui::setValue(parameter, value, role);
  170. }
  171. }
  172. };
  173. // ----------------------------------------------------------------------------
  174. class MyFpBackend : public ctkCmdLineModuleBackendFunctionPointer
  175. {
  176. protected:
  177. QList<QVariant> arguments(ctkCmdLineModuleFrontend *frontend) const
  178. {
  179. QList<QVariant> args;
  180. foreach(ctkCmdLineModuleParameter param, frontend->parameters())
  181. {
  182. QVariant arg = frontend->value(param.name(), ctkCmdLineModuleFrontend::UserRole);
  183. if (!arg.isValid())
  184. {
  185. arg = frontend->value(param.name());
  186. }
  187. args << arg;
  188. }
  189. return args;
  190. }
  191. };
  192. // ----------------------------------------------------------------------------
  193. QString CustomImageDataPath;
  194. void CustomImageTypeModule(const MyImageData* imageData)
  195. {
  196. CustomImageDataPath = imageData->Path;
  197. }
  198. // ----------------------------------------------------------------------------
  199. class ctkCmdLineModuleQtCustomizationTester: public QObject
  200. {
  201. Q_OBJECT
  202. private Q_SLOTS:
  203. void testCustomization();
  204. };
  205. // ----------------------------------------------------------------------------
  206. void ctkCmdLineModuleQtCustomizationTester::testCustomization()
  207. {
  208. qRegisterMetaType<const MyImageData*>("const MyImageData*");
  209. ctkCmdLineModuleManager moduleManager;
  210. MyFpBackend fpBackend;
  211. fpBackend.registerFunctionPointer("Image Type Customization", CustomImageTypeModule);
  212. moduleManager.registerBackend(&fpBackend);
  213. QUrl url = fpBackend.registeredFunctionPointers().front();
  214. moduleManager.registerModule(url);
  215. ctkCmdLineModuleReference moduleRef = moduleManager.moduleReference(url);
  216. ctkCmdLineModuleFrontend* fpFrontend = new MyQtGuiFrontend(moduleRef);
  217. // force the creation of the frontend gui
  218. fpFrontend->guiHandle();
  219. QString expectedImageValue = "/path/to/image2";
  220. QString actualImageValue = fpFrontend->value("param0").toString();
  221. QCOMPARE(actualImageValue, expectedImageValue);
  222. // get a custom QVariant value holding the custom widget
  223. QCOMPARE(fpFrontend->value("param0", ctkCmdLineModuleFrontend::UserRole).value<const MyImageData*>()->Path,
  224. expectedImageValue);
  225. // now set the property for the "LocalResourceRole" (the default property) to something else
  226. expectedImageValue = "/tmp/path/to/image2";
  227. fpFrontend->setValue("param0", expectedImageValue, ctkCmdLineModuleFrontend::LocalResourceRole);
  228. QCOMPARE(fpFrontend->value("param0").toString(), expectedImageValue);
  229. QVERIFY(CustomImageDataPath.isEmpty());
  230. // run the module (function pointer) and check that is gets the tmp path
  231. ctkCmdLineModuleFuture future = moduleManager.run(fpFrontend);
  232. QTest::qSleep(500);
  233. QApplication::processEvents();
  234. future.waitForFinished();
  235. QCOMPARE(CustomImageDataPath, expectedImageValue);
  236. }
  237. // ----------------------------------------------------------------------------
  238. CTK_TEST_MAIN(ctkCmdLineModuleQtCustomizationTest)
  239. #include "moc_ctkCmdLineModuleQtCustomizationTest.cpp"