Salome HOME
Multiple fixes (issue #1757 , issue #1799 , issue #1842 , etc):
authormpv <mpv@opencascade.com>
Tue, 1 Nov 2016 14:45:28 +0000 (17:45 +0300)
committermpv <mpv@opencascade.com>
Tue, 1 Nov 2016 14:45:28 +0000 (17:45 +0300)
- 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

15 files changed:
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/FeaturesPlugin_Partition.h
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_Data.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_SelectionNaming.cpp
src/Model/Model_SelectionNaming.h
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_Events.h
src/ModelAPI/ModelAPI_Feature.cpp
src/ModelAPI/ModelAPI_Result.cpp

index c9869f12446e83acb31d659f7c5cf7ade3d5970b..f1ec8123b50a612e204637d2142f537238ca8190 100755 (executable)
@@ -71,7 +71,8 @@ void FeaturesPlugin_Partition::execute()
     return;
   }
 
-  std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(anObjects, 1.0);
+  std::list<std::shared_ptr<GeomAPI_Pnt> > 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<GeomAlgoAPI_MakeShape> theMakeShape,
-                                           const int theIndex)
+void FeaturesPlugin_Partition::storeResult(
+  ListOfShape& theObjects, ListOfShape& thePlanes,
+  const GeomShapePtr theResultShape,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> 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<GeomAPI_DataMapOfShapeShape> 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;
index ea50c6e0ae44318100dca849355e367b83f1205b..ff3d83df542e1a37359353c22573be6999bf1006 100755 (executable)
@@ -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<GeomAlgoAPI_MakeShape> theMakeShape,
                    const int theIndex = 0);
index 64b5ca6de48b497cf5b88678562f7b50d82d0ccf..cf482e2df5b9ba2ea221c7234e61bedd9e7b803e 100644 (file)
@@ -27,6 +27,9 @@
 #include <TNaming_Tool.hxx>
 #include <TNaming_Builder.hxx>
 #include <TNaming_Localizer.hxx>
+#include <TNaming_SameShapeIterator.hxx>
+#include <TNaming_Iterator.hxx>
+#include <TNaming_NewShapeIterator.hxx>
 #include <TopoDS_Shape.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TDataStd_IntPackedMap.hxx>
@@ -57,8 +60,6 @@
 #include <TopAbs_ShapeEnum.hxx>
 #include <TopoDS_Iterator.hxx>
 #include <BRep_Builder.hxx>
-#include <TNaming_SameShapeIterator.hxx>
-#include <TNaming_Iterator.hxx>
 
 using namespace std;
 //#define DEB_NAMING 1
@@ -150,10 +151,10 @@ void Model_AttributeSelection::setValue(const ResultPtr& theContext,
         aBuilder.Generated(theContext->shape()->impl<TopoDS_Shape>());
         std::shared_ptr<Model_Document> aMyDoc = 
           std::dynamic_pointer_cast<Model_Document>(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<TopoDS_Shape>());
       std::shared_ptr<Model_Document> aMyDoc = 
         std::dynamic_pointer_cast<Model_Document>(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<Model_Document> theDoc,
-  std::string theAdditionalName, std::map<int, int>& theOrientations,
+  std::map<int, int>& theOrientations,
   std::map<int, std::string>& 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<<theContextFeature->document()->kind()<<"/";
-    } else {
-      ResultPtr aDocRes = ModelAPI_Tools::findPartResult(
-        ModelAPI_Session::get()->moduleDocument(), theContextFeature->document());
-      if (aDocRes.get()) {
-        aName<<aDocRes->data()->name()<<"/";
-      }
-    }
-  }
-  aName<<theContextFeature->name();
+  // #1839 : do not store name of the feature in the tree, since this name could be changed
+  //aName<<theContextFeature->name();
   if (theShape.ShapeType() != TopAbs_COMPOUND) { // compound means the whole result for construction
-    aName<<"/";
-    if (!theAdditionalName.empty())
-      aName<<theAdditionalName<<"/";
+    //aName<<"/";
     if (theShape.ShapeType() == TopAbs_FACE) aName<<"Face";
     else if (theShape.ShapeType() == TopAbs_WIRE) aName<<"Wire";
     else if (theShape.ShapeType() == TopAbs_EDGE) aName<<"Edge";
@@ -760,9 +756,9 @@ void Model_AttributeSelection::selectConstruction(
     // saving of context is enough: result construction contains exactly the needed shape
     TNaming_Builder aBuilder(selectionLabel());
     aBuilder.Generated(aSubShape);
-    std::string aName = contextName(theContext);
-    aMyDoc->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<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(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<ModelAPI_Result>(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<Model_Data> aContData = std::dynamic_pointer_cast<Model_Data>(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<Model_Document> aDoc = 
+    std::dynamic_pointer_cast<Model_Document>(aContext->document());
+  FeaturePtr aThisFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(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<ModelAPI_Result>
+        (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<TopoDS_Shape>().IsEqual()
+          }
+        }*/
+        anIterate = true;
+        break;
+      } else if (aNewNS->Evolution() == TNaming_DELETE) { // a shape was deleted => result is null
+        ResultPtr anEmptyContext;
+        std::shared_ptr<GeomAPI_Shape> 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<ModelAPI_Result>
+        (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<GeomAPI_Shape> 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<TopoDS_Shape>();
+    TopAbs_ShapeEnum aSubType = anOldShape.ShapeType();
+    TopoDS_Shape aNewContext = aModifierResFound->shape()->impl<TopoDS_Shape>();
+    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()) {
+
+  }*/
+}
index d1a426693e524ebf828f369111368f3ec6b45926..0d329e6445167b9a97d2c586986cfd9844f5e6ff 100644 (file)
@@ -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
index 0dc8d7bd6fda2d74a65c950082795c11004c2b4e..81ce0984cb9a856808b9439a51fdaee82f571fb5 100644 (file)
@@ -263,6 +263,7 @@ std::shared_ptr<ModelAPI_AttributeSelection>
   // (if attribute is deleted and created, the abort updates attriute and makes the Attr invalid)
   std::shared_ptr<Model_AttributeSelection> aNewAttr = 
     std::shared_ptr<Model_AttributeSelection>(new Model_AttributeSelection(aLabel));
+  aNewAttr->setID(id());
   if (owner()) {
     aNewAttr->setObject(owner());
   }
index 6264e68b5ae1b054ff348b2f9cd87a418f41f76f..8582c5c9bba850a467f3f3db34b43a764ab9bd5d 100644 (file)
@@ -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.
index 31208a493c03355395e9f18fa9a44b4398dc31d6..0b7678a5d532144cacb2b60ed48d64fe43b01631 100644 (file)
@@ -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);
 }
 
index d51c39ba8aca9f9bd0b2be83795acae9cc42e8d8..9cca8864980056cecb8d78ef12b4a60dda1c7f21 100644 (file)
@@ -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;
 };
 
index 87c881c1766f1d0b72416725f4b1008282497391..52cfed613339f94ace0e977a9321dec79160a120 100644 (file)
@@ -7,6 +7,7 @@
 #include "Model_SelectionNaming.h"
 #include "Model_Document.h"
 #include "Model_Objects.h"
+#include "Model_Data.h"
 #include <ModelAPI_Feature.h>
 #include <Events_InfoMessage.h>
 #include <ModelAPI_Session.h>
@@ -48,46 +49,46 @@ Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab)
 
 std::string Model_SelectionNaming::getShapeName(
   std::shared_ptr<Model_Document> 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<ModelAPI_Result>(anObj);
-              if (aRes.get()) {
-                if (aRes && !aRes->shape()->impl<TopoDS_Shape>().IsEqual(theShape)) {
-                  aName = anObj->data()->name() + "/" + aName;
-                }
-              }
+      std::shared_ptr<Model_Data> aData =
+        std::dynamic_pointer_cast<Model_Data>(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 
index 97c49a68e14ccfdaf8d81052675fe91eb16fcda3..944dec58872e33b3c197854a86be27b8bc085fad 100644 (file)
@@ -65,7 +65,7 @@ public:
 protected:
   /// Gets the stored name from the document
   std::string getShapeName(std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape& theShape,
-    const bool theAddContextName);
+    ResultPtr& theContext, const bool theAnotherDoc, const bool theWholeContext);
 };
 
 #endif
index 302dbd2131841b138cb6400dae55a3f681d53bf7..24ef7055d878328f44c7a61ab777a3ed7a8e02e4 100755 (executable)
@@ -8,6 +8,7 @@
 #include <Model_Document.h>
 #include <Model_Data.h>
 #include <Model_Objects.h>
+#include <Model_AttributeSelection.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
@@ -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<Events_Message>& 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 "<<theMessage->eventID().eventText()<<std::endl;
@@ -227,6 +231,11 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     }
     return;
   }
+  if (theMessage->eventID() == kUpdatedSel) {
+    std::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
+        std::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(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<ModelAPI_ObjectUpdatedMessage> aMsg =
@@ -862,3 +871,30 @@ void Model_Update::updateStability(void* theSender)
     }
   }
 }
+
+void Model_Update::updateSelection(const std::set<std::shared_ptr<ModelAPI_Object> >& theObjects)
+{
+  std::set<std::shared_ptr<ModelAPI_Object> >::iterator anObj = theObjects.begin();
+  for(; anObj != theObjects.end(); anObj++) {
+    list<AttributePtr> aRefs = 
+      (*anObj)->data()->attributes(ModelAPI_AttributeSelection::typeId());
+    list<AttributePtr>::iterator aRefsIter = aRefs.begin();
+    for (; aRefsIter != aRefs.end(); aRefsIter++) {
+      std::shared_ptr<Model_AttributeSelection> aSel =
+        std::dynamic_pointer_cast<Model_AttributeSelection>(*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<ModelAPI_AttributeSelectionList> aSel =
+        std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
+      for(int a = aSel->size() - 1; a >= 0; a--) {
+        std::shared_ptr<Model_AttributeSelection> aSelAttr =
+          std::dynamic_pointer_cast<Model_AttributeSelection>(aSel->value(a));
+        if (aSelAttr.get())
+          aSelAttr->updateInHistory();
+      }
+    }
+  }
+}
index 9e37eddd23383e2604fbcceda273f4bf25642920..866f99c301a667ca2b82a1df079752a2497c313d 100644 (file)
@@ -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<ModelAPI_Feature>& theFeature, std::shared_ptr<ModelAPI_Object> 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<std::shared_ptr<ModelAPI_Object> >& theObjects);
+
 };
 
 #endif
index 0ba832111b165475ab9b6f2c752b500d36ea6b14..006b4e7dbb92e0d08e461e3046852762f6f53129 100644 (file)
@@ -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";
 
index ad496462bd8c70e183b6e5574b320543313a0442..b3b60c7926d9207da78aa997b1e827c4fc826284 100644 (file)
@@ -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;
   }
index 187a1fc8271f608506ca716df73cf4d23a4f05ab..8aaa1d720b3c4543b9d3101e12ebe7daa6076c58 100644 (file)
@@ -29,7 +29,7 @@ bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> 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 (tget 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