diff --git a/doc/release/notes/pv-new-resource-menu-action.md b/doc/release/notes/pv-new-resource-menu-action.md new file mode 100644 index 0000000000000000000000000000000000000000..51f482570a21e7160b916b8b373eb336b761870e --- /dev/null +++ b/doc/release/notes/pv-new-resource-menu-action.md @@ -0,0 +1,13 @@ +## Introduce ParaView behavior that adds New Resource + +Operations that share a common theme in the contexts of functionality +and graphical presentation are added to common operation groups. We +have constructed a new operation group for the creation of new +Resources. To utilize this group, we have also added a file menu +option that allows a user to create a new Resource. + +### User-facing changes + +ParaView applications that load SMTK's pqAppComponents plugin now have +access to a menu action to construct a new SMTK resource, if an +operation is associated to that resource in the operation CreatorGroup. diff --git a/smtk/bridge/multiscale/Registrar.cxx b/smtk/bridge/multiscale/Registrar.cxx index 51ac0cfa4fe2d07226d5c7c1b3d2fd5b71c17971..feeecd2f288b246d615a7e5089d023c44b0896e6 100644 --- a/smtk/bridge/multiscale/Registrar.cxx +++ b/smtk/bridge/multiscale/Registrar.cxx @@ -22,6 +22,7 @@ #include "smtk/operation/RegisterPythonOperations.h" +#include "smtk/operation/groups/CreatorGroup.h" #include "smtk/operation/groups/ImporterGroup.h" #include "smtk/operation/groups/ReaderGroup.h" #include "smtk/operation/groups/WriterGroup.h" @@ -50,6 +51,10 @@ void Registrar::registerTo(const smtk::operation::Manager::Ptr& operationManager smtk::operation::registerPythonOperations( operationManager, "smtk.bridge.multiscale.import_from_deform"); + smtk::operation::CreatorGroup(operationManager) + .registerOperation( + "smtk.bridge.multiscale.import_from_deform.import_from_deform"); + smtk::operation::ImporterGroup(operationManager) .registerOperation(); diff --git a/smtk/bridge/polygon/Registrar.cxx b/smtk/bridge/polygon/Registrar.cxx index 43f141b68a2877352dc2fe19c7a98b74dbc09ad6..2786946b05d31c73931eaeb8da4d158cef7577a0 100644 --- a/smtk/bridge/polygon/Registrar.cxx +++ b/smtk/bridge/polygon/Registrar.cxx @@ -32,6 +32,7 @@ #include "smtk/bridge/polygon/Resource.h" +#include "smtk/operation/groups/CreatorGroup.h" #include "smtk/operation/groups/ImporterGroup.h" #include "smtk/operation/groups/ReaderGroup.h" #include "smtk/operation/groups/WriterGroup.h" @@ -61,6 +62,9 @@ void Registrar::registerTo(const smtk::operation::Manager::Ptr& operationManager // Register operations operationManager->registerOperations(); + smtk::operation::CreatorGroup(operationManager) + .registerOperation(); + smtk::operation::ImporterGroup(operationManager) .registerOperation(); diff --git a/smtk/extension/paraview/appcomponents/CMakeLists.txt b/smtk/extension/paraview/appcomponents/CMakeLists.txt index ab1dd373a915ae57cde69946c6fa68bc365a66fd..2a48991c8965025b744e0b48852c1f109a7b289a 100644 --- a/smtk/extension/paraview/appcomponents/CMakeLists.txt +++ b/smtk/extension/paraview/appcomponents/CMakeLists.txt @@ -29,8 +29,9 @@ set(PQComponentsSrcs pqSMTKExportSimulationBehavior.cxx pqSMTKImportOperationBehavior.cxx pqSMTKModelRepresentation.cxx - pqSMTKSaveResourceBehavior.cxx + pqSMTKNewResourceBehavior.cxx pqSMTKOperationPanel.cxx + pqSMTKSaveResourceBehavior.cxx pqSMTKSelectionFilterBehavior.cxx pqSMTKResource.cxx pqSMTKWrapper.cxx @@ -46,8 +47,9 @@ set(PQComponentsHeaders pqSMTKExportSimulationBehavior.h pqSMTKImportOperationBehavior.h pqSMTKModelRepresentation.h - pqSMTKSaveResourceBehavior.h + pqSMTKNewResourceBehavior.h pqSMTKOperationPanel.h + pqSMTKSaveResourceBehavior.h pqSMTKSelectionFilterBehavior.h pqSMTKResource.h pqSMTKWrapper.h @@ -240,6 +242,10 @@ add_pqproxy_custom(proxyIfaces proxyIfaceSrcs XML_GROUP sources XML_NAME SMTKModelReader + TYPE pqSMTKResource + XML_GROUP sources + XML_NAME SMTKModelCreator + TYPE pqSMTKResource XML_GROUP sources XML_NAME_REGEX SMTKModelImporter* diff --git a/smtk/extension/paraview/appcomponents/pqSMTKAppComponentsAutoStart.cxx b/smtk/extension/paraview/appcomponents/pqSMTKAppComponentsAutoStart.cxx index d832ad26617b56da21a9b8c2bf31f7cf5ef30264..f6c8fbd500c27f052ab42350d27d0436d5a68acc 100644 --- a/smtk/extension/paraview/appcomponents/pqSMTKAppComponentsAutoStart.cxx +++ b/smtk/extension/paraview/appcomponents/pqSMTKAppComponentsAutoStart.cxx @@ -15,6 +15,7 @@ #include "smtk/extension/paraview/appcomponents/pqSMTKBehavior.h" #include "smtk/extension/paraview/appcomponents/pqSMTKExportSimulationBehavior.h" #include "smtk/extension/paraview/appcomponents/pqSMTKImportOperationBehavior.h" +#include "smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.h" #include "smtk/extension/paraview/appcomponents/pqSMTKSaveResourceBehavior.h" //#include "smtk/extension/paraview/appcomponents/pqSMTKSelectionFilterBehavior.h" #include "smtk/extension/paraview/server/vtkSMSMTKWrapperProxy.h" @@ -39,7 +40,15 @@ void pqSMTKAppComponentsAutoStart::startup() auto rsrcMgr = pqSMTKBehavior::instance(this); auto rsrcImportOpMgr = pqSMTKImportOperationBehavior::instance(this); auto rsrcExportSimMgr = pqSMTKExportSimulationBehavior::instance(this); + + // The "New Resource" menu item keys off of the "Save Resource" menu item, + // so the order of initialization for the following two global statics is + // important! + // + // TODO: There must be a better way to do this. auto rsrcSaveMgr = pqSMTKSaveResourceBehavior::instance(this); + auto rsrcNewMgr = pqSMTKNewResourceBehavior::instance(this); + auto pqCore = pqApplicationCore::instance(); if (pqCore) { @@ -47,6 +56,7 @@ void pqSMTKAppComponentsAutoStart::startup() pqCore->registerManager("smtk import operation", rsrcImportOpMgr); pqCore->registerManager("smtk export simulation", rsrcExportSimMgr); pqCore->registerManager("smtk save resource", rsrcSaveMgr); + pqCore->registerManager("smtk new resource", rsrcSaveMgr); } (void)rsrcMgr; } @@ -60,5 +70,6 @@ void pqSMTKAppComponentsAutoStart::shutdown() pqCore->unRegisterManager("smtk import operation"); pqCore->unRegisterManager("smtk export simulation"); pqCore->unRegisterManager("smtk save resource"); + pqCore->unRegisterManager("smtk new resource"); } } diff --git a/smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.cxx b/smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.cxx new file mode 100644 index 0000000000000000000000000000000000000000..42f887379d4d9f53802ebbde721e151d35f6eb8e --- /dev/null +++ b/smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.cxx @@ -0,0 +1,284 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= +#include "smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.h" + +// Client side +#include "pqActiveObjects.h" +#include "pqApplicationCore.h" +#include "pqCoreUtilities.h" +#include "pqFileDialog.h" +#include "pqObjectBuilder.h" +#include "pqServer.h" +#include "vtkSMPropertyHelper.h" +#include "vtkSMProxy.h" + +#include "smtk/attribute/Attribute.h" +#include "smtk/attribute/FileItem.h" +#include "smtk/attribute/IntItem.h" +#include "smtk/attribute/StringItem.h" +#include "smtk/attribute/json/jsonResource.h" +#include "smtk/extension/paraview/appcomponents/pqSMTKBehavior.h" +#include "smtk/extension/paraview/appcomponents/pqSMTKOperationPanel.h" +#include "smtk/extension/paraview/appcomponents/pqSMTKWrapper.h" +#include "smtk/extension/qt/qtOperationView.h" +#include "smtk/extension/qt/qtUIManager.h" +#include "smtk/operation/Manager.h" +#include "smtk/operation/groups/CreatorGroup.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nlohmann/json.hpp" + +using json = nlohmann::json; + +pqNewResourceReaction::pqNewResourceReaction( + const std::string& operationName, QAction* parentObject) + : Superclass(parentObject) + , m_operationName(operationName) +{ +} + +void pqNewResourceReaction::newResource() +{ + // Access the active server + pqServer* server = pqActiveObjects::instance().activeServer(); + pqSMTKWrapper* wrapper = pqSMTKBehavior::instance()->resourceManagerForServer(server); + + // Access the unique name associated with the operation. + auto createOp = wrapper->smtkOperationManager()->create(m_operationName); + + // Construct a modal dialog for the operation. + QSharedPointer createDialog = QSharedPointer(new QDialog()); + createDialog->setObjectName("CreateResourceDialog"); + createDialog->setWindowTitle("Create Resource Dialog"); + createDialog->setLayout(new QVBoxLayout(createDialog.data())); + + // Create a new UI for the dialog. + QSharedPointer uiManager = + QSharedPointer(new smtk::extension::qtUIManager(createOp)); + + // Create an operation view for the operation. + smtk::view::ViewPtr view = uiManager->findOrCreateOperationView(); + smtk::extension::qtOperationView* opView = dynamic_cast( + uiManager->setSMTKView(view, createDialog.data())); + + // Remove all connections from the operation view's apply button. We are going + // to intercept the client-side operation parameters and execute them on the + // server. + opView->applyButton()->disconnect(); + + // Retrieve the operation specification and close the modal dialog when the + // apply button is clicked. + std::string typeName; + std::string specification; + QObject::connect(opView->applyButton(), &QPushButton::clicked, [&]() { + typeName = opView->operation()->typeName(); + json j; + smtk::attribute::to_json(j, opView->operation()->parameters()->attributeResource()); + specification = j.dump(); + createDialog->done(QDialog::Accepted); + }); + + // Launch the modal dialog and wait for the operation to succeed. + createDialog->exec(); + + auto pqCore = pqApplicationCore::instance(); + auto builder = pqCore->getObjectBuilder(); + + pqPipelineSource* src = builder->createSource("sources", "SMTKModelCreator", server); + vtkSMPropertyHelper(src->getProxy(), "TypeName").Set(typeName.c_str()); + vtkSMPropertyHelper(src->getProxy(), "Specification").Set(specification.c_str()); + src->getProxy()->UpdateVTKObjects(); + src->updatePipeline(); +} + +namespace +{ +QAction* findSaveResourceAction(QMenu* menu) +{ + foreach (QAction* action, menu->actions()) + { + if (action->text().contains("save resource", Qt::CaseInsensitive)) + { + return action; + } + } + return NULL; +} + +QAction* findExitAction(QMenu* menu) +{ + foreach (QAction* action, menu->actions()) + { + QString name = action->text().toLower(); + name.remove('&'); + if (name == "exit" || name == "quit") + { + return action; + } + } + return NULL; +} + +QAction* findHelpMenuAction(QMenuBar* menubar) +{ + QList menuBarActions = menubar->actions(); + foreach (QAction* existingMenuAction, menuBarActions) + { + QString menuName = existingMenuAction->text().toLower(); + menuName.remove('&'); + if (menuName == "help") + { + return existingMenuAction; + } + } + return NULL; +} +} + +static pqSMTKNewResourceBehavior* g_instance = nullptr; + +pqSMTKNewResourceBehavior::pqSMTKNewResourceBehavior(QObject* parent) + : Superclass(parent) + , m_newMenu(nullptr) +{ + auto pqCore = pqApplicationCore::instance(); + if (pqCore) + { + QMenu* fileMenu = this->fileMenu(); + + // We want to defer the creation of the menu actions as much as possible + // so the File menu will already be populated by the time we add our + // custom actions. If our actions are inserted first, there is no way to + // control where in the list of actions they go, and they end up awkwardly + // sitting at the top of the menu. By using a single-shot connection to + // load our actions, we ensure that extant Save methods are in place; we + // key off of their location to make the menu look better. + QMetaObject::Connection* connection = new QMetaObject::Connection; + *connection = QObject::connect(fileMenu, &QMenu::aboutToShow, [this, connection, fileMenu]() { + QAction* saveAction = findSaveResourceAction(fileMenu); + + this->setNewMenu(qobject_cast( + fileMenu->insertMenu(saveAction, new QMenu("New Resource"))->parent())); + this->updateNewMenu(); + + // Remove this connection. + QObject::disconnect(*connection); + delete connection; + }); + + pqActiveObjects* activeObjects = &pqActiveObjects::instance(); + QObject::connect(activeObjects, SIGNAL(serverChanged(pqServer*)), this, SLOT(updateNewMenu())); + } +} + +QMenu* pqSMTKNewResourceBehavior::fileMenu() +{ + QMainWindow* mainWindow = qobject_cast(pqCoreUtilities::mainWidget()); + + QList menuBarActions = mainWindow->menuBar()->actions(); + + QMenu* menu = NULL; + foreach (QAction* existingMenuAction, menuBarActions) + { + QString menuName = existingMenuAction->text(); + menuName.remove('&'); + if (menuName == "File") + { + return existingMenuAction->menu(); + } + } + + if (menu == nullptr) + { + // Create new menu. + menu = new QMenu("File", mainWindow); + menu->setObjectName("File"); + } + + return menu; +} + +void pqSMTKNewResourceBehavior::setNewMenu(QMenu* menu) +{ + this->m_newMenu = menu; +} + +void pqSMTKNewResourceBehavior::updateNewMenu() +{ + if (m_newMenu != nullptr) + { + m_newMenu->clear(); + + bool visible = false; + + pqServer* server = pqActiveObjects::instance().activeServer(); + pqSMTKWrapper* wrapper = pqSMTKBehavior::instance()->resourceManagerForServer(server); + if (wrapper != nullptr) + { + auto creatorGroup = smtk::operation::CreatorGroup(wrapper->smtkOperationManager()); + auto operationNames = creatorGroup.operationNames(); + visible = !operationNames.empty(); + + for (auto& operationName : operationNames) + { + // We start with the unique operation name. We use it as a key to + // acquire the unique resource name. We then split on the c++ + // double-colon separator and select the penultimate token as the + // short-form for the resource name. Finally, we capitalize the name. + // This is hack-ish, but it should serve as a stopgap until a + // standardized convention for assigning human-readable labels to + // resources is in place. + QString label = QString::fromStdString(creatorGroup.resourceForOperation(operationName)); + QStringList splitLabel = label.split("::"); + label = *(++splitLabel.rbegin()); + label[0] = label[0].toUpper(); + QAction* newResourceAction = new QAction(label, m_newMenu); + m_newMenu->addAction(newResourceAction); + + new pqNewResourceReaction(operationName, newResourceAction); + } + } + m_newMenu->menuAction()->setVisible(visible); + } +} + +pqSMTKNewResourceBehavior* pqSMTKNewResourceBehavior::instance(QObject* parent) +{ + if (!g_instance) + { + g_instance = new pqSMTKNewResourceBehavior(parent); + } + + if (g_instance->parent() == nullptr && parent) + { + g_instance->setParent(parent); + } + + return g_instance; +} + +pqSMTKNewResourceBehavior::~pqSMTKNewResourceBehavior() +{ + if (g_instance == this) + { + g_instance = nullptr; + } + + QObject::disconnect(this); +} diff --git a/smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.h b/smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.h new file mode 100644 index 0000000000000000000000000000000000000000..90179fff7674cade07fc9a2aa048e4e1040c9c6d --- /dev/null +++ b/smtk/extension/paraview/appcomponents/pqSMTKNewResourceBehavior.h @@ -0,0 +1,83 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= +#ifndef smtk_extension_paraview_appcomponents_pqSMTKNewResourceBehavior_h +#define smtk_extension_paraview_appcomponents_pqSMTKNewResourceBehavior_h + +#include "smtk/extension/paraview/appcomponents/Exports.h" + +#include "smtk/PublicPointerDefs.h" + +#include "pqReaction.h" + +#include + +class pqPipelineSource; +class pqServer; +class vtkSMReaderFactory; + +class QMenu; + +/// A reaction for creating a new SMTK Resource. +class pqNewResourceReaction : public pqReaction +{ + Q_OBJECT + typedef pqReaction Superclass; + +public: + /** + * Constructor. Parent cannot be NULL. + */ + pqNewResourceReaction(const std::string& operationName, QAction* parent); + + void newResource(); + +protected: + /** + * Called when the action is triggered. + */ + void onTriggered() override { this->newResource(); } + +private: + Q_DISABLE_COPY(pqNewResourceReaction) + + std::string m_operationName; +}; + +/// Create a menu item under "File" for creating a new SMTK resource. The +/// behavior constructs a client-side operation for the purposes of populating a +/// modal dialog with the create operation's parameters. These parameters are +/// then serialized to a json string, and a server-side operation is created and +/// executed using the deserialized parameters. +class SMTKPQCOMPONENTSEXT_EXPORT pqSMTKNewResourceBehavior : public QObject +{ + Q_OBJECT + using Superclass = QObject; + +public: + static pqSMTKNewResourceBehavior* instance(QObject* parent = nullptr); + ~pqSMTKNewResourceBehavior() override; + + QMenu* fileMenu(); + + void setNewMenu(QMenu*); + +public slots: + void updateNewMenu(); + +protected: + pqSMTKNewResourceBehavior(QObject* parent = nullptr); + +private: + Q_DISABLE_COPY(pqSMTKNewResourceBehavior); + + QMenu* m_newMenu; +}; + +#endif // smtk_extension_paraview_appcomponents_pqSMTKNewResourceBehavior_h diff --git a/smtk/extension/paraview/appcomponents/pqSMTKResource.cxx b/smtk/extension/paraview/appcomponents/pqSMTKResource.cxx index 17cd0a6786fb008d71eed671ee74f1ca6b65edce..3c2b03c28fbc0e90e6c8567f496eaca87268453a 100644 --- a/smtk/extension/paraview/appcomponents/pqSMTKResource.cxx +++ b/smtk/extension/paraview/appcomponents/pqSMTKResource.cxx @@ -14,7 +14,7 @@ #include "smtk/extension/paraview/server/vtkSMSMTKWrapperProxy.h" #include "smtk/extension/paraview/server/vtkSMTKAttributeReader.h" -#include "smtk/extension/paraview/server/vtkSMTKModelReader.h" +#include "smtk/extension/paraview/server/vtkSMTKResourceSource.h" #include "smtk/attribute/Resource.h" @@ -73,7 +73,7 @@ smtk::resource::ResourcePtr pqSMTKResource::getResource() const smtk::resource::ResourcePtr rsrc; auto pxy = this->getProxy()->GetClientSideObject(); // std::cout << "get resource from " << pxy->GetClassName() << "\n"; - auto smtkRsrcRdr = vtkSMTKResourceReader::SafeDownCast(pxy); + auto smtkRsrcRdr = vtkSMTKResourceSource::SafeDownCast(pxy); rsrc = smtkRsrcRdr ? smtkRsrcRdr->GetResource() : nullptr; if (rsrc) { diff --git a/smtk/extension/paraview/appcomponents/pqSMTKWrapper.cxx b/smtk/extension/paraview/appcomponents/pqSMTKWrapper.cxx index d0e2f48bc3ea1cf96591d3b077b6b8bfdc406930..143c25c8032a2268860e430ad92bdebed6d77cb9 100644 --- a/smtk/extension/paraview/appcomponents/pqSMTKWrapper.cxx +++ b/smtk/extension/paraview/appcomponents/pqSMTKWrapper.cxx @@ -13,7 +13,7 @@ #include "smtk/extension/paraview/appcomponents/pqSMTKBehavior.h" #include "smtk/extension/paraview/appcomponents/pqSMTKResource.h" #include "smtk/extension/paraview/server/vtkSMSMTKWrapperProxy.h" -#include "smtk/extension/paraview/server/vtkSMTKResourceReader.h" +#include "smtk/extension/paraview/server/vtkSMTKResourceSource.h" #include "smtk/extension/paraview/server/vtkSMTKWrapper.h" #include "smtk/extension/vtk/source/vtkModelMultiBlockSource.h" // TODO: remove need for me @@ -239,7 +239,7 @@ void pqSMTKWrapper::paraviewSelectionChanged(pqOutputPort* port) { auto dataInput = port->getSourceProxy(); auto dataThing = dataInput->GetClientSideObject(); - auto smtkThing = dynamic_cast(dataThing); + auto smtkThing = dynamic_cast(dataThing); auto mbdsThing = smtkThing ? smtkThing->GetOutput() : nullptr; auto selnInput = port->getSelectionInput(); vtkPVSelectionSource* selnThing = diff --git a/smtk/extension/paraview/server/CMakeLists.txt b/smtk/extension/paraview/server/CMakeLists.txt index 2a9a9db8d07bc94fee997261f1d873f136e8c044..c9c863be36825cd35d549862f01dc6afab78661a 100644 --- a/smtk/extension/paraview/server/CMakeLists.txt +++ b/smtk/extension/paraview/server/CMakeLists.txt @@ -18,8 +18,9 @@ set(serverWrappedSrcs vtkPVModelSources.cxx vtkSMTKAttributeReader.cxx vtkSMTKModelImporter.cxx + vtkSMTKModelCreator.cxx vtkSMTKModelReader.cxx - vtkSMTKResourceReader.cxx + vtkSMTKResourceSource.cxx vtkSMSMTKWrapperProxy.cxx vtkSMTKWrapper.cxx vtkSMSMTKModelRepresentationProxy.cxx @@ -30,8 +31,9 @@ set(serverWrappedHdrs vtkPVModelSources.h vtkSMTKAttributeReader.h vtkSMTKModelImporter.h + vtkSMTKModelCreator.h vtkSMTKModelReader.h - vtkSMTKResourceReader.h + vtkSMTKResourceSource.h vtkSMSMTKWrapperProxy.h vtkSMTKWrapper.h vtkSMSMTKModelRepresentationProxy.h diff --git a/smtk/extension/paraview/server/smconfig.xml b/smtk/extension/paraview/server/smconfig.xml index 06d8a8dccf630ee84d24a73b40f16e11a5339c99..4381d4836489348b0247472d3cfd66107e7a931d 100644 --- a/smtk/extension/paraview/server/smconfig.xml +++ b/smtk/extension/paraview/server/smconfig.xml @@ -106,6 +106,33 @@ + + + + + + + + + + + + + + + FileName = nullptr; this->IncludePathToFile = true; - //std::cout << "Create reader " << this << "\n"; this->Defs = vtkSmartPointer::New(); this->SetNumberOfOutputPorts(1); @@ -47,21 +47,20 @@ vtkSMTKAttributeReader::vtkSMTKAttributeReader() vtkSMTKAttributeReader::~vtkSMTKAttributeReader() { - //std::cout << "Delete reader " << this << "\n"; this->SetFileName(nullptr); - this->SetWrapper(nullptr); } void vtkSMTKAttributeReader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); + os << indent << "FileName: " << this->FileName << "\n"; os << indent << "AttributeResource: " << this->AttributeResource << "\n"; os << indent << "IncludePathToFile: " << this->IncludePathToFile << "\n"; } smtk::resource::ResourcePtr vtkSMTKAttributeReader::GetResource() const { - return std::dynamic_pointer_cast(this->AttributeResource); + return std::dynamic_pointer_cast(this->GetSMTKResource()); } smtk::attribute::ResourcePtr vtkSMTKAttributeReader::GetSMTKResource() const @@ -75,11 +74,6 @@ int vtkSMTKAttributeReader::RequestData(vtkInformation* vtkNotUsed(request), { vtkMultiBlockDataSet* entitySource = vtkMultiBlockDataSet::GetData(outInfo, 0); - /* - std::cout - << " Reader " << this - << " has file " << (this->FileName && this->FileName[0] ? "Y" : "N") << "\n"; - */ if (!this->FileName || !this->FileName[0]) { // No filename is not really an error... we should just have an empty output. diff --git a/smtk/extension/paraview/server/vtkSMTKAttributeReader.h b/smtk/extension/paraview/server/vtkSMTKAttributeReader.h index 409ebce896c888db53b2d7b7fde633c8b2e1baf5..832009c7eef8c535bd0a773d4a0ce2a6d70d4ca5 100644 --- a/smtk/extension/paraview/server/vtkSMTKAttributeReader.h +++ b/smtk/extension/paraview/server/vtkSMTKAttributeReader.h @@ -10,29 +10,33 @@ #ifndef smtk_extension_paraview_server_vtkSMTKAttributeReader_h #define smtk_extension_paraview_server_vtkSMTKAttributeReader_h -#include "smtk/extension/paraview/server/vtkSMTKResourceReader.h" +#include "smtk/extension/paraview/server/vtkSMTKResourceSource.h" #include "smtk/PublicPointerDefs.h" +#include "vtkMultiBlockDataSetAlgorithm.h" #include "vtkNew.h" #include "vtkSmartPointer.h" class vtkSMTKWrapper; - class vtkTable; /**\brief Use SMTK to provide a ParaView-friendly attribute source. */ -class SMTKPVSERVEREXT_EXPORT vtkSMTKAttributeReader : public vtkSMTKResourceReader +class SMTKPVSERVEREXT_EXPORT vtkSMTKAttributeReader : public vtkSMTKResourceSource { public: - vtkTypeMacro(vtkSMTKAttributeReader, vtkSMTKResourceReader); + vtkTypeMacro(vtkSMTKAttributeReader, vtkSMTKResourceSource); void PrintSelf(ostream& os, vtkIndent indent) override; static vtkSMTKAttributeReader* New(); + /// Set/get the URL of the SMTK attribute resource. + vtkGetStringMacro(FileName); + vtkSetStringMacro(FileName); + /// Set/get whether to include the parent directory of \a FileName in the include path. - vtkGetMacro(IncludePathToFile, bool); vtkSetMacro(IncludePathToFile, bool); + vtkGetMacro(IncludePathToFile, bool); /// Return the SMTK resource that holds data read from \a FileName. smtk::resource::ResourcePtr GetResource() const override; @@ -49,6 +53,7 @@ protected: bool LoadFile(); + char* FileName; bool IncludePathToFile; smtk::attribute::ResourcePtr AttributeResource; vtkSmartPointer Defs; diff --git a/smtk/extension/paraview/server/vtkSMTKModelCreator.cxx b/smtk/extension/paraview/server/vtkSMTKModelCreator.cxx new file mode 100644 index 0000000000000000000000000000000000000000..03710f6d022342af598aea71075b41e01f10899c --- /dev/null +++ b/smtk/extension/paraview/server/vtkSMTKModelCreator.cxx @@ -0,0 +1,222 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= +#include "smtk/extension/paraview/server/vtkSMTKModelCreator.h" + +#include "smtk/extension/vtk/source/vtkMeshMultiBlockSource.h" +#include "smtk/extension/vtk/source/vtkModelAuxiliaryGeometry.h" +#include "smtk/extension/vtk/source/vtkModelMultiBlockSource.h" + +#include "smtk/extension/paraview/server/vtkSMTKWrapper.h" + +#include "smtk/attribute/Attribute.h" +#include "smtk/attribute/FileItem.h" +#include "smtk/attribute/IntItem.h" +#include "smtk/attribute/ResourceItem.h" +#include "smtk/attribute/StringItem.h" + +#include "smtk/model/EntityRef.h" +#include "smtk/model/Model.h" +#include "smtk/model/Resource.h" +#include "smtk/model/SessionRef.h" + +#include "smtk/operation/Manager.h" +#include "smtk/operation/operators/ReadResource.h" + +#include "smtk/resource/Manager.h" + +#include "smtk/attribute/ComponentItem.h" +#include "smtk/attribute/json/jsonResource.h" + +#include "vtkCompositeDataIterator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkMultiBlockDataSet.h" +#include "vtkObjectFactory.h" +#include "vtkPolyData.h" + +#include "nlohmann/json.hpp" + +using json = nlohmann::json; + +vtkStandardNewMacro(vtkSMTKModelCreator); + +vtkSMTKModelCreator::vtkSMTKModelCreator() +{ + this->TypeName = nullptr; + this->Specification = nullptr; + this->SetNumberOfOutputPorts(vtkModelMultiBlockSource::NUMBER_OF_OUTPUT_PORTS); +} + +vtkSMTKModelCreator::~vtkSMTKModelCreator() +{ + this->SetTypeName(nullptr); + this->SetSpecification(nullptr); +} + +void vtkSMTKModelCreator::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); + os << indent << "TypeName: " << this->TypeName << "\n"; + os << indent << "Specification: " << this->Specification << "\n"; + os << indent << "ModelSource: " << this->ModelSource << "\n"; +} + +smtk::resource::ResourcePtr vtkSMTKModelCreator::GetResource() const +{ + return std::dynamic_pointer_cast(this->GetSMTKResource()); +} + +smtk::model::ResourcePtr vtkSMTKModelCreator::GetSMTKResource() const +{ + return this->ModelSource->GetModelResource(); +} + +/// Generate polydata from an smtk::model with tessellation information. +int vtkSMTKModelCreator::RequestData(vtkInformation* vtkNotUsed(request), + vtkInformationVector** vtkNotUsed(inInfo), vtkInformationVector* outInfo) +{ + vtkMultiBlockDataSet* entitySource = vtkMultiBlockDataSet::GetData( + outInfo, static_cast(vtkModelMultiBlockSource::MODEL_ENTITY_PORT)); + + vtkMultiBlockDataSet* instanceSource = vtkMultiBlockDataSet::GetData( + outInfo, static_cast(vtkModelMultiBlockSource::PROTOTYPE_PORT)); + + if (!entitySource || !instanceSource) + { + vtkErrorMacro("No output dataset"); + return 0; + } + + vtkMultiBlockDataSet* instancePlacement = vtkMultiBlockDataSet::GetData( + outInfo, static_cast(vtkModelMultiBlockSource::INSTANCE_PORT)); + + if (!instancePlacement) + { + vtkErrorMacro("No output instance-placement dataset"); + return 0; + } + + if (!this->TypeName) + { + vtkErrorMacro("No type name specified."); + return 1; + } + + if (!this->Specification) + { + vtkErrorMacro("No specification specified."); + return 1; + } + + if (this->GetMTime() > this->ModelSource->GetMTime()) + { + if (this->CreateModel()) + { + this->ModelSource->Update(); + } + } + + entitySource->ShallowCopy(this->ModelSource->GetOutputDataObject( + static_cast(vtkModelMultiBlockSource::MODEL_ENTITY_PORT))); + instancePlacement->ShallowCopy(this->ModelSource->GetOutputDataObject( + static_cast(vtkModelMultiBlockSource::INSTANCE_PORT))); + instanceSource->ShallowCopy(this->ModelSource->GetOutputDataObject( + static_cast(vtkModelMultiBlockSource::PROTOTYPE_PORT))); + return 1; +} + +bool vtkSMTKModelCreator::CreateModel() +{ + if (!this->TypeName || !this->Specification) + { + return false; + } + + smtk::resource::Manager::Ptr rsrcMgr; + if (this->Wrapper != nullptr) + { + rsrcMgr = this->Wrapper->GetResourceManager(); + } + + smtk::operation::Manager::Ptr operMgr; + if (this->Wrapper != nullptr) + { + operMgr = this->Wrapper->GetOperationManager(); + } + + if (!operMgr) + { + return false; + } + + auto oper = operMgr->create(std::string(this->TypeName)); + if (!oper) + { + return false; + } + + json j; + + try + { + j = json::parse(this->Specification); + } + catch (std::exception&) + { + return false; + } + + auto specification = oper->specification(); + smtk::attribute::from_json(j, specification); + + auto result = oper->operate(); + if (result->findInt("outcome")->value() != + static_cast(smtk::operation::Operation::Outcome::SUCCEEDED)) + { + return false; + } + + auto rsrc = result->findResource("resource")->value(0); + auto modelRsrc = std::dynamic_pointer_cast(rsrc); + if (!modelRsrc) + { + return false; + } + + // If we have a resouce manager... + if (rsrcMgr) + { + // ... remove the previous resource if we had one. + auto oldRsrc = this->ModelSource->GetModelResource(); + if (oldRsrc) + { + rsrcMgr->remove(oldRsrc); + } + // Add the resource we just read. + rsrcMgr->add(rsrc); + } + + // Tell our multiblock source to generate VTK polydata for model/mesh entities. + this->ModelSource->SetModelResource(modelRsrc); + + // Also, find the first model and tell the multiblock source to render only it. + // TODO: Either we need a separate representation for each model (which is + // IMNSHO a bad idea) or we need to change the multiblock source to work + // without a model. It currently generates tessellations but not all the + // metadata required for color-by modes. + auto models = + modelRsrc->entitiesMatchingFlagsAs(smtk::model::MODEL_ENTITY, false); + if (!models.empty()) + { + this->ModelSource->SetModelEntityID(models.begin()->entity().toString().c_str()); + } + + return true; +} diff --git a/smtk/extension/paraview/server/vtkSMTKModelCreator.h b/smtk/extension/paraview/server/vtkSMTKModelCreator.h new file mode 100644 index 0000000000000000000000000000000000000000..b8f8eaccd08a3831dc41d704525919b40fc7c4bd --- /dev/null +++ b/smtk/extension/paraview/server/vtkSMTKModelCreator.h @@ -0,0 +1,64 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= +#ifndef smtk_extension_paraview_server_vtkSMTKModelCreator_h +#define smtk_extension_paraview_server_vtkSMTKModelCreator_h + +#include "smtk/extension/paraview/server/Exports.h" + +#include "vtkSMTKResourceSource.h" + +class vtkModelMultiBlockSource; +class vtkSMTKWrapper; + +/**\brief A class for SMTK-based model sources. + */ +class SMTKPVSERVEREXT_EXPORT vtkSMTKModelCreator : public vtkSMTKResourceSource +{ +public: + vtkTypeMacro(vtkSMTKModelCreator, vtkSMTKResourceSource); + void PrintSelf(ostream& os, vtkIndent indent) override; + static vtkSMTKModelCreator* New(); + + /// Set/get the create operation type name. + vtkGetStringMacro(TypeName); + vtkSetStringMacro(TypeName); + + /// Set/get the json-formatted input specification for the create operation. + vtkGetStringMacro(Specification); + vtkSetStringMacro(Specification); + + /// Return the VTK algorithm used to read the SMTK file. + vtkModelMultiBlockSource* GetModelSource() { return this->ModelSource.GetPointer(); } + + /// Return the SMTK resource that holds data read from \a FileName. + smtk::resource::ResourcePtr GetResource() const override; + + /// Return the SMTK model resource that holds data read from \a FileName. + smtk::model::ResourcePtr GetSMTKResource() const; + +protected: + vtkSMTKModelCreator(); + ~vtkSMTKModelCreator() override; + + int RequestData( + vtkInformation* request, vtkInformationVector** inInfo, vtkInformationVector* outInfo) override; + + bool CreateModel(); + + char* TypeName; + char* Specification; + vtkNew ModelSource; + +private: + vtkSMTKModelCreator(const vtkSMTKModelCreator&) = delete; + void operator=(const vtkSMTKModelCreator&) = delete; +}; + +#endif diff --git a/smtk/extension/paraview/server/vtkSMTKModelImporter.cxx b/smtk/extension/paraview/server/vtkSMTKModelImporter.cxx index 50e4e73a96134d9362c8d66ac6d557cc2eff5b30..5d2ae790e628be99fa4c00109783d9f3c6b77145 100644 --- a/smtk/extension/paraview/server/vtkSMTKModelImporter.cxx +++ b/smtk/extension/paraview/server/vtkSMTKModelImporter.cxx @@ -48,6 +48,7 @@ vtkStandardNewMacro(vtkSMTKModelImporter); vtkSMTKModelImporter::vtkSMTKModelImporter() { + this->FileName = nullptr; this->ResourceName = nullptr; this->SetNumberOfOutputPorts(vtkModelMultiBlockSource::NUMBER_OF_OUTPUT_PORTS); @@ -58,12 +59,14 @@ vtkSMTKModelImporter::vtkSMTKModelImporter() vtkSMTKModelImporter::~vtkSMTKModelImporter() { + this->SetFileName(nullptr); this->SetResourceName(nullptr); } void vtkSMTKModelImporter::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); + os << indent << "FileName: " << this->FileName << "\n"; os << indent << "ModelSource: " << this->ModelSource << "\n"; } diff --git a/smtk/extension/paraview/server/vtkSMTKModelImporter.h b/smtk/extension/paraview/server/vtkSMTKModelImporter.h index 03520aac7adf6ec5d97b10cecbc906b874470bab..7e4c654ed1ae55c00337de06f5709155a7f4320f 100644 --- a/smtk/extension/paraview/server/vtkSMTKModelImporter.h +++ b/smtk/extension/paraview/server/vtkSMTKModelImporter.h @@ -10,7 +10,7 @@ #ifndef smtk_extension_paraview_server_vtkSMTKModelImporter_h #define smtk_extension_paraview_server_vtkSMTKModelImporter_h -#include "smtk/extension/paraview/server/vtkSMTKResourceReader.h" +#include "smtk/extension/paraview/server/vtkSMTKResourceSource.h" #include "smtk/PublicPointerDefs.h" @@ -29,13 +29,17 @@ class vtkSMTKWrapper; * manager are used to import the file (or perhaps in the future to create a * new resource). Otherwise SMTK's default environment is used. */ -class SMTKPVSERVEREXT_EXPORT vtkSMTKModelImporter : public vtkSMTKResourceReader +class SMTKPVSERVEREXT_EXPORT vtkSMTKModelImporter : public vtkSMTKResourceSource { public: - vtkTypeMacro(vtkSMTKModelImporter, vtkSMTKResourceReader); + vtkTypeMacro(vtkSMTKModelImporter, vtkSMTKResourceSource); void PrintSelf(ostream& os, vtkIndent indent) override; static vtkSMTKModelImporter* New(); + /// Set/get the URL of the SMTK model resource. + vtkGetStringMacro(FileName); + vtkSetStringMacro(FileName); + /// Set/get the unique name of the SMTK resource. vtkGetStringMacro(ResourceName); vtkSetStringMacro(ResourceName); @@ -60,6 +64,7 @@ protected: vtkNew ModelSource; + char* FileName; char* ResourceName; private: diff --git a/smtk/extension/paraview/server/vtkSMTKModelReader.cxx b/smtk/extension/paraview/server/vtkSMTKModelReader.cxx index 89cbd1c691deb0b6cef8ff4f323547f335765d01..49fee62595462168d72a96b67b22154398794d67 100644 --- a/smtk/extension/paraview/server/vtkSMTKModelReader.cxx +++ b/smtk/extension/paraview/server/vtkSMTKModelReader.cxx @@ -46,7 +46,7 @@ vtkStandardNewMacro(vtkSMTKModelReader); vtkSMTKModelReader::vtkSMTKModelReader() { - //std::cout << "Create reader " << this << "\n"; + this->FileName = nullptr; this->SetNumberOfOutputPorts(vtkModelMultiBlockSource::NUMBER_OF_OUTPUT_PORTS); // Ensure this object's MTime > this->ModelSource's MTime so first RequestData() call @@ -56,11 +56,13 @@ vtkSMTKModelReader::vtkSMTKModelReader() vtkSMTKModelReader::~vtkSMTKModelReader() { + this->SetFileName(nullptr); } void vtkSMTKModelReader::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); + os << indent << "FileName: " << this->FileName << "\n"; os << indent << "ModelSource: " << this->ModelSource << "\n"; } diff --git a/smtk/extension/paraview/server/vtkSMTKModelReader.h b/smtk/extension/paraview/server/vtkSMTKModelReader.h index 923691b3a01e23ca1e3a3956d3a94538a772bf51..78cb353532c4e3712352e1269a65edffd689c529 100644 --- a/smtk/extension/paraview/server/vtkSMTKModelReader.h +++ b/smtk/extension/paraview/server/vtkSMTKModelReader.h @@ -10,7 +10,7 @@ #ifndef smtk_extension_paraview_server_vtkSMTKModelReader_h #define smtk_extension_paraview_server_vtkSMTKModelReader_h -#include "smtk/extension/paraview/server/vtkSMTKResourceReader.h" +#include "smtk/extension/paraview/server/vtkSMTKResourceSource.h" #include "smtk/PublicPointerDefs.h" @@ -27,13 +27,17 @@ class vtkSMTKWrapper; * manager are used to load the file (or perhaps in the future to create a new resource). * Otherwise SMTK's default environment is used. */ -class SMTKPVSERVEREXT_EXPORT vtkSMTKModelReader : public vtkSMTKResourceReader +class SMTKPVSERVEREXT_EXPORT vtkSMTKModelReader : public vtkSMTKResourceSource { public: - vtkTypeMacro(vtkSMTKModelReader, vtkSMTKResourceReader); + vtkTypeMacro(vtkSMTKModelReader, vtkSMTKResourceSource); void PrintSelf(ostream& os, vtkIndent indent) override; static vtkSMTKModelReader* New(); + /// Set/get the URL of the SMTK model resource. + vtkGetStringMacro(FileName); + vtkSetStringMacro(FileName); + /// Return the VTK algorithm used to read the SMTK file. vtkModelMultiBlockSource* GetModelSource() { return this->ModelSource.GetPointer(); } @@ -52,6 +56,7 @@ protected: bool LoadFile(); + char* FileName; vtkNew ModelSource; private: diff --git a/smtk/extension/paraview/server/vtkSMTKResourceReader.cxx b/smtk/extension/paraview/server/vtkSMTKResourceSource.cxx similarity index 71% rename from smtk/extension/paraview/server/vtkSMTKResourceReader.cxx rename to smtk/extension/paraview/server/vtkSMTKResourceSource.cxx index 31eafeada495f7610822fb39ba2102aeb2c35f08..3bd1380cbc8b443f01eba26839a8c3e852d75759 100644 --- a/smtk/extension/paraview/server/vtkSMTKResourceReader.cxx +++ b/smtk/extension/paraview/server/vtkSMTKResourceSource.cxx @@ -7,7 +7,7 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //========================================================================= -#include "smtk/extension/paraview/server/vtkSMTKResourceReader.h" +#include "smtk/extension/paraview/server/vtkSMTKResourceSource.h" #include "smtk/extension/paraview/server/vtkSMTKWrapper.h" #include "smtk/resource/Manager.h" @@ -21,38 +21,35 @@ using namespace smtk; -vtkCxxSetObjectMacro(vtkSMTKResourceReader, Wrapper, vtkSMTKWrapper); +vtkCxxSetObjectMacro(vtkSMTKResourceSource, Wrapper, vtkSMTKWrapper); -vtkSMTKResourceReader::vtkSMTKResourceReader() +vtkSMTKResourceSource::vtkSMTKResourceSource() { - this->FileName = nullptr; this->Wrapper = nullptr; this->SetNumberOfInputPorts(0); } -vtkSMTKResourceReader::~vtkSMTKResourceReader() +vtkSMTKResourceSource::~vtkSMTKResourceSource() { if (this->Wrapper) { this->DropResource(); } this->SetWrapper(nullptr); - this->SetFileName(nullptr); } -void vtkSMTKResourceReader::PrintSelf(ostream& os, vtkIndent indent) +void vtkSMTKResourceSource::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); - os << indent << "FileName: " << this->FileName << "\n"; os << indent << "Wrapper: " << this->Wrapper << "\n"; } -smtk::resource::Resource::Ptr vtkSMTKResourceReader::GetResource() const +smtk::resource::Resource::Ptr vtkSMTKResourceSource::GetResource() const { return smtk::resource::Resource::Ptr(); } -void vtkSMTKResourceReader::DropResource() +void vtkSMTKResourceSource::DropResource() { auto rsrc = this->GetResource(); if (!rsrc) diff --git a/smtk/extension/paraview/server/vtkSMTKResourceReader.h b/smtk/extension/paraview/server/vtkSMTKResourceSource.h similarity index 59% rename from smtk/extension/paraview/server/vtkSMTKResourceReader.h rename to smtk/extension/paraview/server/vtkSMTKResourceSource.h index 963b55daa681ce9de93aa187b7a13ba738da5e88..90f434d8b9fa75964445e97c8add1c1eef8bc40c 100644 --- a/smtk/extension/paraview/server/vtkSMTKResourceReader.h +++ b/smtk/extension/paraview/server/vtkSMTKResourceSource.h @@ -7,8 +7,8 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //========================================================================= -#ifndef smtk_extension_paraview_server_vtkSMTKResourceReader_h -#define smtk_extension_paraview_server_vtkSMTKResourceReader_h +#ifndef smtk_extension_paraview_server_vtkSMTKResourceSource_h +#define smtk_extension_paraview_server_vtkSMTKResourceSource_h #include "smtk/extension/paraview/server/Exports.h" @@ -20,22 +20,14 @@ class vtkSMTKWrapper; -/**\brief A base class for SMTK-based readers exposed in ParaView. - * - * If the SMTK wrapper object is set, then the wrapper's resource and operation - * manager are used to load the file (or perhaps in the future to create a new resource). - * Otherwise SMTK's default environment is used. +/**\brief A base class for SMTK-based sources exposed in ParaView. */ -class SMTKPVSERVEREXT_EXPORT vtkSMTKResourceReader : public vtkMultiBlockDataSetAlgorithm +class SMTKPVSERVEREXT_EXPORT vtkSMTKResourceSource : public vtkMultiBlockDataSetAlgorithm { public: - vtkTypeMacro(vtkSMTKResourceReader, vtkMultiBlockDataSetAlgorithm); + vtkTypeMacro(vtkSMTKResourceSource, vtkMultiBlockDataSetAlgorithm); void PrintSelf(ostream& os, vtkIndent indent) override; - /// Set/get the URL of the SMTK model resource. - vtkGetStringMacro(FileName); - vtkSetStringMacro(FileName); - /// Return the SMTK resource that holds data read from \a FileName. virtual smtk::resource::ResourcePtr GetResource() const; @@ -47,15 +39,14 @@ public: virtual void DropResource(); protected: - vtkSMTKResourceReader(); - ~vtkSMTKResourceReader() override; + vtkSMTKResourceSource(); + ~vtkSMTKResourceSource() override; - char* FileName; vtkSMTKWrapper* Wrapper; private: - vtkSMTKResourceReader(const vtkSMTKResourceReader&) = delete; - void operator=(const vtkSMTKResourceReader&) = delete; + vtkSMTKResourceSource(const vtkSMTKResourceSource&) = delete; + void operator=(const vtkSMTKResourceSource&) = delete; }; #endif diff --git a/smtk/extension/paraview/server/vtkSMTKWrapper.cxx b/smtk/extension/paraview/server/vtkSMTKWrapper.cxx index 019a25ea99d003301585ea3e54132025d36870ff..75f38037adc9eef986d403428776d7d42ac81359 100644 --- a/smtk/extension/paraview/server/vtkSMTKWrapper.cxx +++ b/smtk/extension/paraview/server/vtkSMTKWrapper.cxx @@ -73,6 +73,7 @@ vtkSMTKWrapper::vtkSMTKWrapper() smtk::extension::paraview::PluginManager::instance()->registerPluginsTo(this->ResourceManager); this->OperationManager = smtk::operation::Manager::create(); + this->OperationManager->registerResourceManager(this->ResourceManager); smtk::extension::paraview::PluginManager::instance()->registerPluginsTo(this->OperationManager); this->Selection = smtk::view::Selection::create(); @@ -260,11 +261,11 @@ void vtkSMTKWrapper::AddResourceFilter(json& response) if (rsrcThing) { vtkAlgorithm* alg = rsrcThing; - vtkSMTKResourceReader* resourceSrc = nullptr; + vtkSMTKResourceSource* resourceSrc = nullptr; // Recursively walk up ParaView's pipeline until we encounter one of our - // creation filters (marked by inheritence from vtkSMTKResourceReader). - while (alg && !(resourceSrc = vtkSMTKResourceReader::SafeDownCast(alg))) + // creation filters (marked by inheritence from vtkSMTKResourceSource). + while (alg && !(resourceSrc = vtkSMTKResourceSource::SafeDownCast(alg))) { alg = alg->GetInputAlgorithm(0, 0); } diff --git a/smtk/extension/qt/qtOperationView.cxx b/smtk/extension/qt/qtOperationView.cxx index 9125f4b11b784fc1cf53981855b97f169f998fa8..e9451fd37a7d87e8f08ec8c2bb0dd37f1f4b3bf7 100644 --- a/smtk/extension/qt/qtOperationView.cxx +++ b/smtk/extension/qt/qtOperationView.cxx @@ -12,6 +12,7 @@ #include "smtk/extension/qt/qtInstancedView.h" #include "smtk/attribute/Attribute.h" +#include "smtk/attribute/Resource.h" #include "smtk/extension/qt/qtAttribute.h" #include "smtk/extension/qt/qtUIManager.h" #include "smtk/operation/Operation.h" @@ -89,6 +90,16 @@ qtOperationView::~qtOperationView() delete this->Internals; } +QPointer qtOperationView::applyButton() const +{ + return this->Internals->m_applyButton; +} + +smtk::operation::OperationPtr qtOperationView::operation() const +{ + return this->Internals->m_operator; +} + void qtOperationView::createWidget() { QVBoxLayout* parentlayout = static_cast(this->parentWidget()->layout()); diff --git a/smtk/extension/qt/qtOperationView.h b/smtk/extension/qt/qtOperationView.h index cba66b47d1adf2735b1d4b20664bd41cea966e6a..79e5d05173ae168182aebd713430c919257dce5e 100644 --- a/smtk/extension/qt/qtOperationView.h +++ b/smtk/extension/qt/qtOperationView.h @@ -18,7 +18,10 @@ #include "smtk/extension/qt/Exports.h" #include "smtk/extension/qt/qtBaseView.h" +#include + class qtOperationViewInternals; +class QPushButton; namespace smtk { @@ -55,6 +58,9 @@ public: qtOperationView(const OperationViewInfo& info); virtual ~qtOperationView(); + QPointer applyButton() const; + smtk::operation::OperationPtr operation() const; + public slots: void showAdvanceLevelOverlay(bool show) override; void requestModelEntityAssociation() override; diff --git a/smtk/operation/CMakeLists.txt b/smtk/operation/CMakeLists.txt index a56df324fb74504ee013957d63c6686eb71883d3..d1831b52624f0e1870f8c8ce3f6f853191fe89ac 100644 --- a/smtk/operation/CMakeLists.txt +++ b/smtk/operation/CMakeLists.txt @@ -10,6 +10,7 @@ set(operationSrcs SpecificationOps.cxx XMLOperation.cxx + groups/CreatorGroup.cxx groups/ImporterGroup.cxx groups/ExporterGroup.cxx groups/ReaderGroup.cxx @@ -33,6 +34,7 @@ set(operationHeaders ResourceManagerOperation.h XMLOperation.h + groups/CreatorGroup.h groups/ImporterGroup.h groups/ExporterGroup.h groups/ReaderGroup.h diff --git a/smtk/operation/groups/CreatorGroup.cxx b/smtk/operation/groups/CreatorGroup.cxx new file mode 100644 index 0000000000000000000000000000000000000000..462cce50e78cecd34a85747123697f7fc7fcaaeb --- /dev/null +++ b/smtk/operation/groups/CreatorGroup.cxx @@ -0,0 +1,75 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= + +#include "smtk/operation/groups/CreatorGroup.h" +#include "smtk/attribute/Attribute.h" + +#include "smtk/operation/Manager.h" + +namespace smtk +{ +namespace operation +{ + +std::string CreatorGroup::resourceForOperation(const Operation::Index& index) const +{ + auto vals = values(index); + return !vals.empty() ? *vals.begin() : ""; +} + +std::string CreatorGroup::resourceForOperation(const std::string& operationName) const +{ + auto vals = values(operationName); + return !vals.empty() ? *vals.begin() : ""; +} + +std::set CreatorGroup::operationsForResource( + const std::string& resourceName) const +{ + std::set operations; + + auto manager = m_manager.lock(); + if (manager == nullptr) + { + return operations; + } + + std::set allOperations = this->operations(); + + for (auto& index : allOperations) + { + if (resourceForOperation(index) == resourceName) + { + operations.insert(index); + } + } + return operations; +} + +std::set CreatorGroup::supportedResources() const +{ + std::set resources; + + auto manager = m_manager.lock(); + if (manager == nullptr) + { + return resources; + } + + std::set allOperations = this->operations(); + + for (auto& index : allOperations) + { + resources.insert(resourceForOperation(index)); + } + return resources; +} +} +} diff --git a/smtk/operation/groups/CreatorGroup.h b/smtk/operation/groups/CreatorGroup.h new file mode 100644 index 0000000000000000000000000000000000000000..8483c9f42111b4460efdaf8ed4e6cd57cb77f564 --- /dev/null +++ b/smtk/operation/groups/CreatorGroup.h @@ -0,0 +1,111 @@ +//========================================================================= +// Copyright (c) Kitware, Inc. +// All rights reserved. +// See LICENSE.txt for details. +// +// This software is distributed WITHOUT ANY WARRANTY; without even +// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. See the above copyright notice for more information. +//========================================================================= + +#ifndef smtk_operation_CreatorGroup_h +#define smtk_operation_CreatorGroup_h + +#include "smtk/CoreExports.h" + +#include "smtk/attribute/Attribute.h" +#include "smtk/attribute/Definition.h" +#include "smtk/attribute/FileItem.h" +#include "smtk/attribute/FileItemDefinition.h" + +#include "smtk/common/TypeName.h" + +#include "smtk/operation/Group.h" +#include "smtk/operation/Manager.h" +#include "smtk/operation/Operation.h" +#include "smtk/operation/SpecificationOps.h" + +#include +#include + +namespace smtk +{ +namespace operation +{ +class Manager; + +class SMTKCORE_EXPORT CreatorGroup : protected Group +{ +public: + using Group::has; + using Group::operations; + using Group::operationNames; + + static constexpr const char* const type_name = "creator"; + + CreatorGroup(std::shared_ptr manager) + : Group(type_name, manager) + { + } + + /// Register an IO operation identified by it's unique name and the type of + /// resource it handles. + template + bool registerOperation(const std::string&); + + /// Register an IO operation identified by its type index and the type of + /// resource it handles. + template + bool registerOperation(const Operation::Index&); + + /// Register an IO operation identified by its class type and the name of the + /// resource it reads. + template + bool registerOperation(); + + /// Given a resource name, return the set of operators that were associated + /// with the resource during registration. + std::set operationsForResource(const std::string& resourceName) const; + + /// Given an operation name, return the resource associated with the operation. + std::string resourceForOperation(const std::string&) const; + + /// Given an operation index, return the resource associated with the operation. + std::string resourceForOperation(const Operation::Index&) const; + + /// Given a resource type, return the set of operators that were associated + /// with the resource during registration. + template + std::set operationsForResource() const; + + std::set supportedResources() const; +}; + +template +bool CreatorGroup::registerOperation(const std::string& typeName) +{ + return Group::registerOperation(typeName, { smtk::common::typeName() }); +} + +template +bool CreatorGroup::registerOperation(const Operation::Index& index) +{ + return Group::registerOperation(index, { smtk::common::typeName() }); +} + +template +bool CreatorGroup::registerOperation() +{ + return Group::registerOperation( + std::type_index(typeid(OperationType)).hash_code(), { smtk::common::typeName() }); +} + +template +std::set CreatorGroup::operationsForResource() const +{ + return operationsForResource(smtk::common::typeName()); +} +} +} + +#endif // smtk_operation_CreatorGroup_h