From a65a7feb87054c806fbb5c4672c2caccdfa863a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Sat, 21 Dec 2024 20:02:07 +0100 Subject: [PATCH] FEM: Switch post groups to extension based system --- src/App/OriginGroupExtension.cpp | 2 +- src/Mod/Fem/App/AppFem.cpp | 1 + src/Mod/Fem/App/CMakeLists.txt | 2 + src/Mod/Fem/App/FemPostBranch.cpp | 65 ++----- src/Mod/Fem/App/FemPostBranch.h | 33 +--- src/Mod/Fem/App/FemPostFilter.cpp | 37 ++-- src/Mod/Fem/App/FemPostFunction.cpp | 16 +- src/Mod/Fem/App/FemPostFunction.h | 8 +- src/Mod/Fem/App/FemPostGroupExtension.cpp | 163 ++++++++++++++++++ src/Mod/Fem/App/FemPostGroupExtension.h | 68 ++++++++ src/Mod/Fem/App/FemPostPipeline.cpp | 72 +++----- src/Mod/Fem/App/FemPostPipeline.h | 22 +-- src/Mod/Fem/Gui/Command.cpp | 21 +-- src/Mod/Fem/Gui/TaskPostBoxes.cpp | 32 ++-- .../Fem/Gui/ViewProviderFemPostFunction.cpp | 17 +- src/Mod/Fem/Gui/ViewProviderFemPostFunction.h | 6 +- src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp | 10 +- .../Fem/Gui/ViewProviderFemPostPipeline.cpp | 41 +---- src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h | 2 - 19 files changed, 350 insertions(+), 268 deletions(-) create mode 100644 src/Mod/Fem/App/FemPostGroupExtension.cpp create mode 100644 src/Mod/Fem/App/FemPostGroupExtension.h diff --git a/src/App/OriginGroupExtension.cpp b/src/App/OriginGroupExtension.cpp index 5b8a9a0163..a657b9d7a0 100644 --- a/src/App/OriginGroupExtension.cpp +++ b/src/App/OriginGroupExtension.cpp @@ -40,7 +40,7 @@ EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtensi OriginGroupExtension::OriginGroupExtension() { - + Base::Console().Message("Extension type: %s\n", OriginGroupExtension::getExtensionClassTypeId().getName()); initExtensionType(OriginGroupExtension::getExtensionClassTypeId()); EXTENSION_ADD_PROPERTY_TYPE(Origin, diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index ef2cbfce19..f769425c9b 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -184,6 +184,7 @@ PyMOD_INIT_FUNC(Fem) Fem::FemPostSmoothFilterExtension ::init(); Fem::FemPostObject ::init(); + Fem::FemPostGroupExtension ::init(); Fem::FemPostPipeline ::init(); Fem::FemPostFilter ::init(); Fem::FemPostClipFilter ::init(); diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index dff8238603..234de8551b 100644 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -83,6 +83,8 @@ if(BUILD_FEM_VTK) PropertyPostDataObject.cpp FemPostObject.h FemPostObject.cpp + FemPostGroupExtension.h + FemPostGroupExtension.cpp FemPostPipeline.h FemPostPipeline.cpp FemPostBranch.h diff --git a/src/Mod/Fem/App/FemPostBranch.cpp b/src/Mod/Fem/App/FemPostBranch.cpp index 39f486eddc..e92704d93a 100644 --- a/src/Mod/Fem/App/FemPostBranch.cpp +++ b/src/Mod/Fem/App/FemPostBranch.cpp @@ -41,7 +41,6 @@ #include "FemMesh.h" #include "FemMeshObject.h" -#include "FemPostPipeline.h" #include "FemPostBranch.h" #include "FemPostBranchPy.h" #include "FemVTKTools.h" @@ -50,30 +49,22 @@ using namespace Fem; using namespace App; -PROPERTY_SOURCE(Fem::FemPostBranch, Fem::FemPostFilter) -const char* FemPostBranch::ModeEnums[] = {"Serial", "Parallel", nullptr}; +PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostBranch, Fem::FemPostFilter); + const char* FemPostBranch::OutputEnums[] = {"Passthrough", "Append", nullptr}; -FemPostBranch::FemPostBranch() : Fem::FemPostFilter(), App::GroupExtension() +FemPostBranch::FemPostBranch() : Fem::FemPostFilter(), Fem::FemPostGroupExtension() { - GroupExtension::initExtension(this); + FemPostGroupExtension::initExtension(this); - ADD_PROPERTY_TYPE(Mode, - (long(0)), - "Branch", - App::Prop_None, - "Selects which input the child filters of the branch receive\n" - "In serial the first filter receives the branch input, and the concecitive ones get the prior filter output.\n" - "In parallel, every filter receives the branch input."); ADD_PROPERTY_TYPE(Output, (long(0)), - "Branch", + "Pipeline", App::Prop_None, "Selects what the output of the branch itself is\n" "In passthrough the branchs output is equal its imput.\n" - "In append, all filters outputs gets appended as the branches output"); + "In append, all child filter outputs gets appended as the branches output"); - Mode.setEnums(ModeEnums); Output.setEnums(OutputEnums); /* We always have a passthrough filter. This allows to connect our children @@ -211,58 +202,24 @@ void FemPostBranch::filterChanged(FemPostFilter* filter) // if we append as output, we need to inform the parent object that we are isTouched if (Output.getValue() == 1) { //make sure we inform our parent object that we changed, it then can inform others if needed - App::DocumentObject* group = App::GroupExtension::getGroupOfObject(this); + App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this); if (!group) { return; } - - if (group->isDerivedFrom(Fem::FemPostPipeline::getClassTypeId())) { - auto pipe = dynamic_cast(group); - pipe->filterChanged(this); - } - else if (group->isDerivedFrom(Fem::FemPostBranch::getClassTypeId())) { - auto branch = dynamic_cast(group); - branch->filterChanged(this); + if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) { + auto postgroup = group->getExtensionByType(); + postgroup->filterChanged(this); } } } -void FemPostBranch::pipelineChanged(FemPostFilter* filter) { +void FemPostBranch::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 onChanged(&Group); } -void FemPostBranch::recomputeChildren() -{ - for (const auto& obj : Group.getValues()) { - obj->touch(); - } -} - -FemPostObject* FemPostBranch::getLastPostObject() -{ - - if (Group.getValues().empty()) { - return this; - } - - return static_cast(Group.getValues().back()); -} - -bool FemPostBranch::holdsPostObject(FemPostObject* obj) -{ - - std::vector::const_iterator it = Group.getValues().begin(); - for (; it != Group.getValues().end(); ++it) { - - if (*it == obj) { - return true; - } - } - return false; -} PyObject* FemPostBranch::getPyObject() { diff --git a/src/Mod/Fem/App/FemPostBranch.h b/src/Mod/Fem/App/FemPostBranch.h index a9ff238018..1762d0d025 100644 --- a/src/Mod/Fem/App/FemPostBranch.h +++ b/src/Mod/Fem/App/FemPostBranch.h @@ -23,12 +23,9 @@ #ifndef Fem_FemPostBranch_H #define Fem_FemPostBranch_H -#include "App/GroupExtension.h" #include "FemPostFilter.h" -#include "FemPostFunction.h" -#include "FemPostObject.h" -#include "FemResultObject.h" +#include "FemPostGroupExtension.h" #include #include @@ -38,7 +35,7 @@ namespace Fem { -class FemExport FemPostBranch: public Fem::FemPostFilter, public App::GroupExtension +class FemExport FemPostBranch: public Fem::FemPostFilter, public FemPostGroupExtension { PROPERTY_HEADER_WITH_EXTENSIONS(Fem::FemPostBranch); @@ -59,40 +56,18 @@ public: return "FemGui::ViewProviderFemPostBranch"; } - // load data from files - static bool canRead(Base::FileInfo file); - void read(Base::FileInfo file); - void scale(double s); - - // load from results - void load(FemResultObject* res); - // Branch handling - void filterChanged(FemPostFilter* filter); - void pipelineChanged(FemPostFilter* filter); - void recomputeChildren(); - FemPostObject* getLastPostObject(); - bool holdsPostObject(FemPostObject* obj); + void filterChanged(FemPostFilter* filter) override; + void filterPipelineChanged(FemPostFilter* filter) override; protected: void onChanged(const App::Property* prop) override; private: - static const char* ModeEnums[]; static const char* OutputEnums[]; vtkSmartPointer m_append; vtkSmartPointer m_passthrough; - - template - void readXMLFile(std::string file) - { - - vtkSmartPointer reader = vtkSmartPointer::New(); - reader->SetFileName(file.c_str()); - reader->Update(); - Data.setValue(reader->GetOutput()); - } }; } // namespace Fem diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index ccd3327608..428347cb33 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -78,19 +78,14 @@ void FemPostFilter::setActiveFilterPipeline(std::string name) //set the new pipeline active m_activePipeline = name; - //inform our parent, that we need to be connected a new - App::DocumentObject* group = App::GroupExtension::getGroupOfObject(this); + //inform our parent, that we need to be reconnected + App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this); if (!group) { return; } - - if (group->isDerivedFrom(Fem::FemPostPipeline::getClassTypeId())) { - auto pipe = dynamic_cast(group); - pipe->pipelineChanged(this); - } - else if (group->isDerivedFrom(Fem::FemPostBranch::getClassTypeId())) { - auto branch = dynamic_cast(group); - branch->pipelineChanged(this); + if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) { + auto postgroup = group->getExtensionByType(); + postgroup->filterPipelineChanged(this); } } } @@ -103,18 +98,15 @@ FemPostFilter::FilterPipeline& FemPostFilter::getActiveFilterPipeline() void FemPostFilter::onChanged(const App::Property* prop) { //make sure we inform our parent object that we changed, it then can inform others if needed - App::DocumentObject* group = App::GroupExtension::getGroupOfObject(this); - if (!group) { - return FemPostObject::onChanged(prop); - } - - if (group->isDerivedFrom(Fem::FemPostPipeline::getClassTypeId())) { - auto pipe = dynamic_cast(group); - pipe->filterChanged(this); - } - else if (group->isDerivedFrom(Fem::FemPostBranch::getClassTypeId())) { - auto branch = dynamic_cast(group); - branch->filterChanged(this); + if(prop != &Data) { + App::DocumentObject* group = FemPostGroupExtension::getGroupOfObject(this); + if (!group) { + return; + } + if (group->hasExtension(FemPostGroupExtension::getExtensionClassTypeId())) { + auto postgroup = group->getExtensionByType(); + postgroup->filterChanged(this); + } } return FemPostObject::onChanged(prop); @@ -1162,7 +1154,6 @@ FemPostWarpVectorFilter::~FemPostWarpVectorFilter() = default; DocumentObjectExecReturn* FemPostWarpVectorFilter::execute() { - Base::Console().Message("Warp Execute\n"); std::string val; if (Vector.getValue() >= 0) { diff --git a/src/Mod/Fem/App/FemPostFunction.cpp b/src/Mod/Fem/App/FemPostFunction.cpp index 0b41eb95d8..683c5c464f 100644 --- a/src/Mod/Fem/App/FemPostFunction.cpp +++ b/src/Mod/Fem/App/FemPostFunction.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #include "FemPostFunction.h" +#include using namespace Fem; @@ -31,19 +32,26 @@ using namespace App; PROPERTY_SOURCE(Fem::FemPostFunctionProvider, App::DocumentObject) FemPostFunctionProvider::FemPostFunctionProvider() - : DocumentObject() + : DocumentObjectGroup() { - ADD_PROPERTY(Functions, (nullptr)); } FemPostFunctionProvider::~FemPostFunctionProvider() = default; -void FemPostFunctionProvider::onChanged(const Property* prop) +bool FemPostFunctionProvider::allowObject(App::DocumentObject* obj) { - App::DocumentObject::onChanged(prop); + return obj->isDerivedFrom(FemPostFunction::getClassTypeId()); } +void FemPostFunctionProvider::unsetupObject() +{ + // remove all children! + auto document = getExtendedObject()->getDocument(); + for (const auto& obj : Group.getValues()) { + document->removeObject(obj->getNameInDocument()); + } +} PROPERTY_SOURCE(Fem::FemPostFunction, App::DocumentObject) diff --git a/src/Mod/Fem/App/FemPostFunction.h b/src/Mod/Fem/App/FemPostFunction.h index e8885d9369..a23ad01f36 100644 --- a/src/Mod/Fem/App/FemPostFunction.h +++ b/src/Mod/Fem/App/FemPostFunction.h @@ -32,6 +32,7 @@ #include #include +#include #include "FemPostObject.h" @@ -72,7 +73,7 @@ protected: vtkBoundingBox m_boundingBox; }; -class FemExport FemPostFunctionProvider: public App::DocumentObject +class FemExport FemPostFunctionProvider: public App::DocumentObjectGroup { PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostFunctionProvider); @@ -86,10 +87,9 @@ public: return "FemGui::ViewProviderFemPostFunctionProvider"; } - App::PropertyLinkList Functions; - protected: - void onChanged(const App::Property* prop) override; + bool allowObject(App::DocumentObject* obj) override; + void unsetupObject() override; }; // --------------------------------------------------------------------------- diff --git a/src/Mod/Fem/App/FemPostGroupExtension.cpp b/src/Mod/Fem/App/FemPostGroupExtension.cpp new file mode 100644 index 0000000000..58436f9022 --- /dev/null +++ b/src/Mod/Fem/App/FemPostGroupExtension.cpp @@ -0,0 +1,163 @@ +/*************************************************************************** + * Copyright (c) 2024 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 "FemPostGroupExtension.h" +#include + +using namespace Fem; + +EXTENSION_PROPERTY_SOURCE(Fem::FemPostGroupExtension, App::GroupExtension); + +const char* FemPostGroupExtension::ModeEnums[] = {"Serial", "Parallel", nullptr}; + +FemPostGroupExtension::FemPostGroupExtension() : App::GroupExtension() { + + initExtensionType(Fem::FemPostGroupExtension::getExtensionClassTypeId()); + + EXTENSION_ADD_PROPERTY_TYPE(Mode, + (long(0)), + "Pipeline", + App::Prop_None, + "Selects the pipeline data transition mode.\n" + "In serial, every filter gets the output of the previous one as input.\n" + "In parallel, every filter gets the pipeline source as input.\n"); + + EXTENSION_ADD_PROPERTY_TYPE(Filter, + (nullptr), + "Pipeline", + App::Prop_Transient, + "List of all filters"); + + Mode.setEnums(ModeEnums); +} + +FemPostGroupExtension::~FemPostGroupExtension() { + +} + + +void FemPostGroupExtension::initExtension(App::ExtensionContainer* obj) +{ + + if (!obj->isDerivedFrom(Fem::FemPostObject::getClassTypeId())) { + throw Base::RuntimeError("FemPostGroupExtension can only be applied to FemPostObject"); + } + + App::GroupExtension::initExtension(obj); +} + +void FemPostGroupExtension::extensionOnChanged(const App::Property* p) +{ + if(p == &Group) { + if (!m_blockChange) { + // make sure filter property holds all our filters (and non filters are in front) + std::vector filters; + for(auto obj : Group.getValues()) { + if(obj->isDerivedFrom(FemPostFilter::getClassTypeId())) { + filters.push_back(obj); + } + } + + // sort the group, so that non filter objects are always on top + auto objs = Group.getValues(); + std::sort( objs.begin( ), objs.end( ), [ ]( const App::DocumentObject* lhs, const App::DocumentObject* rhs ){ + + int l = lhs->isDerivedFrom(FemPostFilter::getClassTypeId()) ? 0 : 1; + int r = rhs->isDerivedFrom(FemPostFilter::getClassTypeId()) ? 0 : 1; + return r filters; + for (auto obj : Filter.getValues()) { + if (obj->isDerivedFrom(Fem::FemPostFilter::getClassTypeId())) { + filters.push_back(obj); + } + } + + //collect all other items that are not filters + std::vector objs; + for (auto obj : Group.getValues()) { + if (!obj->isDerivedFrom(Fem::FemPostFilter::getClassTypeId())) { + objs.push_back(obj); + } + } + + // set the properties correctly + m_blockChange = true; + objs.insert( objs.end(), filters.begin(), filters.end() ); + Filter.setValue(filters); + Group.setValue(objs); + m_blockChange = false; + } + } + GroupExtension::extensionOnChanged(p); +} + +void FemPostGroupExtension::onExtendedUnsetupObject() +{ + // remove all children! + auto document = getExtendedObject()->getDocument(); + for (const auto& obj : Group.getValues()) { + document->removeObject(obj->getNameInDocument()); + } +} + +void FemPostGroupExtension::recomputeChildren() +{ + for (const auto& obj : Group.getValues()) { + obj->touch(); + } +} + +FemPostObject* FemPostGroupExtension::getLastPostObject() +{ + + if (Group.getValues().empty()) { + return static_cast(this->getExtendedObject()); + } + + return static_cast(Group.getValues().back()); +} + +bool FemPostGroupExtension::holdsPostObject(FemPostObject* obj) +{ + + std::vector::const_iterator it = Group.getValues().begin(); + for (; it != Group.getValues().end(); ++it) { + + if (*it == obj) { + return true; + } + } + return false; +} diff --git a/src/Mod/Fem/App/FemPostGroupExtension.h b/src/Mod/Fem/App/FemPostGroupExtension.h new file mode 100644 index 0000000000..311f2981c3 --- /dev/null +++ b/src/Mod/Fem/App/FemPostGroupExtension.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (c) 2024 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_FemPostGroup_H +#define Fem_FemPostGroup_H + +#include "Base/Unit.h" +#include "App/GroupExtension.h" +#include "FemPostFilter.h" + +namespace Fem +{ + +// object grouping FEM filters and building the structure of the pipeline +class FemExport FemPostGroupExtension : public App::GroupExtension { + + using inherited = App::GroupExtension; + EXTENSION_PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostGroupExtension); + +public: + /// Constructor + FemPostGroupExtension(); + ~FemPostGroupExtension() override; + + void initExtension(App::ExtensionContainer* obj) override; + + App::PropertyEnumeration Mode; + App::PropertyLinkList Filter; + + // Pipeline handling + virtual void filterChanged(FemPostFilter*) {}; // settings change in filter + virtual void filterPipelineChanged(FemPostFilter*) {}; // pipeline change in filter + virtual void recomputeChildren(); + virtual FemPostObject* getLastPostObject(); + virtual bool holdsPostObject(FemPostObject* obj); + +protected: + void extensionOnChanged(const App::Property* p) override; + void onExtendedUnsetupObject() override; + +private: + bool m_blockChange = false; + static const char* ModeEnums[]; +}; + +} // namespace Fem + + +#endif // Fem_FemPostGroup_H diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index a675f86a09..cebdd65aef 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -151,7 +151,7 @@ int FemFrameSourceAlgorithm::RequestInformation(vtkInformation*reqInfo, vtkInfor return 1; } -int FemFrameSourceAlgorithm::RequestData(vtkInformation* reqInfo, vtkInformationVector** inVector, vtkInformationVector* outVector) +int FemFrameSourceAlgorithm::RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outVector) { std::stringstream strstm; @@ -192,34 +192,19 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation* reqInfo, vtkInformation } +PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostPipeline, Fem::FemPostObject) -PROPERTY_SOURCE(Fem::FemPostPipeline, Fem::FemPostObject) -const char* FemPostPipeline::ModeEnums[] = {"Serial", "Parallel", nullptr}; - -FemPostPipeline::FemPostPipeline() : Fem::FemPostObject(), App::GroupExtension() +FemPostPipeline::FemPostPipeline() : FemPostObject(), FemPostGroupExtension() { - GroupExtension::initExtension(this); - ADD_PROPERTY_TYPE(Functions, - (nullptr), - "Pipeline", - App::Prop_Hidden, - "The function provider which groups all pipeline functions"); - ADD_PROPERTY_TYPE(Mode, - (long(0)), - "Pipeline", - App::Prop_None, - "Selects the pipeline data transition mode.\n" - "In serial, every filter gets the output of the previous one as input.\n" - "In parallel, every filter gets the pipeline source as input.\n"); + FemPostGroupExtension::initExtension(this); + ADD_PROPERTY_TYPE(Frame, (long(0)), "Pipeline", App::Prop_None, "The frame used to calculate the data in the pipeline processing (read only, set via pipeline object)."); - Mode.setEnums(ModeEnums); - // create our source algorithm m_source_algorithm = vtkSmartPointer::New(); } @@ -249,6 +234,17 @@ vtkDataSet* FemPostPipeline::getDataSet() { return nullptr; } +Fem::FemPostFunctionProvider* FemPostPipeline::getFunctionProvider() { + + // see if we have one + for (auto obj : Group.getValues()){ + if(obj->isDerivedFrom(FemPostFunctionProvider::getClassTypeId())) { + return static_cast(obj); + } + } + return nullptr; +} + bool FemPostPipeline::canRead(Base::FileInfo File) { @@ -305,6 +301,7 @@ void FemPostPipeline::onChanged(const Property* prop) * of our child filters correctly according to the new settings */ + FemPostObject::onChanged(prop); // use the correct data as source if (prop == &Data) { @@ -360,10 +357,10 @@ void FemPostPipeline::onChanged(const Property* prop) // connect all filters correctly to the source - if (prop == &Group || prop == &Mode) { + if (prop == &Filter || prop == &Mode) { // we check if all connections are right and add new ones if needed - std::vector objs = Group.getValues(); + std::vector objs = Filter.getValues(); if (objs.empty()) { return; @@ -398,9 +395,6 @@ void FemPostPipeline::onChanged(const Property* prop) filter = nextFilter; }; } - - FemPostObject::onChanged(prop); - } void FemPostPipeline::filterChanged(FemPostFilter* filter) @@ -428,7 +422,7 @@ void FemPostPipeline::filterChanged(FemPostFilter* filter) } } -void FemPostPipeline::pipelineChanged(FemPostFilter* filter) { +void FemPostPipeline::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 @@ -441,7 +435,7 @@ void FemPostPipeline::recomputeChildren() double frame = 0; auto frames = getFrameValues(); if (!frames.empty() && - Frame.getValue() < frames.size()) { + Frame.getValue() < long(frames.size())) { frame = frames[Frame.getValue()]; } @@ -455,30 +449,6 @@ void FemPostPipeline::recomputeChildren() } } -FemPostObject* FemPostPipeline::getLastPostObject() -{ - - if (Group.getValues().empty()) { - return this; - } - - return static_cast(Group.getValues().back()); -} - -bool FemPostPipeline::holdsPostObject(FemPostObject* obj) -{ - - std::vector::const_iterator it = Group.getValues().begin(); - for (; it != Group.getValues().end(); ++it) { - - if (*it == obj) { - return true; - } - } - return false; -} - - bool FemPostPipeline::hasFrames() { diff --git a/src/Mod/Fem/App/FemPostPipeline.h b/src/Mod/Fem/App/FemPostPipeline.h index 19f6c3628f..ba05b08d53 100644 --- a/src/Mod/Fem/App/FemPostPipeline.h +++ b/src/Mod/Fem/App/FemPostPipeline.h @@ -23,12 +23,8 @@ #ifndef Fem_FemPostPipeline_H #define Fem_FemPostPipeline_H -<<<<<<< HEAD - -======= #include "Base/Unit.h" ->>>>>>> 782848c556 (FEM: Make multistep work for eigenmodes) -#include "App/GroupExtension.h" +#include "FemPostGroupExtension.h" #include "FemPostFilter.h" #include "FemPostFunction.h" @@ -66,7 +62,7 @@ protected: }; -class FemExport FemPostPipeline: public Fem::FemPostObject, public App::GroupExtension +class FemExport FemPostPipeline: public Fem::FemPostObject, public Fem::FemPostGroupExtension { PROPERTY_HEADER_WITH_EXTENSIONS(Fem::FemPostPipeline); @@ -75,12 +71,11 @@ public: FemPostPipeline(); ~FemPostPipeline() override; - App::PropertyLink Functions; - App::PropertyEnumeration Mode; App::PropertyEnumeration Frame; virtual vtkDataSet* getDataSet() override; + Fem::FemPostFunctionProvider* getFunctionProvider(); short mustExecute() const override; PyObject* getPyObject() override; @@ -99,12 +94,10 @@ public: void load(FemResultObject* res); void load(std::vector res, std::vector values, Base::Unit unit, std::string frame_type); - // Pipeline handling - void filterChanged(FemPostFilter* filter); - void pipelineChanged(FemPostFilter* filter); - void recomputeChildren(); - FemPostObject* getLastPostObject(); - bool holdsPostObject(FemPostObject* obj); + // Group pipeline handling + void filterChanged(FemPostFilter* filter) override; + void filterPipelineChanged(FemPostFilter* filter) override; + void recomputeChildren() override; // frame handling bool hasFrames(); @@ -117,7 +110,6 @@ protected: void onChanged(const App::Property* prop) override; private: - static const char* ModeEnums[]; App::Enumeration m_frameEnum; vtkSmartPointer m_source_algorithm; diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index b4cddba94c..292c43bb13 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -2479,23 +2479,17 @@ void CmdFemPostFunctions::activated(int iMsg) openCommand(QT_TRANSLATE_NOOP("Command", "Create function")); // check if the pipeline has a filter provider and add one if needed - Fem::FemPostFunctionProvider* provider; - if (!pipeline->Functions.getValue() - || pipeline->Functions.getValue()->getTypeId() - != Fem::FemPostFunctionProvider::getClassTypeId()) { + Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider(); + if (!provider) { std::string FuncName = getUniqueObjectName("Functions"); doCommand(Doc, "App.ActiveDocument.addObject('Fem::FemPostFunctionProvider','%s')", FuncName.c_str()); doCommand(Doc, - "App.ActiveDocument.%s.Functions = App.ActiveDocument.%s", + "App.ActiveDocument.%s.addObject(App.ActiveDocument.%s)", pipeline->getNameInDocument(), FuncName.c_str()); - provider = static_cast( - getDocument()->getObject(FuncName.c_str())); - } - else { - provider = static_cast(pipeline->Functions.getValue()); + provider = pipeline->getFunctionProvider(); } // build the object @@ -2504,10 +2498,9 @@ void CmdFemPostFunctions::activated(int iMsg) "App.activeDocument().addObject('Fem::FemPost%sFunction','%s')", name.c_str(), FeatName.c_str()); - doCommand(Doc, "__list__ = App.ActiveDocument.%s.Functions", provider->getNameInDocument()); - doCommand(Doc, "__list__.append(App.ActiveDocument.%s)", FeatName.c_str()); - doCommand(Doc, "App.ActiveDocument.%s.Functions = __list__", provider->getNameInDocument()); - doCommand(Doc, "del __list__"); + doCommand(Doc, "App.ActiveDocument.%s.addObject(App.ActiveDocument.%s)", + provider->getNameInDocument(), + FeatName.c_str()); // set the default values, for this get the bounding box vtkBoundingBox box = pipeline->getBoundingBox(); diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.cpp b/src/Mod/Fem/Gui/TaskPostBoxes.cpp index e1d74124f5..eab5d3cd53 100644 --- a/src/Mod/Fem/Gui/TaskPostBoxes.cpp +++ b/src/Mod/Fem/Gui/TaskPostBoxes.cpp @@ -1385,17 +1385,15 @@ void TaskPostClip::collectImplicitFunctions() pipelines = getDocument()->getObjectsOfType(); if (!pipelines.empty()) { Fem::FemPostPipeline* pipeline = pipelines.front(); - if (pipeline->Functions.getValue() - && pipeline->Functions.getValue()->is()) { + Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider(); + if (provider) { ui->FunctionBox->clear(); QStringList items; std::size_t currentItem = 0; App::DocumentObject* currentFunction = getObject()->Function.getValue(); - const std::vector& funcs = - static_cast(pipeline->Functions.getValue()) - ->Functions.getValues(); + const std::vector& funcs = provider->Group.getValues(); for (std::size_t i = 0; i < funcs.size(); ++i) { items.push_back(QString::fromLatin1(funcs[i]->getNameInDocument())); if (currentFunction == funcs[i]) { @@ -1435,12 +1433,10 @@ void TaskPostClip::onFunctionBoxCurrentIndexChanged(int idx) pipelines = getDocument()->getObjectsOfType(); if (!pipelines.empty()) { Fem::FemPostPipeline* pipeline = pipelines.front(); - if (pipeline->Functions.getValue() - && pipeline->Functions.getValue()->is()) { + Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider(); + if (provider) { - const std::vector& funcs = - static_cast(pipeline->Functions.getValue()) - ->Functions.getValues(); + const std::vector& funcs = provider->Group.getValues(); if (idx >= 0) { getObject()->Function.setValue(funcs[idx]); } @@ -1695,17 +1691,15 @@ void TaskPostCut::collectImplicitFunctions() pipelines = getDocument()->getObjectsOfType(); if (!pipelines.empty()) { Fem::FemPostPipeline* pipeline = pipelines.front(); - if (pipeline->Functions.getValue() - && pipeline->Functions.getValue()->is()) { + Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider(); + if (provider) { ui->FunctionBox->clear(); QStringList items; std::size_t currentItem = 0; App::DocumentObject* currentFunction = getObject()->Function.getValue(); - const std::vector& funcs = - static_cast(pipeline->Functions.getValue()) - ->Functions.getValues(); + const std::vector& funcs = provider->Group.getValues(); for (std::size_t i = 0; i < funcs.size(); ++i) { items.push_back(QString::fromLatin1(funcs[i]->getNameInDocument())); if (currentFunction == funcs[i]) { @@ -1745,12 +1739,10 @@ void TaskPostCut::onFunctionBoxCurrentIndexChanged(int idx) pipelines = getDocument()->getObjectsOfType(); if (!pipelines.empty()) { Fem::FemPostPipeline* pipeline = pipelines.front(); - if (pipeline->Functions.getValue() - && pipeline->Functions.getValue()->is()) { + Fem::FemPostFunctionProvider* provider = pipeline->getFunctionProvider(); + if (provider) { - const std::vector& funcs = - static_cast(pipeline->Functions.getValue()) - ->Functions.getValues(); + const std::vector& funcs = provider->Group.getValues(); if (idx >= 0) { getObject()->Function.setValue(funcs[idx]); } diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp index 866a64d3dc..dd827fd215 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp @@ -92,16 +92,6 @@ ViewProviderFemPostFunctionProvider::ViewProviderFemPostFunctionProvider() = def ViewProviderFemPostFunctionProvider::~ViewProviderFemPostFunctionProvider() = default; -std::vector ViewProviderFemPostFunctionProvider::claimChildren() const -{ - return getObject()->Functions.getValues(); -} - -std::vector ViewProviderFemPostFunctionProvider::claimChildren3D() const -{ - return claimChildren(); -} - void ViewProviderFemPostFunctionProvider::onChanged(const App::Property* prop) { Gui::ViewProviderDocumentObject::onChanged(prop); @@ -113,7 +103,7 @@ void ViewProviderFemPostFunctionProvider::updateData(const App::Property* prop) { Gui::ViewProviderDocumentObject::updateData(prop); Fem::FemPostFunctionProvider* obj = getObject(); - if (prop == &obj->Functions) { + if (prop == &obj->Group) { updateSize(); } } @@ -139,8 +129,9 @@ bool ViewProviderFemPostFunctionProvider::onDelete(const std::vectorgetDocument(), - "functions list"); + this->getDocument(), + "functions list"); + } bool ViewProviderFemPostFunctionProvider::canDelete(App::DocumentObject* obj) const diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h index c6df9edd0c..f95fae3031 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include @@ -93,7 +93,7 @@ private: boost::signals2::scoped_connection m_connection; }; -class FemGuiExport ViewProviderFemPostFunctionProvider: public Gui::ViewProviderDocumentObject +class FemGuiExport ViewProviderFemPostFunctionProvider: public Gui::ViewProviderDocumentObjectGroup { PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemPostFunctionProvider); @@ -111,8 +111,6 @@ public: bool canDelete(App::DocumentObject* obj) const override; protected: - std::vector claimChildren() const override; - std::vector claimChildren3D() const override; void onChanged(const App::Property* prop) override; void updateData(const App::Property*) override; diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 63d2c24966..5e5c620d16 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -1067,7 +1067,15 @@ bool ViewProviderFemPostObject::onDelete(const std::vector&) { // warn the user if the object has unselected children auto objs = claimChildren(); - return ViewProviderFemAnalysis::checkSelectedChildren(objs, this->getDocument(), "pipeline"); + if (!ViewProviderFemAnalysis::checkSelectedChildren(objs, this->getDocument(), "pipeline")) { + return false; + }; + + // delete all subelements + for(auto obj : objs) { + getObject()->getDocument()->removeObject(obj->getNameInDocument()); + } + return true; } bool ViewProviderFemPostObject::canDelete(App::DocumentObject* obj) const diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp index 83ee439429..36a17530d8 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp @@ -52,59 +52,34 @@ ViewProviderFemPostPipeline::ViewProviderFemPostPipeline() ViewProviderFemPostPipeline::~ViewProviderFemPostPipeline() = default; -std::vector ViewProviderFemPostPipeline::claimChildren() const -{ - - Fem::FemPostPipeline* pipeline = getObject(); - std::vector children = FemGui::ViewProviderFemPostObject::claimChildren(); - - if (pipeline->Functions.getValue()) { - children.insert(children.begin(), pipeline->Functions.getValue()); - } - - return children; -} - -std::vector ViewProviderFemPostPipeline::claimChildren3D() const -{ - return claimChildren(); -} void ViewProviderFemPostPipeline::updateData(const App::Property* prop) { FemGui::ViewProviderFemPostObject::updateData(prop); -<<<<<<< HEAD + Fem::FemPostPipeline* pipeline = getObject(); -======= - Fem::FemPostPipeline* pipeline = static_cast(getObject()); - ->>>>>>> 782848c556 (FEM: Make multistep work for eigenmodes) - if (prop == &pipeline->Functions) { - updateFunctionSize(); - } - if (prop == &pipeline->Frame) { // Frame is pipeline property, not post object, parent updateData does not catch it for update updateVtk(); } + else if ((prop == &pipeline->Data) || + (prop == &pipeline->Group)) { + updateFunctionSize(); + } } void ViewProviderFemPostPipeline::updateFunctionSize() { - // we need to get the bounding box and set the function provider size Fem::FemPostPipeline* obj = getObject(); - - if (!obj->Functions.getValue() - || !obj->Functions.getValue()->isDerivedFrom( - Fem::FemPostFunctionProvider::getClassTypeId())) { + Fem::FemPostFunctionProvider* fp = obj->getFunctionProvider(); + if (!fp) { return; } - // get the function provider FemGui::ViewProviderFemPostFunctionProvider* vp = static_cast( - Gui::Application::Instance->getViewProvider(obj->Functions.getValue())); + Gui::Application::Instance->getViewProvider(fp)); if (obj->Data.getValue() && obj->Data.getValue()->IsA("vtkDataSet")) { vtkBoundingBox box = obj->getBoundingBox(); diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h index 2ca65b2a8d..2c5d5f77b5 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h @@ -43,8 +43,6 @@ public: ViewProviderFemPostPipeline(); ~ViewProviderFemPostPipeline() override; - std::vector claimChildren() const override; - std::vector claimChildren3D() const override; void updateData(const App::Property* prop) override; bool onDelete(const std::vector& objs) override; void onSelectionChanged(const Gui::SelectionChanges& sel) override;