From 4bc2a1d6f3e8d87c23a337440cdb4b6602fb2edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Sat, 21 Dec 2024 23:13:10 +0100 Subject: [PATCH] FEM: Add post pipeline branch --- src/Mod/Fem/App/AppFem.cpp | 2 + src/Mod/Fem/App/CMakeLists.txt | 10 +- ...PostBranch.cpp => FemPostBranchFilter.cpp} | 34 ++- ...{FemPostBranch.h => FemPostBranchFilter.h} | 17 +- ...BranchPy.xml => FemPostBranchFilterPy.xml} | 8 +- ...PyImp.cpp => FemPostBranchFilterPyImp.cpp} | 26 +- src/Mod/Fem/App/FemPostFilter.cpp | 2 +- src/Mod/Fem/App/FemPostGroupExtension.cpp | 11 + src/Mod/Fem/App/FemPostGroupExtension.h | 3 + src/Mod/Fem/Gui/AppFemGui.cpp | 2 + src/Mod/Fem/Gui/CMakeLists.txt | 3 + src/Mod/Fem/Gui/Command.cpp | 258 +++++++----------- src/Mod/Fem/Gui/Resources/Fem.qrc | 1 + .../Resources/icons/FEM_PostBranchFilter.svg | 118 ++++++++ src/Mod/Fem/Gui/TaskPostBoxes.cpp | 58 ++++ src/Mod/Fem/Gui/TaskPostBoxes.h | 27 +- src/Mod/Fem/Gui/TaskPostBranch.ui | 103 +++++++ .../Gui/ViewProviderFemPostBranchFilter.cpp | 53 ++++ .../Fem/Gui/ViewProviderFemPostBranchFilter.h | 61 +++++ src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h | 8 +- src/Mod/Fem/Gui/Workbench.cpp | 1 + 21 files changed, 595 insertions(+), 211 deletions(-) rename src/Mod/Fem/App/{FemPostBranch.cpp => FemPostBranchFilter.cpp} (87%) rename src/Mod/Fem/App/{FemPostBranch.h => FemPostBranchFilter.h} (86%) rename src/Mod/Fem/App/{FemPostBranchPy.xml => FemPostBranchFilterPy.xml} (87%) rename src/Mod/Fem/App/{FemPostBranchPyImp.cpp => FemPostBranchFilterPyImp.cpp} (76%) create mode 100644 src/Mod/Fem/Gui/Resources/icons/FEM_PostBranchFilter.svg create mode 100644 src/Mod/Fem/Gui/TaskPostBranch.ui create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index f769425c9b..b8a8cb6d17 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -65,6 +65,7 @@ #include "FemPostFilter.h" #include "FemPostFunction.h" #include "FemPostPipeline.h" +#include "FemPostBranchFilter.h" #include "PropertyPostDataObject.h" #endif @@ -187,6 +188,7 @@ PyMOD_INIT_FUNC(Fem) Fem::FemPostGroupExtension ::init(); Fem::FemPostPipeline ::init(); Fem::FemPostFilter ::init(); + Fem::FemPostBranchFilter ::init(); Fem::FemPostClipFilter ::init(); Fem::FemPostContoursFilter ::init(); Fem::FemPostCutFilter ::init(); diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index 234de8551b..61d3f20be1 100644 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -67,12 +67,12 @@ if(BUILD_FEM_VTK) FemPostObjectPyImp.cpp FemPostPipelinePy.xml FemPostPipelinePyImp.cpp - FemPostBranchPy.xml - FemPostBranchPyImp.cpp + FemPostBranchFilterPy.xml + FemPostBranchFilterPyImp.cpp ) generate_from_xml(FemPostObjectPy) generate_from_xml(FemPostPipelinePy) - generate_from_xml(FemPostBranchPy) + generate_from_xml(FemPostBranchFilterPy) endif(BUILD_FEM_VTK) SOURCE_GROUP("Python" FILES ${Python_SRCS}) @@ -87,8 +87,8 @@ if(BUILD_FEM_VTK) FemPostGroupExtension.cpp FemPostPipeline.h FemPostPipeline.cpp - FemPostBranch.h - FemPostBranch.cpp + FemPostBranchFilter.h + FemPostBranchFilter.cpp FemPostFilter.h FemPostFilter.cpp FemPostFunction.h diff --git a/src/Mod/Fem/App/FemPostBranch.cpp b/src/Mod/Fem/App/FemPostBranchFilter.cpp similarity index 87% rename from src/Mod/Fem/App/FemPostBranch.cpp rename to src/Mod/Fem/App/FemPostBranchFilter.cpp index e92704d93a..e9b2d76d2f 100644 --- a/src/Mod/Fem/App/FemPostBranch.cpp +++ b/src/Mod/Fem/App/FemPostBranchFilter.cpp @@ -41,19 +41,19 @@ #include "FemMesh.h" #include "FemMeshObject.h" -#include "FemPostBranch.h" -#include "FemPostBranchPy.h" +#include "FemPostBranchFilter.h" +#include "FemPostBranchFilterPy.h" #include "FemVTKTools.h" using namespace Fem; using namespace App; -PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostBranch, Fem::FemPostFilter); +PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostBranchFilter, Fem::FemPostFilter); -const char* FemPostBranch::OutputEnums[] = {"Passthrough", "Append", nullptr}; +const char* FemPostBranchFilter::OutputEnums[] = {"Passthrough", "Append", nullptr}; -FemPostBranch::FemPostBranch() : Fem::FemPostFilter(), Fem::FemPostGroupExtension() +FemPostBranchFilter::FemPostBranchFilter() : Fem::FemPostFilter(), Fem::FemPostGroupExtension() { FemPostGroupExtension::initExtension(this); @@ -93,9 +93,9 @@ FemPostBranch::FemPostBranch() : Fem::FemPostFilter(), Fem::FemPostGroupExtensio setActiveFilterPipeline("passthrough"); } -FemPostBranch::~FemPostBranch() = default; +FemPostBranchFilter::~FemPostBranchFilter() = default; -short FemPostBranch::mustExecute() const +short FemPostBranchFilter::mustExecute() const { if (Mode.isTouched()) { return 1; @@ -105,7 +105,7 @@ short FemPostBranch::mustExecute() const } -void FemPostBranch::onChanged(const Property* prop) +void FemPostBranchFilter::onChanged(const Property* prop) { /* onChanged handles the Pipeline setup: we connect the inputs and outputs * of our child filters correctly according to the new settings @@ -170,13 +170,23 @@ void FemPostBranch::onChanged(const Property* prop) else { setActiveFilterPipeline("append"); } + // inform toplevel pipeline we changed + App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this); + if (!group) { + return; + } + if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) { + auto postgroup = group->getExtensionByType(); + postgroup->filterChanged(this); + } } FemPostFilter::onChanged(prop); } -void FemPostBranch::filterChanged(FemPostFilter* filter) +void FemPostBranchFilter::filterChanged(FemPostFilter* filter) { + //we only need to update the following children if we are in serial mode if (Mode.getValue() == 0) { @@ -213,7 +223,7 @@ void FemPostBranch::filterChanged(FemPostFilter* filter) } } -void FemPostBranch::filterPipelineChanged(FemPostFilter*) { +void FemPostBranchFilter::filterPipelineChanged(FemPostFilter*) { // one of our filters has changed its active pipeline. We need to reconnect it properly. // As we are cheap we just reconnect everything // TODO: Do more efficiently @@ -221,11 +231,11 @@ void FemPostBranch::filterPipelineChanged(FemPostFilter*) { } -PyObject* FemPostBranch::getPyObject() +PyObject* FemPostBranchFilter::getPyObject() { if (PythonObject.is(Py::_None())) { // ref counter is set to 1 - PythonObject = Py::Object(new FemPostBranchPy(this), true); + PythonObject = Py::Object(new FemPostBranchFilterPy(this), true); } return Py::new_reference_to(PythonObject); } diff --git a/src/Mod/Fem/App/FemPostBranch.h b/src/Mod/Fem/App/FemPostBranchFilter.h similarity index 86% rename from src/Mod/Fem/App/FemPostBranch.h rename to src/Mod/Fem/App/FemPostBranchFilter.h index 1762d0d025..fd04b51e4c 100644 --- a/src/Mod/Fem/App/FemPostBranch.h +++ b/src/Mod/Fem/App/FemPostBranchFilter.h @@ -20,8 +20,8 @@ * * ***************************************************************************/ -#ifndef Fem_FemPostBranch_H -#define Fem_FemPostBranch_H +#ifndef Fem_FemPostBranchFilter_H +#define Fem_FemPostBranchFilter_H #include "FemPostFilter.h" @@ -35,16 +35,15 @@ namespace Fem { -class FemExport FemPostBranch: public Fem::FemPostFilter, public FemPostGroupExtension +class FemExport FemPostBranchFilter: public Fem::FemPostFilter, public FemPostGroupExtension { - PROPERTY_HEADER_WITH_EXTENSIONS(Fem::FemPostBranch); + PROPERTY_HEADER_WITH_EXTENSIONS(Fem::FemPostBranchFilter); public: /// Constructor - FemPostBranch(); - ~FemPostBranch() override; + FemPostBranchFilter(); + ~FemPostBranchFilter() override; - App::PropertyEnumeration Mode; App::PropertyEnumeration Output; @@ -53,7 +52,7 @@ public: const char* getViewProviderName() const override { - return "FemGui::ViewProviderFemPostBranch"; + return "FemGui::ViewProviderFemPostBranchFilter"; } // Branch handling @@ -73,4 +72,4 @@ private: } // namespace Fem -#endif // Fem_FemPostBranch_H +#endif // Fem_FemPostBranchFilter_H diff --git a/src/Mod/Fem/App/FemPostBranchPy.xml b/src/Mod/Fem/App/FemPostBranchFilterPy.xml similarity index 87% rename from src/Mod/Fem/App/FemPostBranchPy.xml rename to src/Mod/Fem/App/FemPostBranchFilterPy.xml index 73f7325548..91cd392996 100644 --- a/src/Mod/Fem/App/FemPostBranchPy.xml +++ b/src/Mod/Fem/App/FemPostBranchFilterPy.xml @@ -2,10 +2,10 @@ diff --git a/src/Mod/Fem/App/FemPostBranchPyImp.cpp b/src/Mod/Fem/App/FemPostBranchFilterPyImp.cpp similarity index 76% rename from src/Mod/Fem/App/FemPostBranchPyImp.cpp rename to src/Mod/Fem/App/FemPostBranchFilterPyImp.cpp index cab55fc171..23051912b2 100644 --- a/src/Mod/Fem/App/FemPostBranchPyImp.cpp +++ b/src/Mod/Fem/App/FemPostBranchFilterPyImp.cpp @@ -28,45 +28,45 @@ #include // clang-format off -#include "FemPostBranch.h" -#include "FemPostBranchPy.h" -#include "FemPostBranchPy.cpp" +#include "FemPostBranchFilter.h" +#include "FemPostBranchFilterPy.h" +#include "FemPostBranchFilterPy.cpp" // clang-format on using namespace Fem; // returns a string which represents the object e.g. when printed in python -std::string FemPostBranchPy::representation() const +std::string FemPostBranchFilterPy::representation() const { - return {""}; + return {""}; } -PyObject* FemPostBranchPy::recomputeChildren(PyObject* args) +PyObject* FemPostBranchFilterPy::recomputeChildren(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; } - getFemPostBranchPtr()->recomputeChildren(); + getFemPostBranchFilterPtr()->recomputeChildren(); Py_Return; } -PyObject* FemPostBranchPy::getLastPostObject(PyObject* args) +PyObject* FemPostBranchFilterPy::getLastPostObject(PyObject* args) { if (!PyArg_ParseTuple(args, "")) { return nullptr; } - App::DocumentObject* obj = getFemPostBranchPtr()->getLastPostObject(); + App::DocumentObject* obj = getFemPostBranchFilterPtr()->getLastPostObject(); if (obj) { return obj->getPyObject(); } Py_Return; } -PyObject* FemPostBranchPy::holdsPostObject(PyObject* args) +PyObject* FemPostBranchFilterPy::holdsPostObject(PyObject* args) { PyObject* py; if (!PyArg_ParseTuple(args, "O!", &(App::DocumentObjectPy::Type), &py)) { @@ -79,16 +79,16 @@ PyObject* FemPostBranchPy::holdsPostObject(PyObject* args) return nullptr; } - bool ok = getFemPostBranchPtr()->holdsPostObject(static_cast(obj)); + bool ok = getFemPostBranchFilterPtr()->holdsPostObject(static_cast(obj)); return Py_BuildValue("O", (ok ? Py_True : Py_False)); } -PyObject* FemPostBranchPy::getCustomAttributes(const char* /*attr*/) const +PyObject* FemPostBranchFilterPy::getCustomAttributes(const char* /*attr*/) const { return nullptr; } -int FemPostBranchPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +int FemPostBranchFilterPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) { return 0; } diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index 428347cb33..f1f7789566 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -35,7 +35,7 @@ #include "FemPostFilter.h" #include "FemPostPipeline.h" -#include "FemPostBranch.h" +#include "FemPostBranchFilter.h" using namespace Fem; diff --git a/src/Mod/Fem/App/FemPostGroupExtension.cpp b/src/Mod/Fem/App/FemPostGroupExtension.cpp index 58436f9022..6fafdbc95a 100644 --- a/src/Mod/Fem/App/FemPostGroupExtension.cpp +++ b/src/Mod/Fem/App/FemPostGroupExtension.cpp @@ -123,6 +123,17 @@ void FemPostGroupExtension::extensionOnChanged(const App::Property* p) GroupExtension::extensionOnChanged(p); } +App::DocumentObject* FemPostGroupExtension::getGroupOfObject(const App::DocumentObject* obj) +{ + for (auto o : obj->getInList()) { + if (o->hasExtension(FemPostGroupExtension::getExtensionClassTypeId(), false)) { + return o; + } + } + + return nullptr; +} + void FemPostGroupExtension::onExtendedUnsetupObject() { // remove all children! diff --git a/src/Mod/Fem/App/FemPostGroupExtension.h b/src/Mod/Fem/App/FemPostGroupExtension.h index 311f2981c3..8cce8fb1ca 100644 --- a/src/Mod/Fem/App/FemPostGroupExtension.h +++ b/src/Mod/Fem/App/FemPostGroupExtension.h @@ -53,6 +53,9 @@ public: virtual FemPostObject* getLastPostObject(); virtual bool holdsPostObject(FemPostObject* obj); + // general + static App::DocumentObject* getGroupOfObject(const App::DocumentObject* obj); + protected: void extensionOnChanged(const App::Property* p) override; void onExtendedUnsetupObject() override; diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index 6f9fc459b2..cc0aa8dc7f 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -74,6 +74,7 @@ #include "ViewProviderFemPostFunction.h" #include "ViewProviderFemPostObject.h" #include "ViewProviderFemPostPipeline.h" +#include "ViewProviderFemPostBranchFilter.h" #endif @@ -160,6 +161,7 @@ PyMOD_INIT_FUNC(FemGui) #ifdef FC_USE_VTK FemGui::ViewProviderFemPostObject ::init(); FemGui::ViewProviderFemPostPipeline ::init(); + FemGui::ViewProviderFemPostBranchFilter ::init(); FemGui::ViewProviderFemPostClip ::init(); FemGui::ViewProviderFemPostContours ::init(); FemGui::ViewProviderFemPostCut ::init(); diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index c9fc4f5bfc..6fb0572ecd 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -96,6 +96,7 @@ if(BUILD_FEM_VTK) TaskPostScalarClip.ui TaskPostWarpVector.ui TaskPostFrames.ui + TaskPostBranch.ui ) endif(BUILD_FEM_VTK) @@ -334,6 +335,8 @@ if(BUILD_FEM_VTK) ViewProviderFemPostObject.cpp ViewProviderFemPostPipeline.h ViewProviderFemPostPipeline.cpp + ViewProviderFemPostBranchFilter.h + ViewProviderFemPostBranchFilter.cpp ViewProviderFemPostFunction.h ViewProviderFemPostFunction.cpp ViewProviderFemPostFilter.h diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index 292c43bb13..9e1411a231 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -1838,31 +1838,20 @@ void setupFilter(Gui::Command* cmd, std::string Name) // at first we must determine the pipeline of the selection object // (which can be a pipeline itself) - bool selectionIsPipeline = false; - Fem::FemPostPipeline* pipeline = nullptr; - if (selObject->isDerivedFrom()) { - pipeline = static_cast(selObject); - selectionIsPipeline = true; - } - else { - auto parents = selObject->getInList(); - if (!parents.empty()) { - for (auto parentObject : parents) { - if (parentObject->isDerivedFrom()) { - pipeline = static_cast(parentObject); - } - } + App::DocumentObject* pipeline = nullptr; + if(selObject->hasExtension(Fem::FemPostGroupExtension::getExtensionClassTypeId())) { + pipeline = selObject; + } else { + pipeline = Fem::FemPostGroupExtension::getGroupOfObject(selObject); + if (!pipeline || !pipeline->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + QMessageBox::warning( + Gui::getMainWindow(), + qApp->translate("setupFilter", "Error: Object not in a post processing group"), + qApp->translate("setupFilter", "The filter could not be set up: Object not in a post processing group.")); + return; } } - if (!pipeline) { - QMessageBox::warning( - Gui::getMainWindow(), - qApp->translate("setupFilter", "Error: no post processing object selected."), - qApp->translate("setupFilter", "The filter could not be set up.")); - return; - } - // create the object and add it to the pipeline cmd->openCommand(QT_TRANSLATE_NOOP("Command", "Create filter")); cmd->doCommand(Gui::Command::Doc, @@ -2032,30 +2021,15 @@ void CmdFemPostClipFilter::activated(int) bool CmdFemPostClipFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2084,30 +2058,15 @@ void CmdFemPostCutFilter::activated(int) bool CmdFemPostCutFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2136,27 +2095,15 @@ void CmdFemPostDataAlongLineFilter::activated(int) bool CmdFemPostDataAlongLineFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2186,27 +2133,15 @@ void CmdFemPostDataAtPointFilter::activated(int) bool CmdFemPostDataAtPointFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2311,27 +2246,15 @@ void CmdFemPostScalarClipFilter::activated(int) bool CmdFemPostScalarClipFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible other filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2360,27 +2283,15 @@ void CmdFemPostWarpVectorFilter::activated(int) bool CmdFemPostWarpVectorFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible other filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2409,27 +2320,15 @@ void CmdFemPostContoursFilter::activated(int) bool CmdFemPostContoursFilter::isActive() { // only allow one object - if (getSelection().getSelection().size() > 1) { + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { return false; } - // only activate if a result is either a post pipeline or a possible other filter - if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; - } - else if (getSelection().countObjectsOfType() == 1) { - return true; + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } } return false; } @@ -2796,6 +2695,42 @@ bool CmdFemPostPipelineFromResult::isActive() return (results.size() == 1) ? true : false; } +//================================================================================================ +DEF_STD_CMD_A(CmdFemPostBranchFilter) + +CmdFemPostBranchFilter::CmdFemPostBranchFilter() + : Command("FEM_PostBranchFilter") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Pipeline branch"); + sToolTipText = QT_TR_NOOP("Branches the pipeline into a new path"); + sWhatsThis = "FEM_PostBranchFilter"; + sStatusTip = sToolTipText; + sPixmap = "FEM_PostBranchFilter"; +} + +void CmdFemPostBranchFilter::activated(int) +{ + setupFilter(this, "Branch"); +} + +bool CmdFemPostBranchFilter::isActive() +{ + // only allow one object + auto selection = getSelection().getSelection(); + if (selection.size() > 1) { + return false; + } + // only activate if a post object is selected + for (auto obj : selection ) { + if (obj.pObject->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + return true; + } + } + return false; +} + #endif @@ -2851,6 +2786,7 @@ void CreateFemCommands() rcCmdMgr.addCommand(new CmdFemPostLinearizedStressesFilter); rcCmdMgr.addCommand(new CmdFemPostFunctions); rcCmdMgr.addCommand(new CmdFemPostPipelineFromResult); + rcCmdMgr.addCommand(new CmdFemPostBranchFilter); rcCmdMgr.addCommand(new CmdFemPostScalarClipFilter); rcCmdMgr.addCommand(new CmdFemPostWarpVectorFilter); #endif diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index d92c070cba..dd132e54fc 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -81,6 +81,7 @@ icons/FEM_PostFilterLinearizedStresses.svg icons/FEM_PostFilterWarp.svg icons/FEM_PostFrames.svg + icons/FEM_PostBranchFilter.svg icons/FEM_PostPipelineFromResult.svg icons/FEM_ResultShow.svg icons/FEM_ResultsPurge.svg diff --git a/src/Mod/Fem/Gui/Resources/icons/FEM_PostBranchFilter.svg b/src/Mod/Fem/Gui/Resources/icons/FEM_PostBranchFilter.svg new file mode 100644 index 0000000000..39dfd204f1 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/FEM_PostBranchFilter.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + image/svg+xml + + + + [Alexander Gryson] + + + 2017-03-11 + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/ + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.cpp b/src/Mod/Fem/Gui/TaskPostBoxes.cpp index eab5d3cd53..d4f78a0465 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.cpp +++ b/src/Mod/Fem/Gui/TaskPostBoxes.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include "ui_TaskPostClip.h" @@ -60,6 +61,7 @@ #include "ui_TaskPostScalarClip.h" #include "ui_TaskPostWarpVector.h" #include "ui_TaskPostFrames.h" +#include "ui_TaskPostBranch.h" #include "FemSettings.h" @@ -67,6 +69,7 @@ #include "ViewProviderFemPostFilter.h" #include "ViewProviderFemPostFunction.h" #include "ViewProviderFemPostObject.h" +#include "ViewProviderFemPostBranchFilter.h" using namespace FemGui; @@ -540,6 +543,61 @@ void TaskPostFrames::applyPythonCode() // *************************************************************************** +// *************************************************************************** +// Branch +TaskPostBranch::TaskPostBranch(ViewProviderFemPostBranchFilter* view, QWidget* parent) + : TaskPostBox(view, + Gui::BitmapFactory().pixmap("FEM_PostBranchFilter"), + tr("Branch behaviour"), + parent), ui(new Ui_TaskPostBranch) +{ + // we load the views widget + proxy = new QWidget(this); + ui->setupUi(proxy); + this->groupLayout()->addWidget(proxy); + setupConnections(); + + // populate the data + auto branch = static_cast(getObject()); + + ui->ModeBox->setCurrentIndex(branch->Mode.getValue()); + ui->OutputBox->setCurrentIndex(branch->Output.getValue()); +} + +TaskPostBranch::~TaskPostBranch() = default; + +void TaskPostBranch::setupConnections() +{ + connect(ui->ModeBox, + qOverload(&QComboBox::currentIndexChanged), + this, + &TaskPostBranch::onModeIndexChanged); + + connect(ui->OutputBox, + qOverload(&QComboBox::currentIndexChanged), + this, + &TaskPostBranch::onOutputIndexChanged); +} + +void TaskPostBranch::onModeIndexChanged(int idx) +{ + static_cast(getObject())->Mode.setValue(idx); +} + +void TaskPostBranch::onOutputIndexChanged(int idx) +{ + static_cast(getObject())->Output.setValue(idx); +} + + + +void TaskPostBranch::applyPythonCode() +{ + // we apply the views widgets python code +} + + + // *************************************************************************** // data along line filter TaskPostDataAlongLine::TaskPostDataAlongLine(ViewProviderFemPostDataAlongLine* view, diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.h b/src/Mod/Fem/Gui/TaskPostBoxes.h index 85c0b350fc..b33729e03b 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.h +++ b/src/Mod/Fem/Gui/TaskPostBoxes.h @@ -30,7 +30,6 @@ #include "ViewProviderFemPostFunction.h" - class QComboBox; class Ui_TaskPostDisplay; class Ui_TaskPostClip; @@ -41,6 +40,7 @@ class Ui_TaskPostScalarClip; class Ui_TaskPostWarpVector; class Ui_TaskPostCut; class Ui_TaskPostFrames; +class Ui_TaskPostBranch; class SoFontStyle; class SoText2; @@ -278,7 +278,7 @@ public: }; // *************************************************************************** -// steps +// frames class TaskPostFrames: public TaskPostBox { Q_OBJECT @@ -303,6 +303,29 @@ private: // *************************************************************************** +// *************************************************************************** +// branch +class ViewProviderFemPostBranchFilter; + +class TaskPostBranch: public TaskPostBox +{ + Q_OBJECT + +public: + explicit TaskPostBranch(ViewProviderFemPostBranchFilter* view, QWidget* parent = nullptr); + ~TaskPostBranch() override; + + void applyPythonCode() override; + +private: + void setupConnections(); + void onModeIndexChanged(int); + void onOutputIndexChanged(int); + + QWidget* proxy; + std::unique_ptr ui; +}; + // *************************************************************************** // data along line filter class ViewProviderFemPostDataAlongLine; diff --git a/src/Mod/Fem/Gui/TaskPostBranch.ui b/src/Mod/Fem/Gui/TaskPostBranch.ui new file mode 100644 index 0000000000..4e94d5fcfd --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostBranch.ui @@ -0,0 +1,103 @@ + + + TaskPostBranch + + + + 0 + 0 + 292 + 94 + + + + + 0 + 0 + + + + Form + + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Selects the input, the child filter will receive:</p><p><span style=" font-weight:600;">Serial:</span> The first filter in the branch will get the Branches input as its own input. The next filter will then receive the firsts filters output as input, and so on.</p><p><span style=" font-weight:600;">Parallel: </span>All filter in the branch will receive the Branches input as their own input. </p></body></html> + + + Mode + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Selects the input, the child filters will receive:</p><p><span style=" font-weight:600;">Serial:</span> The first filter in the branch will get the Branches input as its own input. The next filter will then receive the firsts filters output as input, and so on.</p><p><span style=" font-weight:600;">Parallel: </span>All filter in the branch will receive the Branches input as their own input. </p></body></html> + + + + Serial + + + + + Parallel + + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Selects the how the output of the branch is determined:</p><p><span style=" font-weight:600;">Passthrough:</span> The branches output is the same as its input, no matter what the branch child filter do.</p><p><span style=" font-weight:600;">Append:</span> The branches output is a collection of all child filter: it appends child outputs together and offers this as branch output.</p></body></html> + + + + Passthrough + + + + + Append + + + + + + + + <html><head/><body><p>Selects the how the output of the branch is determined:</p><p><span style=" font-weight:600;">Passthrough:</span> The branches output is the same as its input, no matter what the branch child filter do.</p><p><span style=" font-weight:600;">Append:</span> The branches output is a collection of all child filter: it appends child outputs together and offers this as branch output.</p></body></html> + + + Output + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.cpp new file mode 100644 index 0000000000..941485e127 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (c) 2015 Stefan Tröger * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#include "TaskPostBoxes.h" +#include "ViewProviderFemPostBranchFilter.h" + + +using namespace FemGui; + + +PROPERTY_SOURCE_WITH_EXTENSIONS(FemGui::ViewProviderFemPostBranchFilter, FemGui::ViewProviderFemPostObject) + +ViewProviderFemPostBranchFilter::ViewProviderFemPostBranchFilter() : Gui::ViewProviderGroupExtension() +{ + Gui::ViewProviderGroupExtension::initExtension(this); + sPixmap = "FEM_PostBranchFilter"; +} + +ViewProviderFemPostBranchFilter::~ViewProviderFemPostBranchFilter() +{ + +} + +void ViewProviderFemPostBranchFilter::setupTaskDialog(TaskDlgPost* dlg) +{ + // add the branch ui + dlg->appendBox(new TaskPostBranch(this)); + + // add the display options + FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg); +} + diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h b/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h new file mode 100644 index 0000000000..75199692fb --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostBranchFilter.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (c) 2015 Stefan Tröger * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#ifndef FEM_VIEWPROVIDERFEMPOSTBRANCHFILTER_H +#define FEM_VIEWPROVIDERFEMPOSTBRANCHFILTER_H + +#include "ViewProviderFemPostObject.h" +#include + + +namespace Gui +{ +class SelectionChanges; +class SoFCColorBar; +} // namespace Gui + +namespace FemGui +{ + +class TaskDlgPost; + +class FemGuiExport ViewProviderFemPostBranchFilter: public ViewProviderFemPostObject, public Gui::ViewProviderGroupExtension +{ + PROPERTY_HEADER_WITH_EXTENSIONS(FemGui::ViewProviderFemPostBranchFilter); + +public: + ViewProviderFemPostBranchFilter(); + ~ViewProviderFemPostBranchFilter() override; + +protected: + virtual void setupTaskDialog(TaskDlgPost* dlg) override; + + // override, to not show/hide children as the parent is shown/hidden like normal groups + void extensionHide() override {}; + void extensionShow() override {}; + +}; + +} + + +#endif // FEM_VIEWPROVIDERFEMPOSTBRANCHFILTER_H diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h index 2c5d5f77b5..199ff626a5 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h @@ -51,13 +51,13 @@ public: void scaleField(vtkDataSet* dset, vtkDataArray* pdata, double FieldFactor); PyObject* getPyObject() override; - // override, to not show/hide children as the parent is shown/hidden like normal groups - void extensionHide() override {}; - void extensionShow() override {}; - protected: void updateFunctionSize(); virtual void setupTaskDialog(TaskDlgPost* dlg) override; + + // override, to not show/hide children as the parent is shown/hidden like normal groups + void extensionHide() override {}; + void extensionShow() override {}; }; } // namespace FemGui diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index adcdc7ad12..345632754e 100644 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -199,6 +199,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const *results << "Separator" << "FEM_PostApplyChanges" << "FEM_PostPipelineFromResult" + << "FEM_PostBranchFilter" << "Separator" << "FEM_PostFilterWarp" << "FEM_PostFilterClipScalar"