/*========================================================================= Library: CTK Copyright (c) Kitware Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.txt Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. =========================================================================*/ // Qt includes #include #include #include #include #include // CTK includes #include "ctkCmdLineModuleManager.h" #include "ctkCmdLineModuleFrontendQtGui.h" #include "ctkCmdLineModuleBackendFunctionPointer.h" #include "ctkCmdLineModuleParameter.h" #include "ctkCmdLineModuleParameterGroup.h" #include "ctkCmdLineModuleDescription.h" #include "ctkCmdLineModuleXslTransform.h" #include "ctkCmdLineModuleFuture.h" #include "ctkTest.h" // ---------------------------------------------------------------------------- struct MyImageData : public ctk::CmdLineModuleBackendFunctionPointer::ImageType { MyImageData(const QString& path = QString()) : Path(path) {} QString Path; }; Q_DECLARE_METATYPE(MyImageData) Q_DECLARE_METATYPE(const MyImageData*) // ---------------------------------------------------------------------------- namespace ctk { namespace CmdLineModuleBackendFunctionPointer { template<> QString GetParameterTypeName() { return "image"; } }} // ---------------------------------------------------------------------------- class MyImageComboBox : public QComboBox { Q_OBJECT public: Q_PROPERTY(QString currentValue READ currentValue WRITE setCurrentValue) Q_PROPERTY(const MyImageData* currentImage READ currentImage) MyImageComboBox(QWidget* parent = 0) : QComboBox(parent) { imageData << MyImageData("/path/to/image1") << MyImageData("/path/to/image2") << MyImageData("/path/to/image3"); this->addItem("Image 1"); this->addItem("Image 2"); this->addItem("Image 3"); } QString currentValue() const { return this->imageData.at(this->currentIndex()).Path; } void setCurrentValue(const QString& path) { this->imageData[this->currentIndex()].Path = path; } const MyImageData* currentImage() const { return &this->imageData.at(this->currentIndex()); } private: QList imageData; }; // ---------------------------------------------------------------------------- class MyQtGuiFrontend : public ctkCmdLineModuleFrontendQtGui { public: MyQtGuiFrontend(const ctkCmdLineModuleReference& moduleRef) : ctkCmdLineModuleFrontendQtGui(moduleRef) {} QUiLoader* uiLoader() const { struct MyUiLoader : public QUiLoader { QStringList availableWidgets() const { return QUiLoader::availableWidgets() << "MyImageComboBox"; } QWidget* createWidget(const QString& className, QWidget* parent, const QString& name) { if (className == "MyImageComboBox") { MyImageComboBox* comboBox = new MyImageComboBox(parent); comboBox->setObjectName(name); comboBox->setCurrentIndex(1); return comboBox; } return QUiLoader::createWidget(className, parent, name); } }; static MyUiLoader myUiLoader; return &myUiLoader; } ctkCmdLineModuleXslTransform* xslTransform() const { static bool initialized = false; ctkCmdLineModuleXslTransform* transform = ctkCmdLineModuleFrontendQtGui::xslTransform(); if (!initialized) { transform->bindVariable("imageInputWidget", "MyImageComboBox"); static QFile extraXsl(":/MyImageComboBoxTest.xsl"); transform->setXslExtraTransformation(&extraXsl); initialized = true; } return transform; } QVariant value(const QString ¶meter, int role) const { if (role == UserRole) { ctkCmdLineModuleParameter param = this->moduleReference().description().parameter(parameter); if (param.channel() == "input" && param.tag() == "image") { return this->customValue(parameter, "currentImage"); } return QVariant(); } return ctkCmdLineModuleFrontendQtGui::value(parameter, role); } }; // ---------------------------------------------------------------------------- class MyFpBackend : public ctkCmdLineModuleBackendFunctionPointer { protected: QList arguments(ctkCmdLineModuleFrontend *frontend) const { QList args; foreach(ctkCmdLineModuleParameter param, frontend->parameters()) { QVariant arg = frontend->value(param.name(), ctkCmdLineModuleFrontend::UserRole); if (!arg.isValid()) { arg = frontend->value(param.name()); } args << arg; } return args; } }; // ---------------------------------------------------------------------------- QString CustomImageDataPath; void CustomImageTypeModule(const MyImageData* imageData) { CustomImageDataPath = imageData->Path; } // ---------------------------------------------------------------------------- class ctkCmdLineModuleQtCustomizationTester: public QObject { Q_OBJECT private Q_SLOTS: void testCustomization(); }; // ---------------------------------------------------------------------------- void ctkCmdLineModuleQtCustomizationTester::testCustomization() { qRegisterMetaType("const MyImageData*"); ctkCmdLineModuleManager moduleManager; MyFpBackend fpBackend; fpBackend.registerFunctionPointer("Image Type Customization", CustomImageTypeModule); moduleManager.registerBackend(&fpBackend); QUrl url = fpBackend.registeredFunctionPointers().front(); moduleManager.registerModule(url); ctkCmdLineModuleReference moduleRef = moduleManager.moduleReference(url); ctkCmdLineModuleFrontend* fpFrontend = new MyQtGuiFrontend(moduleRef); // force the creation of the frontend gui fpFrontend->guiHandle(); QString expectedImageValue = "/path/to/image2"; QCOMPARE(fpFrontend->value("param0").toString(), expectedImageValue); // get a custom QVariant value holding the custom widget QCOMPARE(fpFrontend->value("param0", ctkCmdLineModuleFrontend::UserRole).value()->Path, expectedImageValue); // now set the property for the "LocalResourceRole" (the default property) to something else expectedImageValue = "/tmp/path/to/image2"; fpFrontend->setValue("param0", expectedImageValue); QCOMPARE(fpFrontend->value("param0").toString(), expectedImageValue); QVERIFY(CustomImageDataPath.isEmpty()); // run the module (function pointer) and check that is gets the tmp path ctkCmdLineModuleFuture future = moduleManager.run(fpFrontend); QTest::qSleep(500); QApplication::processEvents(); future.waitForFinished(); QCOMPARE(CustomImageDataPath, expectedImageValue); } // ---------------------------------------------------------------------------- CTK_TEST_MAIN(ctkCmdLineModuleQtCustomizationTest) #include "moc_ctkCmdLineModuleQtCustomizationTest.cpp"