From 782ddee7ec183e10378487f5bdd27d4b00124f81 Mon Sep 17 00:00:00 2001 From: mpv Date: Tue, 1 Nov 2016 17:45:28 +0300 Subject: [PATCH] Multiple fixes (issue #1757 , issue #1799 , issue #1842 , etc): - don't store names of results in selection to avoid problem on rename of results - update selection of bodies after something is added in the middle of history that changes the argument - recompute selection context of the group if it is moved donw --- .../FeaturesPlugin_Partition.cpp | 40 ++-- src/FeaturesPlugin/FeaturesPlugin_Partition.h | 3 +- src/Model/Model_AttributeSelection.cpp | 205 +++++++++++++++--- src/Model/Model_AttributeSelection.h | 3 + src/Model/Model_AttributeSelectionList.cpp | 1 + src/Model/Model_Data.h | 1 + src/Model/Model_Objects.cpp | 4 +- src/Model/Model_Objects.h | 1 + src/Model/Model_SelectionNaming.cpp | 70 +++--- src/Model/Model_SelectionNaming.h | 2 +- src/Model/Model_Update.cpp | 36 +++ src/Model/Model_Update.h | 5 + src/ModelAPI/ModelAPI_Events.h | 20 +- src/ModelAPI/ModelAPI_Feature.cpp | 6 + src/ModelAPI/ModelAPI_Result.cpp | 2 +- 15 files changed, 302 insertions(+), 97 deletions(-) diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp index c9869f124..f1ec8123b 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.cpp @@ -71,7 +71,8 @@ void FeaturesPlugin_Partition::execute() return; } - std::list > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0); + std::list > aBoundingPoints = + GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0); // Resize planes. ListOfShape aTools; @@ -108,14 +109,13 @@ void FeaturesPlugin_Partition::execute() GeomShapePtr aResultShape = aPartitionAlgo->shape(); int aResultIndex = 0; - anObjects.insert(anObjects.end(), aPlanes.begin(), aPlanes.end()); if(aResultShape->shapeType() == GeomAPI_Shape::COMPOUND) { for(GeomAPI_ShapeIterator anIt(aResultShape); anIt.more(); anIt.next()) { - storeResult(anObjects, anIt.current(), aMakeShapeList, aResultIndex); + storeResult(anObjects, aPlanes, anIt.current(), aMakeShapeList, aResultIndex); ++aResultIndex; } } else { - storeResult(anObjects, aResultShape, aMakeShapeList, aResultIndex); + storeResult(anObjects, aPlanes, aResultShape, aMakeShapeList, aResultIndex); ++aResultIndex; } @@ -124,24 +124,29 @@ void FeaturesPlugin_Partition::execute() } //================================================================================================= -void FeaturesPlugin_Partition::storeResult(const ListOfShape& theObjects, - const GeomShapePtr theResultShape, - const std::shared_ptr theMakeShape, - const int theIndex) +void FeaturesPlugin_Partition::storeResult( + ListOfShape& theObjects, ListOfShape& thePlanes, + const GeomShapePtr theResultShape, + const std::shared_ptr theMakeShape, + const int theIndex) { - // Find base. + // Find base. The most complicated is the real modified object (#1799 if box is partitioned by + // two planes the box is the base, not planes, independently on the order in the list). GeomShapePtr aBaseShape; for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { GeomShapePtr anObjectShape = *anIt; - aBaseShape = findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape); - if(!aBaseShape.get()) { - aBaseShape = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape); + GeomShapePtr aCandidate = + findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape); + if(!aCandidate.get()) { + aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape); } - if(!aBaseShape.get()) { - aBaseShape = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape); - } - if(aBaseShape.get()) { - break; + if (!aCandidate.get()) + aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape); + + if(aCandidate.get()) { + if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) { + aBaseShape = aCandidate; + } } } @@ -163,6 +168,7 @@ void FeaturesPlugin_Partition::storeResult(const ListOfShape& theObjects, aResultBody->storeModified(aBaseShape, theResultShape, aSubTag); std::shared_ptr aMapOfSubShapes = theMakeShape->mapOfSubShapes(); + theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end()); int anIndex = 1; for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) { GeomShapePtr aShape = *anIt; diff --git a/src/FeaturesPlugin/FeaturesPlugin_Partition.h b/src/FeaturesPlugin/FeaturesPlugin_Partition.h index ea50c6e0a..ff3d83df5 100755 --- a/src/FeaturesPlugin/FeaturesPlugin_Partition.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Partition.h @@ -51,7 +51,8 @@ public: private: /// Stores result of generation. - void storeResult(const ListOfShape& theObjects, + void storeResult(ListOfShape& theObjects, + ListOfShape& thePlanes, const GeomShapePtr theResultShape, const std::shared_ptr theMakeShape, const int theIndex = 0); diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 64b5ca6de..cf482e2df 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -57,8 +60,6 @@ #include #include #include -#include -#include using namespace std; //#define DEB_NAMING 1 @@ -150,10 +151,10 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext, aBuilder.Generated(theContext->shape()->impl()); std::shared_ptr aMyDoc = std::dynamic_pointer_cast(owner()->document()); - std::string aName = contextName(theContext); + //std::string aName = contextName(theContext); // for selection in different document, add the document name - aMyDoc->addNamingName(aSelLab, aName); - TDataStd_Name::Set(aSelLab, aName.c_str()); + //aMyDoc->addNamingName(aSelLab, aName); + //TDataStd_Name::Set(aSelLab, aName.c_str()); } else { // for sketch the naming is needed in DS BRep_Builder aCompoundBuilder; TopoDS_Compound aComp; @@ -416,9 +417,9 @@ bool Model_AttributeSelection::update() aBuilder.Generated(aContext->shape()->impl()); std::shared_ptr aMyDoc = std::dynamic_pointer_cast(owner()->document()); - std::string aName = contextName(aContext); - aMyDoc->addNamingName(aSelLab, aName); - TDataStd_Name::Set(aSelLab, aName.c_str()); + //std::string aName = contextName(aContext); + //aMyDoc->addNamingName(aSelLab, aName); + //TDataStd_Name::Set(aSelLab, aName.c_str()); } return setInvalidIfFalse(aSelLab, aContext->shape() && !aContext->shape()->isNull()); } @@ -436,10 +437,18 @@ bool Model_AttributeSelection::update() if (aContext->groupName() == ModelAPI_ResultBody::group()) { // body: just a named shape, use selection mechanism from OCCT TNaming_Selector aSelector(aSelLab); - TopoDS_Shape anOldShape = aSelector.NamedShape()->Get(); + TopoDS_Shape anOldShape; + if (!aSelector.NamedShape().IsNull()) { + anOldShape = aSelector.NamedShape()->Get(); + } bool aResult = aSelector.Solve(scope()) == Standard_True; aResult = setInvalidIfFalse(aSelLab, aResult); // must be before sending of updated attribute (1556) - if (!anOldShape.IsEqual(aSelector.NamedShape()->Get())) // send updated if shape is changed + TopoDS_Shape aNewShape; + if (!aSelector.NamedShape().IsNull()) { + aNewShape = aSelector.NamedShape()->Get(); + } + if (anOldShape.IsNull() || aNewShape.IsNull() || + !anOldShape.IsEqual(aSelector.NamedShape()->Get())) // send updated if shape is changed owner()->data()->sendAttributeUpdated(this); return aResult; } else if (aContext->groupName() == ModelAPI_ResultConstruction::group()) { @@ -689,7 +698,7 @@ void Model_AttributeSelection::selectBody( /// -1 is out, 1 is in, 0 is not needed static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, const int theID, const FeaturePtr& theContextFeature, std::shared_ptr theDoc, - std::string theAdditionalName, std::map& theOrientations, + std::map& theOrientations, std::map& theSubNames, // name of sub-elements by ID to be exported instead of indexes Handle(TDataStd_IntPackedMap) theRefs = Handle(TDataStd_IntPackedMap)(), const int theOrientation = 0) @@ -701,23 +710,10 @@ static void registerSubShape(TDF_Label theMainLabel, TopoDS_Shape theShape, TNaming_Builder aBuilder(aLab); aBuilder.Generated(theShape); std::stringstream aName; - // add the part name if the selected object is located in other part - if (theDoc != theContextFeature->document()) { - if (theContextFeature->document() == ModelAPI_Session::get()->moduleDocument()) { - aName<document()->kind()<<"/"; - } else { - ResultPtr aDocRes = ModelAPI_Tools::findPartResult( - ModelAPI_Session::get()->moduleDocument(), theContextFeature->document()); - if (aDocRes.get()) { - aName<data()->name()<<"/"; - } - } - } - aName<name(); + // #1839 : do not store name of the feature in the tree, since this name could be changed + //aName<name(); if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction - aName<<"/"; - if (!theAdditionalName.empty()) - aName<addNamingName(selectionLabel(), aName); - TDataStd_Name::Set(selectionLabel(), aName.c_str()); + //std::string aName = contextName(theContext); + //aMyDoc->addNamingName(selectionLabel(), aName); + //TDataStd_Name::Set(selectionLabel(), aName.c_str()); return; } std::shared_ptr aData = std::dynamic_pointer_cast(owner()->data()); @@ -844,7 +840,7 @@ void Model_AttributeSelection::selectConstruction( int anOrient = Model_SelectionNaming::edgeOrientation(aSubShape, anEdge); anOrientations[anID] = anOrient; registerSubShape( - selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, "", anOrientations, + selectionLabel(), anEdge, anID, aContextFeature, aMyDoc, anOrientations, aSubNames, Handle(TDataStd_IntPackedMap)(), anOrient); } } @@ -857,7 +853,7 @@ void Model_AttributeSelection::selectConstruction( std::stringstream anAdditionalName; registerSubShape( - selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, "", anOrientations, + selectionLabel(), aV, aTagIndex, aContextFeature, aMyDoc, anOrientations, aSubNames); } } @@ -871,7 +867,7 @@ void Model_AttributeSelection::selectConstruction( TNaming_Builder aBuilder(selectionLabel()); aBuilder.Generated(aSubShape); registerSubShape( - selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, "", anOrientations, aSubNames, aRefs); + selectionLabel(), aSubShape, 0, aContextFeature, aMyDoc, anOrientations, aSubNames, aRefs); } bool Model_AttributeSelection::selectPart( @@ -1072,3 +1068,146 @@ std::string Model_AttributeSelection::contextName(const ResultPtr& theContext) c aResult += theContext->data()->name(); return aResult; } + +void Model_AttributeSelection::updateInHistory() +{ + ResultPtr aContext = std::dynamic_pointer_cast(myRef.value()); + // only bodies may be modified later in the history, don't do anything otherwise + if (!aContext.get() || aContext->groupName() != ModelAPI_ResultBody::group()) + return; + std::shared_ptr aContData = std::dynamic_pointer_cast(aContext->data()); + if (!aContData.get() || !aContData->isValid()) + return; + TDF_Label aContLab = aContData->label(); // named shape where the selected context is located + Handle(TNaming_NamedShape) aContNS; + if (!aContLab.FindAttribute(TNaming_NamedShape::GetID(), aContNS)) + return; + std::shared_ptr aDoc = + std::dynamic_pointer_cast(aContext->document()); + FeaturePtr aThisFeature = std::dynamic_pointer_cast(owner()); + FeaturePtr aCurrentModifierFeat = aDoc->feature(aContext); + // iterate the context shape modifications in order to find a feature that is upper in history + // that this one and is really modifies the referenced result to refer to it + ResultPtr aModifierResFound; + TNaming_Iterator aPairIter(aContNS); + TopoDS_Shape aNewShape = aPairIter.NewShape(); + bool anIterate = true; + // trying to update also the sub-shape selected + GeomShapePtr aSubShape = value(); + if (aSubShape.get() && aSubShape->isEqual(aContext->shape())) + aSubShape.reset(); + + while(anIterate) { + anIterate = false; + TNaming_SameShapeIterator aModifIter(aNewShape, aContLab); + for(; aModifIter.More(); aModifIter.Next()) { + ResultPtr aModifierObj = std::dynamic_pointer_cast + (aDoc->objects()->object(aModifIter.Label().Father())); + if (!aModifierObj.get()) + break; + FeaturePtr aModifierFeat = aDoc->feature(aModifierObj); + if (!aModifierFeat.get()) + break; + if (aModifierFeat == aThisFeature || aDoc->objects()->isLater(aModifierFeat, aThisFeature)) + continue; // the modifier feature is later than this, so, should not be used + if (aCurrentModifierFeat == aModifierFeat || aDoc->objects()->isLater(aCurrentModifierFeat, aModifierFeat)) + continue; // the current modifier is later than the found, so, useless + Handle(TNaming_NamedShape) aNewNS; + aModifIter.Label().FindAttribute(TNaming_NamedShape::GetID(), aNewNS); + if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { + aModifierResFound = aModifierObj; + aCurrentModifierFeat = aModifierFeat; + TNaming_Iterator aPairIter(aNewNS); + aNewShape = aPairIter.NewShape(); + /* + // searching for sub-shape equivalent on the sub-label of the new context result + TDF_ChildIDIterator aNSIter(aNewNS->Label(), TNaming_NamedShape::GetID()); + for(; aNSIter.More(); aNSIter.Next()) { + TNaming_Iterator aPairsIter(aNSIter.Value()->Label()); + for(; aPairsIter.More(); aPairsIter.Next()) { + if (aSubShape->impl().IsEqual() + } + }*/ + anIterate = true; + break; + } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null + ResultPtr anEmptyContext; + std::shared_ptr anEmptyShape; + setValue(anEmptyContext, anEmptyShape); // nullify the selection + return; + } else { // not-precessed modification => don't support it + continue; + } + } + + /* + TNaming_NewShapeIterator aModifIter(aPairIter.NewShape(), aContLab); + if (aModifIter.More()) aModifIter.Next(); // skip this shape result + for(; aModifIter.More(); aModifIter.Next()) { + ResultPtr aModifierObj = std::dynamic_pointer_cast + (aDoc->objects()->object(aModifIter.Label().Father())); + if (!aModifierObj.get()) + break; + FeaturePtr aModifierFeat = aDoc->feature(aModifierObj); + if (!aModifierFeat.get()) + break; + if (aModifierFeat == aThisFeature || aDoc->objects()->isLater(aModifierFeat, aThisFeature)) + break; // the modifier feature is later than this, so, should not be used + Handle(TNaming_NamedShape) aNewNS = aModifIter.NamedShape(); + if (aNewNS->Evolution() == TNaming_MODIFY || aNewNS->Evolution() == TNaming_GENERATED) { + aModifierResFound = aModifierObj; + } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null + ResultPtr anEmptyContext; + std::shared_ptr anEmptyShape; + setValue(anEmptyContext, anEmptyShape); // nullify the selection + return; + } else { // not-precessed modification => don't support it + break; + } + } + // already found what is needed, don't iterate the next pair since normally + if (aModifierResFound.get()) // there must be only one pair in the result-shape + break; + */ + } + if (aModifierResFound.get()) { + // update scope to reset to a new one + myScope.Clear(); + myRef.setValue(aModifierResFound); + update(); // it must recompute a new sub-shape automatically + } + /* + if (aModifierResFound.get()) { + // update scope to reset to a new one + myScope.Clear(); + if (!aSubShape.get() || aSubShape->isNull()) { // no sub-shape, so, just update a context + setValue(aModifierResFound, aSubShape); + return; + } + // seaching for the same sub-shape: the old topology stays the same + TopoDS_Shape anOldShape = aSubShape->impl(); + TopAbs_ShapeEnum aSubType = anOldShape.ShapeType(); + TopoDS_Shape aNewContext = aModifierResFound->shape()->impl(); + TopExp_Explorer anExp(aNewContext, aSubType); + for(; anExp.More(); anExp.Next()) { + if (anExp.Current().IsEqual(anOldShape)) + break; + } + if (anExp.More()) { // found + setValue(aModifierResFound, aSubShape); + return; + } + // seaching for the same sub-shape: equal geometry + for(anExp.Init(aNewContext, aSubType); anExp.More(); anExp.Next()) { + if (aSubType == TopAbs_VERTEX) { + + } + } + }*/ + // if sub-shape selection exists, search also sub-shape new instance + /* + GeomShapePtr aSubShape = value(); + if (aSubShape.get() && aSubShape != aContext->shape()) { + + }*/ +} diff --git a/src/Model/Model_AttributeSelection.h b/src/Model/Model_AttributeSelection.h index d1a426693..0d329e644 100644 --- a/src/Model/Model_AttributeSelection.h +++ b/src/Model/Model_AttributeSelection.h @@ -71,6 +71,9 @@ public: /// Returns true if recomute of selection become impossible MODEL_EXPORT virtual bool isInvalid(); + /// Updates the arguments of selection if something was affected by creation + /// or reorder of features upper in the history line (issue #1757) + MODEL_EXPORT virtual void updateInHistory(); protected: /// Objects are created for features automatically diff --git a/src/Model/Model_AttributeSelectionList.cpp b/src/Model/Model_AttributeSelectionList.cpp index 0dc8d7bd6..81ce0984c 100644 --- a/src/Model/Model_AttributeSelectionList.cpp +++ b/src/Model/Model_AttributeSelectionList.cpp @@ -263,6 +263,7 @@ std::shared_ptr // (if attribute is deleted and created, the abort updates attriute and makes the Attr invalid) std::shared_ptr aNewAttr = std::shared_ptr(new Model_AttributeSelection(aLabel)); + aNewAttr->setID(id()); if (owner()) { aNewAttr->setObject(owner()); } diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index 6264e68b5..8582c5c9b 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -75,6 +75,7 @@ class Model_Data : public ModelAPI_Data friend class Model_AttributeSelection; friend class Model_AttributeSelectionList; friend class Model_ValidatorsFactory; + friend class Model_SelectionNaming; public: /// The simplest constructor. "setLabel" must be called just after to initialize correctly. diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 31208a493..0b7678a5d 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -316,8 +316,8 @@ void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) // update the feature and the history clearHistory(theMoved); // make sure all (selection) attributes of moved feature will be updated - static Events_ID EVENT_UPD = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED); - ModelAPI_EventCreator::get()->sendUpdated(theMoved, EVENT_UPD); + static Events_ID kUpdateSelection = Events_Loop::loop()->eventByName(EVENT_UPDATE_SELECTION); + ModelAPI_EventCreator::get()->sendUpdated(theMoved, kUpdateSelection, false); ModelAPI_EventCreator::get()->sendReordered(theMoved); } diff --git a/src/Model/Model_Objects.h b/src/Model/Model_Objects.h index d51c39ba8..9cca88649 100644 --- a/src/Model/Model_Objects.h +++ b/src/Model/Model_Objects.h @@ -222,6 +222,7 @@ class Model_Objects friend class Model_AttributeReference; friend class Model_AttributeRefAttr; friend class Model_AttributeRefList; + friend class Model_AttributeSelection; friend class Model_SelectionNaming; }; diff --git a/src/Model/Model_SelectionNaming.cpp b/src/Model/Model_SelectionNaming.cpp index 87c881c17..52cfed613 100644 --- a/src/Model/Model_SelectionNaming.cpp +++ b/src/Model/Model_SelectionNaming.cpp @@ -7,6 +7,7 @@ #include "Model_SelectionNaming.h" #include "Model_Document.h" #include "Model_Objects.h" +#include "Model_Data.h" #include #include #include @@ -48,46 +49,46 @@ Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab) std::string Model_SelectionNaming::getShapeName( std::shared_ptr theDoc, const TopoDS_Shape& theShape, - const bool theAddContextName) + ResultPtr& theContext, const bool theAnotherDoc, const bool theWholeContext) { std::string aName; + // add the result name to the name of the shape (it was in BodyBuilder, but did not work on Result rename) + bool isNeedContextName = theContext->shape().get() != NULL;// && !theContext->shape()->isEqual(theSubSh); // check if the subShape is already in DF Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(theShape, myLab); Handle(TDataStd_Name) anAttr; if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) { - aName = TCollection_AsciiString(anAttr->Get()).ToCString(); - // indexes are added to sub-shapes not primitives (primitives must not be located at the same label) - if(!aName.empty() && aNS->Evolution() != TNaming_PRIMITIVE && theAddContextName) { - const TDF_Label& aLabel = aNS->Label();//theDoc->findNamingName(aName); - static const std::string aPostFix("_"); - TNaming_Iterator anItL(aNS); - for(int i = 1; anItL.More(); anItL.Next(), i++) { - if(anItL.NewShape() == theShape) { - aName += aPostFix; - aName += TCollection_AsciiString (i).ToCString(); - break; - } - } - } - if (theAddContextName && aName.find("/") == std::string::npos) { // searching for the context object - for(TDF_Label anObjL = aNS->Label(); anObjL.Depth() > 4; anObjL = anObjL.Father()) { - int aDepth = anObjL.Depth(); - if (aDepth == 5 || aDepth == 7) { - ObjectPtr anObj = theDoc->objects()->object(anObjL); - if (anObj.get()) { - ResultPtr aRes = std::dynamic_pointer_cast(anObj); - if (aRes.get()) { - if (aRes && !aRes->shape()->impl().IsEqual(theShape)) { - aName = anObj->data()->name() + "/" + aName; - } - } + std::shared_ptr aData = + std::dynamic_pointer_cast(theContext->data()); + if (isNeedContextName && aData && aData->label().IsEqual(aNS->Label())) { + // do nothing because this context name will be added later in this method + } else { + aName = TCollection_AsciiString(anAttr->Get()).ToCString(); + // indexes are added to sub-shapes not primitives (primitives must not be located at the same label) + if(!aName.empty() && aNS->Evolution() != TNaming_PRIMITIVE && isNeedContextName) { + const TDF_Label& aLabel = aNS->Label();//theDoc->findNamingName(aName); + static const std::string aPostFix("_"); + TNaming_Iterator anItL(aNS); + for(int i = 1; anItL.More(); anItL.Next(), i++) { + if(anItL.NewShape() == theShape) { + aName += aPostFix; + aName += TCollection_AsciiString (i).ToCString(); + break; } } } } } } + + // Name is empty and this is full context, it just add the whole context name that must be added + bool isEmptyName = aName.empty(); + if (isNeedContextName && (!isEmptyName || theWholeContext)) { + aName = theContext->data()->name() + (isEmptyName ? "" : ("/" + aName)); + if (theAnotherDoc) + aName = theContext->document()->kind() + "/" + aName; // PartSet + } return aName; } @@ -149,12 +150,9 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, BRepTools::Write(aContext, "Context.brep"); } #endif + aName = getShapeName(aDoc, aSubShape, theContext, theAnotherDoc, + theContext->shape()->isEqual(theSubSh)); - // add the result name to the name of the shape (it was in BodyBuilder, but did not work on Result rename) - bool isNeedContextName = theContext->shape().get() && !theContext->shape()->isEqual(theSubSh); - - // check if the subShape is already in DF - aName = getShapeName(aDoc, aSubShape, isNeedContextName); if(aName.empty() ) { // not in the document! TopAbs_ShapeEnum aType = aSubShape.ShapeType(); switch (aType) { @@ -201,7 +199,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, // build name of the sub-shape Edge for(int i=1; i <= aSMap.Extent(); i++) { const TopoDS_Shape& aFace = aSMap.FindKey(i); - std::string aFaceName = getShapeName(aDoc, aFace, isNeedContextName); + std::string aFaceName = getShapeName(aDoc, aFace, theContext, theAnotherDoc, false); if(i == 1) aName = aFaceName; else @@ -209,7 +207,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, } TopTools_ListIteratorOfListOfShape itl(aListOfNbs); for (;itl.More();itl.Next()) { - std::string aFaceName = getShapeName(aDoc, itl.Value(), isNeedContextName); + std::string aFaceName = getShapeName(aDoc, itl.Value(), theContext, theAnotherDoc, false); aName += "&" + aFaceName; } } @@ -258,7 +256,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopTools_ListIteratorOfListOfShape itl(aListE); for (int i = 1;itl.More();itl.Next(),i++) { const TopoDS_Shape& anEdge = itl.Value(); - std::string anEdgeName = getShapeName(aDoc, anEdge, isNeedContextName); + std::string anEdgeName = getShapeName(aDoc, anEdge, theContext, theAnotherDoc, false); if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway isByFaces = true; aName.clear(); @@ -278,7 +276,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext, TopTools_ListIteratorOfListOfShape itl(aList); for (int i = 1;itl.More();itl.Next(),i++) { const TopoDS_Shape& aFace = itl.Value(); - std::string aFaceName = getShapeName(aDoc, aFace, isNeedContextName); + std::string aFaceName = getShapeName(aDoc, aFace, theContext, theAnotherDoc, false); if(i == 1) aName = aFaceName; else diff --git a/src/Model/Model_SelectionNaming.h b/src/Model/Model_SelectionNaming.h index 97c49a68e..944dec588 100644 --- a/src/Model/Model_SelectionNaming.h +++ b/src/Model/Model_SelectionNaming.h @@ -65,7 +65,7 @@ public: protected: /// Gets the stored name from the document std::string getShapeName(std::shared_ptr theDoc, const TopoDS_Shape& theShape, - const bool theAddContextName); + ResultPtr& theContext, const bool theAnotherDoc, const bool theWholeContext); }; #endif diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp index 302dbd213..24ef7055d 100755 --- a/src/Model/Model_Update.cpp +++ b/src/Model/Model_Update.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,8 @@ Model_Update::Model_Update() aLoop->registerListener(this, kPreviewRequestedEvent); static const Events_ID kReorderEvent = aLoop->eventByName(EVENT_ORDER_UPDATED); aLoop->registerListener(this, kReorderEvent); + static const Events_ID kUpdatedSel = aLoop->eventByName(EVENT_UPDATE_SELECTION); + aLoop->registerListener(this, kUpdatedSel); // Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true"; myIsParamUpdated = false; @@ -207,6 +210,7 @@ void Model_Update::processEvent(const std::shared_ptr& theMessag static const Events_ID kPreviewRequestedEvent = aLoop->eventByName(EVENT_PREVIEW_REQUESTED); static const Events_ID kReorderEvent = aLoop->eventByName(EVENT_ORDER_UPDATED); static const Events_ID kRedisplayEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static const Events_ID kUpdatedSel = aLoop->eventByName(EVENT_UPDATE_SELECTION); #ifdef DEB_UPDATE std::cout<<"****** Event "<eventID().eventText()<& theMessag } return; } + if (theMessage->eventID() == kUpdatedSel) { + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); + updateSelection(aMsg->objects()); + } // creation is added to "update" to avoid recomputation twice: on create and immediately after on update if (theMessage->eventID() == kCreatedEvent) { std::shared_ptr aMsg = @@ -862,3 +871,30 @@ void Model_Update::updateStability(void* theSender) } } } + +void Model_Update::updateSelection(const std::set >& theObjects) +{ + std::set >::iterator anObj = theObjects.begin(); + for(; anObj != theObjects.end(); anObj++) { + list aRefs = + (*anObj)->data()->attributes(ModelAPI_AttributeSelection::typeId()); + list::iterator aRefsIter = aRefs.begin(); + for (; aRefsIter != aRefs.end(); aRefsIter++) { + std::shared_ptr aSel = + std::dynamic_pointer_cast(*aRefsIter); + aSel->updateInHistory(); + } + // update the selection list attributes if any + aRefs = (*anObj)->data()->attributes(ModelAPI_AttributeSelectionList::typeId()); + for (aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) { + std::shared_ptr aSel = + std::dynamic_pointer_cast(*aRefsIter); + for(int a = aSel->size() - 1; a >= 0; a--) { + std::shared_ptr aSelAttr = + std::dynamic_pointer_cast(aSel->value(a)); + if (aSelAttr.get()) + aSelAttr->updateInHistory(); + } + } + } +} diff --git a/src/Model/Model_Update.h b/src/Model/Model_Update.h index 9e37eddd2..866f99c30 100644 --- a/src/Model/Model_Update.h +++ b/src/Model/Model_Update.h @@ -89,6 +89,11 @@ protected: /// Returns true if theFeature modification was caused by theReason (may be feature of result of this feature) bool isReason( std::shared_ptr& theFeature, std::shared_ptr theReason); + + /// Updates a selection attributes for the features that possible were affected by creation + /// or reorder of features upper in the history line (issue #1757) + void updateSelection(const std::set >& theObjects); + }; #endif diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index 0ba832111..006b4e7db 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -36,20 +36,31 @@ static const char * EVENT_OBJECT_MOVED = "ObjectsMoved"; static const char * EVENT_OBJECT_TO_REDISPLAY = "ObjectsToRedisplay"; /// Event ID that plugin is loaded (comes with ModelAPI_ObjectUpdatedMessage) static const char * EVENT_PLUGIN_LOADED = "PluginLoaded"; -// +/// The active document becomes another one static const char * EVENT_DOCUMENT_CHANGED = "CurrentDocumentChanged"; +/// Event ID that order of objects in group is changed, so, tree must be fully rectreated (movement of feature) +static const char * EVENT_ORDER_UPDATED = "OrderUpdated"; +/// Event ID that the sketch is prepared and all grouped messages for the solver may be flushed +static const char * EVENT_UPDATE_SELECTION = "UpdateSelection"; + +/// Request for the enabled/disabled actions behavior for some specific features static const char * EVENT_FEATURE_STATE_REQUEST = "FeatureStateRequest"; +/// Reply for the enabled/disabled actions behavior for some specific features static const char * EVENT_FEATURE_STATE_RESPONSE = "FeatureStateResponse"; - +/// To block the viewer updates static const char * EVENT_UPDATE_VIEWER_BLOCKED = "UpdateViewerBlocked"; +/// To unblock the viewer updates static const char * EVENT_UPDATE_VIEWER_UNBLOCKED = "UpdateViewerUnblocked"; +/// To inform that there is an empty presentation in the viewer static const char * EVENT_EMPTY_AIS_PRESENTATION = "EmptyAISPresentation"; +/// To inform that there is an empty operation for presentation in the viewer static const char * EVENT_EMPTY_OPERATION_PRESENTATION = "EmptyOperationPresentation"; - +/// To block preview static const char * EVENT_PREVIEW_BLOCKED = "PreviewBlocked"; +/// To preview the current feature in the viewer (to compute the result) static const char * EVENT_PREVIEW_REQUESTED = "PreviewRequested"; /// Event ID that solver has conflicting constraints (comes with ModelAPI_SolverFailedMessage) @@ -57,9 +68,6 @@ static const char * EVENT_SOLVER_FAILED = "SolverFailed"; /// Event ID that the problem in solver disappeared static const char * EVENT_SOLVER_REPAIRED = "SolverRepaired"; -/// Event ID that order of objects in group is changed, so, tree must be fully rectreated (movement of feature) -static const char * EVENT_ORDER_UPDATED = "OrderUpdated"; - /// Event ID that informs that some object has changed the stability static const char * EVENT_STABILITY_CHANGED = "StabilityChanged"; diff --git a/src/ModelAPI/ModelAPI_Feature.cpp b/src/ModelAPI/ModelAPI_Feature.cpp index ad496462b..b3b60c792 100644 --- a/src/ModelAPI/ModelAPI_Feature.cpp +++ b/src/ModelAPI/ModelAPI_Feature.cpp @@ -188,6 +188,12 @@ bool ModelAPI_Feature::setDisabled(const bool theFlag) for(; aResIter != myResults.end(); aResIter++) { (*aResIter)->setDisabled(*aResIter, false); } + // update selection for the case something was updated higher in the history + // while this feature was disabled + static Events_Loop* aLoop = Events_Loop::loop(); + static Events_ID kUpdatedSel = aLoop->eventByName(EVENT_UPDATE_SELECTION); + static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get(); + aECreator->sendUpdated(data()->owner(), kUpdatedSel, false); } return true; } diff --git a/src/ModelAPI/ModelAPI_Result.cpp b/src/ModelAPI/ModelAPI_Result.cpp index 187a1fc82..8aaa1d720 100644 --- a/src/ModelAPI/ModelAPI_Result.cpp +++ b/src/ModelAPI/ModelAPI_Result.cpp @@ -29,7 +29,7 @@ bool ModelAPI_Result::setDisabled(std::shared_ptr theThis, cons { if (myIsDisabled != theFlag) { myIsDisabled = theFlag; - data()->setIsDeleted(theFlag); // store it in data model (t oget back on undo/redo, etc) + data()->setIsDeleted(theFlag); // store it in data model (to get back on undo/redo, etc) // this must be before "updated" message send to have history updated for OB update document()->updateHistory(groupName()); // to update the history cash data in the document // generate related events -- 2.39.2