From 696ce87ccb8fed24ff4451f3a1d1235cd0d89a53 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 11 Jun 2019 12:37:13 +0300 Subject: [PATCH] Several improvement of the filters functionality, correct work with shapes types in the filters and arguments. --- .../FeaturesPlugin_Validators.cpp | 2 +- src/FiltersPlugin/FiltersPlugin_Selection.cpp | 37 +++++++++++++++ src/FiltersPlugin/FiltersPlugin_Selection.h | 26 +++++++--- src/GeomAPI/GeomAPI_Shape.cpp | 16 +++---- src/Model/Model_AttributeSelectionList.cpp | 47 +++++++++++++++++++ src/Model/Model_AttributeSelectionList.h | 6 +++ src/Model/Model_Document.h | 1 + src/Model/Model_Filter.cpp | 12 +++++ .../ModelAPI_AttributeSelectionList.h | 9 ++-- src/ModelAPI/ModelAPI_Filter.h | 11 ++++- .../ModuleBase_WidgetSelectionFilter.cpp | 7 ++- 11 files changed, 152 insertions(+), 22 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp index 30993f225..d7755548e 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Validators.cpp @@ -30,7 +30,7 @@ #include #include -#include > +#include #include #include #include diff --git a/src/FiltersPlugin/FiltersPlugin_Selection.cpp b/src/FiltersPlugin/FiltersPlugin_Selection.cpp index fefedb084..4b656d847 100644 --- a/src/FiltersPlugin/FiltersPlugin_Selection.cpp +++ b/src/FiltersPlugin/FiltersPlugin_Selection.cpp @@ -21,6 +21,7 @@ #include #include +#include // identifier of the reverse flag of a filter static const std::string kReverseAttrID(""); @@ -79,3 +80,39 @@ std::list FiltersPlugin_Selection::filterArgs(const std::string th data()->attributesOfGroup(theFilterID, aList); return aList; } + +void FiltersPlugin_Selection::setAttribute(const AttributePtr& theAttr) +{ + if (myBase != theAttr) { // clear all filters if the attribute is changed or defined a new + std::list aFilters; + data()->allGroups(aFilters); + std::list::iterator aFIter = aFilters.begin(); + for(; aFIter != aFilters.end(); aFIter++) { + data()->removeAttributes(*aFIter); + } + } + myBase = theAttr; + if (myBase.get()) { // check that the type of sub-elements is supported by all existing filters + std::shared_ptr aSelList = + std::dynamic_pointer_cast(theAttr); + if (aSelList.get()) { + std::string aStrType = aSelList->selectionType(); + GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(aStrType); + std::list aFilters; + data()->allGroups(aFilters); + ModelAPI_FiltersFactory* aFactory = ModelAPI_Session::get()->filters(); + std::list::iterator aFIter = aFilters.begin(); + for(; aFIter != aFilters.end(); aFIter++) { + FilterPtr aFilter = aFactory->filter(*aFIter); + if (aFilter.get() && !aFilter->isSupported(aType)) { + data()->removeAttributes(*aFIter); + } + } + } + } +} + +const AttributePtr& FiltersPlugin_Selection::baseAttribute() const +{ + return myBase; +} diff --git a/src/FiltersPlugin/FiltersPlugin_Selection.h b/src/FiltersPlugin/FiltersPlugin_Selection.h index 46a880891..0e68ac9bb 100644 --- a/src/FiltersPlugin/FiltersPlugin_Selection.h +++ b/src/FiltersPlugin/FiltersPlugin_Selection.h @@ -60,22 +60,36 @@ public: // methods related to the filters management /// Adds a filter to the feature. Also initializes arguments of this filter. - FILTERS_EXPORT virtual void addFilter(const std::string theFilterID); + FILTERS_EXPORT virtual void addFilter(const std::string theFilterID) override; /// Removes an existing filter from the feature. - FILTERS_EXPORT virtual void removeFilter(const std::string theFilterID); + FILTERS_EXPORT virtual void removeFilter(const std::string theFilterID) override; /// Returns the list of existing filters in the feature. - FILTERS_EXPORT virtual std::list filters() const; + FILTERS_EXPORT virtual std::list filters() const override; /// Stores the reversed flag for the filter. - FILTERS_EXPORT virtual void setReversed(const std::string theFilterID, const bool theReversed); + FILTERS_EXPORT virtual void setReversed + (const std::string theFilterID, const bool theReversed) override; /// Returns the reversed flag value for the filter. - FILTERS_EXPORT virtual bool isReversed(const std::string theFilterID); + FILTERS_EXPORT virtual bool isReversed(const std::string theFilterID) override; /// Returns the ordered list of attributes related to the filter. - FILTERS_EXPORT virtual std::list filterArgs(const std::string theFilterID) const; + FILTERS_EXPORT virtual std::list + filterArgs(const std::string theFilterID) const override; + + /// Sets the attribute (not-persistent field) that contains this filters feature. + /// The filter feature may make synchronization by this method call. + FILTERS_EXPORT virtual void setAttribute(const AttributePtr& theAttr) override; + + /// Returns the attribute (not-persistent field) that contains this filters feature. + FILTERS_EXPORT virtual const AttributePtr& baseAttribute() const override; + +protected: + + AttributePtr myBase; ///< the attribute related to this filter + }; #endif diff --git a/src/GeomAPI/GeomAPI_Shape.cpp b/src/GeomAPI/GeomAPI_Shape.cpp index 3b0709eac..98bfdcf9e 100644 --- a/src/GeomAPI/GeomAPI_Shape.cpp +++ b/src/GeomAPI/GeomAPI_Shape.cpp @@ -460,21 +460,21 @@ GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeType() const GeomAPI_Shape::ShapeType GeomAPI_Shape::shapeTypeByStr(std::string theType) { std::transform(theType.begin(), theType.end(), theType.begin(), ::toupper); - if (theType == "COMPOUND") + if (theType == "COMPOUND" || theType == "COMPOUNDS") return COMPOUND; - if (theType == "COMPSOLID") + if (theType == "COMPSOLID" || theType == "COMPSOLIDS") return COMPSOLID; - if (theType == "SOLID") + if (theType == "SOLID" || theType == "SOLIDS") return SOLID; - if (theType == "SHELL") + if (theType == "SHELL" || theType == "SHELLS") return SHELL; - if (theType == "FACE") + if (theType == "FACE" || theType == "FACES") return FACE; - if (theType == "WIRE") + if (theType == "WIRE" || theType == "WIRES") return WIRE; - if (theType == "EDGE") + if (theType == "EDGE" || theType == "EDGES") return EDGE; - if (theType == "VERTEX") + if (theType == "VERTEX" || theType == "VERTICES") return VERTEX; return SHAPE; // default } diff --git a/src/Model/Model_AttributeSelectionList.cpp b/src/Model/Model_AttributeSelectionList.cpp index 0ef7aeff3..50b04d3c3 100644 --- a/src/Model/Model_AttributeSelectionList.cpp +++ b/src/Model/Model_AttributeSelectionList.cpp @@ -22,6 +22,7 @@ #include "Model_Application.h" #include "Model_Events.h" #include "Model_Data.h" +#include "Model_Objects.h" #include #include @@ -32,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +48,10 @@ /// topology" flag enabled static const Standard_GUID kIS_GEOMETRICAL_SELECTION("f16987b6-e6c8-435c-99fa-03a7e0b06e83"); +/// GUID for TDataStd_ReferenceList attribute that refers the selection filters feature +static const Standard_GUID kSELECTION_FILTERS_REF("ea5b1dbf-a740-4a0b-a1b2-3c3c756e691a"); + + void Model_AttributeSelectionList::append( const ObjectPtr& theContext, const std::shared_ptr& theSubShape, const bool theTemporarily) @@ -480,3 +486,44 @@ void Model_AttributeSelectionList::setGeometricalSelection(const bool theIsGeome myCash.clear(); // empty list as indicator that cash is not used owner()->data()->sendAttributeUpdated(this); } + +FiltersFeaturePtr Model_AttributeSelectionList::filters() const +{ + Handle(TDataStd_ReferenceList) aRef; + if (myLab.FindAttribute(kSELECTION_FILTERS_REF, aRef) && !aRef->IsEmpty()) { + if (owner().get()) { + std::shared_ptr aDoc = std::dynamic_pointer_cast( + owner()->document()); + if (aDoc) { + const TDF_Label& aRefLab = aRef->First(); + if (!aRefLab.IsNull()) { // it may happen with old document, issue #285 + ObjectPtr anObj = aDoc->objects()->object(aRefLab); + FiltersFeaturePtr aFeat = std::dynamic_pointer_cast(anObj); + if (aFeat.get()) { + aFeat->setAttribute(owner()->data()->attribute(id())); + return aFeat; + } + } + } + } + } + return FiltersFeaturePtr(); // null pointer if nothing is defined +} + +void Model_AttributeSelectionList::setFilters(FiltersFeaturePtr theFeature) +{ + Handle(TDataStd_ReferenceList) aRef = TDataStd_ReferenceList::Set(myLab, kSELECTION_FILTERS_REF); + if (theFeature.get()) { + std::shared_ptr aData = std::dynamic_pointer_cast(theFeature->data()); + if (aData->isValid()) { + TDF_Label anObjLab = aData->label().Father(); // object label + if (!aRef->IsEmpty()) + aRef->Clear(); + aRef->Append(anObjLab); + theFeature->setAttribute(owner()->data()->attribute(id())); + return; + } + } + // remove attribute if something is wrong + myLab.ForgetAttribute(TDataStd_ReferenceList::GetID()); +} diff --git a/src/Model/Model_AttributeSelectionList.h b/src/Model/Model_AttributeSelectionList.h index 839cd431d..ca797e623 100644 --- a/src/Model/Model_AttributeSelectionList.h +++ b/src/Model/Model_AttributeSelectionList.h @@ -115,6 +115,12 @@ public: /// Returns true if is geometrical selection. MODEL_EXPORT virtual bool isGeometricalSelection() const override; + /// Returns a selection filters feature if it is defined for this selection list + MODEL_EXPORT virtual FiltersFeaturePtr filters() const; + + /// Sets a selection filters feature if it is defined for this selection list + MODEL_EXPORT virtual void setFilters(FiltersFeaturePtr theFeature); + protected: /// Objects are created for features automatically MODEL_EXPORT Model_AttributeSelectionList(TDF_Label& theLabel); diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index a61cc6ad4..72a570738 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -395,6 +395,7 @@ class Model_Document : public ModelAPI_Document friend class Model_AttributeRefList; friend class Model_AttributeRefAttrList; friend class Model_AttributeSelection; + friend class Model_AttributeSelectionList; friend class Model_ResultPart; friend class Model_ResultBody; friend class Model_ResultConstruction; diff --git a/src/Model/Model_Filter.cpp b/src/Model/Model_Filter.cpp index 14905d040..549bed4da 100644 --- a/src/Model/Model_Filter.cpp +++ b/src/Model/Model_Filter.cpp @@ -20,6 +20,7 @@ #include "Model_Filter.h" #include "ModelAPI_AttributeBoolean.h" +#include "ModelAPI_AttributeSelectionList.h" #include @@ -41,6 +42,17 @@ struct FilterArgs { bool Model_FiltersFactory::isValid(FeaturePtr theFiltersFeature, GeomShapePtr theShape) { + // check that the shape type corresponds to the attribute list type + AttributePtr aBase = + std::dynamic_pointer_cast(theFiltersFeature)->baseAttribute(); + if (aBase.get()) { + std::shared_ptr aList = + std::dynamic_pointer_cast(aBase); + std::string aStrType = aList->selectionType(); + GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(aStrType); + if (theShape->shapeType() != aType) + return false; + } // prepare all filters args ModelAPI_FiltersArgs anArgs; std::list aFilters; /// all filters and the reverse values diff --git a/src/ModelAPI/ModelAPI_AttributeSelectionList.h b/src/ModelAPI/ModelAPI_AttributeSelectionList.h index 5c304db25..4280f613a 100644 --- a/src/ModelAPI/ModelAPI_AttributeSelectionList.h +++ b/src/ModelAPI/ModelAPI_AttributeSelectionList.h @@ -115,15 +115,16 @@ class ModelAPI_AttributeSelectionList : public ModelAPI_Attribute /// To virtually destroy the fields of successors MODELAPI_EXPORT virtual ~ModelAPI_AttributeSelectionList(); - MODELAPI_EXPORT FiltersFeaturePtr filters() const { return myFilters; } - MODELAPI_EXPORT void setFilters(FiltersFeaturePtr theFeature) { myFilters = theFeature; } + /// Returns a selection filters feature if it is defined for this selection list + MODELAPI_EXPORT virtual FiltersFeaturePtr filters() const = 0; + + /// Sets a selection filters feature if it is defined for this selection list + MODELAPI_EXPORT virtual void setFilters(FiltersFeaturePtr theFeature) = 0; protected: /// Objects are created for features automatically MODELAPI_EXPORT ModelAPI_AttributeSelectionList(); -protected: - FiltersFeaturePtr myFilters; }; //! Pointer on double attribute diff --git a/src/ModelAPI/ModelAPI_Filter.h b/src/ModelAPI/ModelAPI_Filter.h index a900548bf..08bb82d1e 100644 --- a/src/ModelAPI/ModelAPI_Filter.h +++ b/src/ModelAPI/ModelAPI_Filter.h @@ -57,6 +57,13 @@ public: /// Returns the ordered list of attributes related to the filter. virtual std::list filterArgs(const std::string theFilterID) const = 0; + + /// Sets the attribute (not-persistent field) that contains this filters feature. + /// The filter feature may make synchronization by this method call. + virtual void setAttribute(const AttributePtr& theAttr) = 0; + + /// Returns the attribute (not-persistent field) that contains this filters feature. + virtual const AttributePtr& baseAttribute() const = 0; }; typedef std::shared_ptr FiltersFeaturePtr; @@ -93,7 +100,9 @@ public: /// adds an attribute of the filter std::shared_ptr initAttribute( const std::string& theID, const std::string theAttrType) { - return myFeature->data()->addFloatingAttribute(theID, theAttrType, myCurrentFilter); + AttributePtr aR = myFeature->data()->addFloatingAttribute(theID, theAttrType, myCurrentFilter); + aR->setIsArgument(false); // to avoid parametric update + return aR; } }; diff --git a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp index 4146656b0..faf52833c 100644 --- a/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp +++ b/src/ModuleBase/ModuleBase_WidgetSelectionFilter.cpp @@ -450,13 +450,16 @@ void ModuleBase_WidgetSelectionFilter::onSelect() GeomShapePtr aShape = aBody->shape(); std::list aSubShapes = aShape->subShapes((GeomAPI_Shape::ShapeType)mySelectionType); + TopTools_MapOfShape alreadyThere; std::list::const_iterator aShapesIt; for (aShapesIt = aSubShapes.cbegin(); aShapesIt != aSubShapes.cend(); aShapesIt++) { GeomShapePtr aShape = (*aShapesIt); - SessionPtr aSession = ModelAPI_Session::get(); + TopoDS_Shape aTShape = aShape->impl(); + if (!alreadyThere.Add(aTShape)) + continue; + static SessionPtr aSession = ModelAPI_Session::get(); bool isValid = aSession->filters()->isValid(myFeature, aShape); if (isValid) { - TopoDS_Shape aTShape = aShape->impl(); aBuilder.Add(aComp, aTShape); ModuleBase_ViewerPrsPtr aValue(new ModuleBase_ViewerPrs(aObj, aShape)); myValues.append(aValue); -- 2.39.2