]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
[CEA] Allow to keep result in SHAPER eksu/40621KeepResultInShaper
authorEkaterina Sukhareva <ekaterina.sukhareva@opencascade.com>
Fri, 23 Aug 2024 15:24:44 +0000 (16:24 +0100)
committerEsukhareva <ekaterina.sukhareva@opencascade.com>
Fri, 6 Sep 2024 15:26:02 +0000 (16:26 +0100)
41 files changed:
src/FeaturesPlugin/FeaturesPlugin_Copy.cpp
src/FeaturesPlugin/FeaturesPlugin_Copy.h
src/GeomAPI/GeomAPI_Shape.cpp
src/GeomAPI/GeomAPI_Shape.h
src/Model/Model_AttributeSelection.cpp
src/Model/Model_AttributeSelection.h
src/Model/Model_AttributeSelectionList.cpp
src/Model/Model_AttributeSelectionList.h
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Objects.cpp
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/Model/Model_Tools.cpp
src/Model/Model_Tools.h
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_AttributeSelection.h
src/ModelAPI/ModelAPI_AttributeSelectionList.h
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Result.cpp
src/ModelAPI/ModelAPI_Result.h
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelHighAPI/ModelHighAPI_Dumper.cpp
src/PartSet/PartSet_IconFactory.cpp
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/compound_persistent.png [new file with mode: 0755]
src/XGUI/pictures/compoundofsolids_persistent.png [new file with mode: 0755]
src/XGUI/pictures/compsolid_persistent.png [new file with mode: 0755]
src/XGUI/pictures/edge_persistent.png [new file with mode: 0755]
src/XGUI/pictures/face_persistent.png [new file with mode: 0755]
src/XGUI/pictures/shell_persistent.png [new file with mode: 0755]
src/XGUI/pictures/solid_persistent.png [new file with mode: 0755]
src/XGUI/pictures/vertex_persistent.png [new file with mode: 0755]
src/XGUI/pictures/wire_persistent.png [new file with mode: 0755]

index e1110270f3eba1d78396dfb453127bf974ac99a3..f357f66c5e8d199d2b9b556a2ee1b6efd3d1a661 100644 (file)
@@ -33,6 +33,12 @@ void FeaturesPlugin_Copy::initAttributes()
 {
   data()->addAttribute(OBJECTS(), ModelAPI_AttributeSelectionList::typeId());
   data()->addAttribute(NUMBER(), ModelAPI_AttributeInteger::typeId());
+
+  AttributeIntegerPtr aNameNumAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(
+    data()->addAttribute(NAME_SUFFIX(), ModelAPI_AttributeInteger::typeId()));
+  if (!aNameNumAttr->isInitialized()){
+    aNameNumAttr->setValue(0);
+  }
 }
 
 static GeomShapePtr shapeOfSelection(AttributeSelectionPtr theSel) {
@@ -77,7 +83,8 @@ void FeaturesPlugin_Copy::execute()
       std::wstring aBaseName = aSel->context() ? aSel->context()->data()->name() :
         aSel->contextFeature()->firstResult()->data()->name();
       std::wstring aName;
-      int anInd = 0;
+      int aNameNum = integer(NAME_SUFFIX())->value();
+      int anInd = aNameNum;
       do {
         anInd++;
         std::wostringstream aNameStr;
@@ -88,12 +95,12 @@ void FeaturesPlugin_Copy::execute()
 
       std::shared_ptr<ModelAPI_ResultBody> aResultBody =
         document()->createBody(data(), aResultIndex);
-      aResultBody->data()->setName(aName);
+      aResultBody->data()->setName(aName, false);
       // to make sub-results also names with a similar name temporarily rename the feature
       std::wstring anOrigName = name();
-      data()->setName(aBaseName);
+      data()->setName(aBaseName, false);
       aResultBody->store(aResult);
-      data()->setName(anOrigName);
+      data()->setName(anOrigName, false);
       aResultBody->loadFirstLevel(aResult, "Copy");
       setResult(aResultBody, aResultIndex++);
     }
index 49bcc06e70164331a6eee5ecd923d566c7b0bf95..b213f0aa6cf69ce31114a858577402723ecda1e0 100644 (file)
@@ -28,8 +28,8 @@
 /// \ingroup Plugins
 /// \brief This feature copies the selected results and sub-results (for the whole feature selected
 ///        all results of this feature are copied). The referenced arguments of this feature are
-///        not concealed. The difference with \94Recover\94 feature is that not concealed results may
-///        be selected and in the history behavior: the \93Move to the End\94 of groups will move to
+///        not concealed. The difference with �Recover� feature is that not concealed results may
+///        be selected and in the history behavior: the �Move to the End� of groups will move to
 ///        all copy-results.
 
 class FeaturesPlugin_Copy : public ModelAPI_Feature, public ModelAPI_FeatureCopyInterface
@@ -62,6 +62,14 @@ public:
     return MY_NUMBER;
   }
 
+  /// Integer attribute that contains the number of copies of original object that was created before
+  /// (used for creating copies of persistent object)
+  inline static const std::string NAME_SUFFIX()
+  {
+    static std::string MY_NAME_NUMBER("name_suffix");
+    return MY_NAME_NUMBER;
+  }
+
   /// Performs the algorithm and stores results it in the data structure.
   FEATURESPLUGIN_EXPORT virtual void execute();
 
index 3fb717b753f7e05d5b41f579de458b58c91e367f..046da23db43c696169c2c41530089172f49fc625 100644 (file)
@@ -110,9 +110,78 @@ bool GeomAPI_Shape::isSameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape
     return face()->isSameGeometry(theShape);
   else if (isEdge())
     return edge()->isSameGeometry(theShape);
+  else if (isVertex())
+    return vertex()->isEqual(theShape);
+  else
+  {
+    //check only bounding boxes and amounts of subshapes
+    return isProbablySameGeometry(theShape);
+  }
   return false;
 }
 
+bool GeomAPI_Shape::isSameSize(const std::shared_ptr<GeomAPI_Shape> theShape) const
+{
+  if (!theShape.get())
+    return false;
+
+  if(theShape->shapeType() != shapeType())
+    return false;
+
+  double aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
+  computeSize(aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ);
+
+  double aSMinX, aSMinY, aSMinZ, aSMaxX, aSMaxY, aSMaxZ;
+  theShape->computeSize(aSMinX, aSMinY, aSMinZ, aSMaxX, aSMaxY, aSMaxZ);
+
+  if(fabs(aMinX-aSMinX) > Precision::Confusion() ||
+     fabs(aMinY-aSMinY) > Precision::Confusion() ||
+     fabs(aMinZ-aSMinZ) > Precision::Confusion() ||
+     fabs(aMaxX-aSMaxX) > Precision::Confusion() ||
+     fabs(aMaxY-aSMaxY) > Precision::Confusion() ||
+     fabs(aMaxZ-aSMaxZ) > Precision::Confusion()){
+    return false;
+  }
+  return true;
+
+}
+
+bool GeomAPI_Shape::isSameAmountOfSubs(const std::shared_ptr<GeomAPI_Shape> theShape) const
+{
+  if (!theShape.get())
+    return false;
+
+  if(theShape->shapeType() != shapeType())
+    return false;
+
+
+  if(theShape->subShapes(GeomAPI_Shape::COMPOUND).size() != subShapes(GeomAPI_Shape::COMPOUND).size() ||
+     theShape->subShapes(GeomAPI_Shape::COMPSOLID).size() != subShapes(GeomAPI_Shape::COMPSOLID).size() ||
+     theShape->subShapes(GeomAPI_Shape::SOLID).size() != subShapes(GeomAPI_Shape::SOLID).size() ||
+     theShape->subShapes(GeomAPI_Shape::SHELL).size() != subShapes(GeomAPI_Shape::SHELL).size() ||
+     theShape->subShapes(GeomAPI_Shape::FACE).size() != subShapes(GeomAPI_Shape::FACE).size() ||
+     theShape->subShapes(GeomAPI_Shape::WIRE).size() != subShapes(GeomAPI_Shape::WIRE).size() ||
+     theShape->subShapes(GeomAPI_Shape::EDGE).size() != subShapes(GeomAPI_Shape::EDGE).size() ||
+     theShape->subShapes(GeomAPI_Shape::VERTEX).size() != subShapes(GeomAPI_Shape::VERTEX).size()){
+    return false;
+  }
+  return true;
+}
+
+bool GeomAPI_Shape::isProbablySameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape) const
+{
+  if (!theShape.get())
+    return false;
+
+  if(theShape->shapeType() != shapeType())
+    return false;
+
+  if(!isSameAmountOfSubs(theShape) || !isSameSize(theShape))
+    return false;
+
+  return true;
+}
+
 bool GeomAPI_Shape::isVertex() const
 {
   const TopoDS_Shape& aShape = const_cast<GeomAPI_Shape*>(this)->impl<TopoDS_Shape>();
index e697092623854170609e59a02720056d838dc5a0..edfe32774931415bb8e1eb9fbd4e1252b1a0f5e0 100644 (file)
@@ -78,10 +78,23 @@ public:
   GEOMAPI_EXPORT
   virtual bool isSame(const std::shared_ptr<GeomAPI_Shape> theShape) const;
 
-  /// Returns \c true if shapes have same underlying geometry
+  /// Returns \c true if shapes have same underlying geometry (vertex,edge,face only)
   GEOMAPI_EXPORT
   virtual bool isSameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape) const;
 
+  /// Returns \c true if bounding boxes of the shapes are equal (compared shapes should be the same type)
+  GEOMAPI_EXPORT
+  virtual bool isSameSize(const std::shared_ptr<GeomAPI_Shape> theShape) const;
+
+  /// Returns \c true if shapes have the same amounts of each type of subshapes (compared shapes should be the same type)
+  GEOMAPI_EXPORT
+  virtual bool isSameAmountOfSubs(const std::shared_ptr<GeomAPI_Shape> theShape) const;
+
+  /// Returns \c true if shapes (probably) have same underlying geometry (shell, solid, compound, compsolid)
+  /// Compare bounding boxes and amounts of subshapes
+  GEOMAPI_EXPORT
+  virtual bool isProbablySameGeometry(const std::shared_ptr<GeomAPI_Shape> theShape) const;
+
   /// Returns whether the shape is a vertex
   GEOMAPI_EXPORT
   virtual bool isVertex() const;
index 8ee38cbc82c92f96ebc1976b745a85d6cea8e41a..a672008a7bf0781666abb0e4cfacbd3cc3d97dcc 100644 (file)
@@ -74,6 +74,8 @@
 #include <Geom_TrimmedCurve.hxx>
 #include <BRep_Builder.hxx>
 
+#include <utility>
+
 //#define DEB_NAMING 1
 #ifdef DEB_NAMING
 #include <BRepTools.hxx>
@@ -2222,3 +2224,38 @@ void Model_AttributeSelection::reset()
   ModelAPI_AttributeSelection::reset();
   myRef.reset();
 }
+
+bool Model_AttributeSelection::isCopyToSwallow()
+{
+  ResultPtr aContext = context();
+  if (aContext.get()) 
+  {
+    return ModelAPI_Tools::isCopyToSwallow(aContext);
+  }
+  return false;
+}
+
+std::pair<ResultPtr, std::shared_ptr<GeomAPI_Shape>> Model_AttributeSelection::getOriginalContext() 
+{
+    auto aThisPair = std::make_pair(context(), value());
+    if(!isCopyToSwallow())
+        return aThisPair;
+
+    ResultPtr aCopyContext = context();
+    ObjectPtr anOriginalObject = ModelAPI_Tools::getOriginalObject(aCopyContext);
+
+
+    ResultPtr anOriginaResult = std::dynamic_pointer_cast<ModelAPI_Result>(anOriginalObject); //it should be original object
+    GeomShapePtr aGeomObj = value();
+    GeomAPI_Shape::ShapeType aCurType = aGeomObj->shapeType();
+    ListOfShape anOrigSubs = anOriginaResult->shape()->subShapes(aCurType,true);
+    for(auto anOrigSub: anOrigSubs)
+    {
+        if(anOrigSub->isSameGeometry(aGeomObj))
+        {
+            return std::make_pair(anOriginaResult, anOrigSub);
+        }
+    }
+
+    return aThisPair;
+}
\ No newline at end of file
index 6b726748f5efa5a8df50da400b588aa62011621d..c5d8a008bee3757ed6fbcd3591b375d3de3631c6 100644 (file)
@@ -147,6 +147,12 @@ public:
   /// Resets attribute to deafult state
   MODEL_EXPORT virtual void reset();
 
+  /// Return true if context of the atribute is a copy of persistent result
+  MODEL_EXPORT virtual bool isCopyToSwallow();
+
+  /// Return original context and shape of this copy atribute
+  MODEL_EXPORT virtual std::pair<ResultPtr, std::shared_ptr<GeomAPI_Shape>> getOriginalContext();
+
 protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeSelection(TDF_Label& theLabel);
index 3380b1f65a53fc679d195dfc8e20394934ab125f..d3db4d7574e8a90435b58699763a8ba8b8be0b03 100644 (file)
@@ -44,6 +44,7 @@
 #include <TNaming_NamedShape.hxx>
 #include <NCollection_List.hxx>
 
+
 /// GUID for UAttribute that indicates the list has "To add all elements that share the same
 /// topology" flag enabled
 static const Standard_GUID kIS_GEOMETRICAL_SELECTION("f16987b6-e6c8-435c-99fa-03a7e0b06e83");
@@ -546,3 +547,16 @@ void Model_AttributeSelectionList::setFilters(FiltersFeaturePtr theFeature)
   // remove attribute if something is wrong
   myLab.ForgetAttribute(TDataStd_ReferenceList::GetID());
 }
+
+bool Model_AttributeSelectionList::isContainCopiesToSwallow()
+{
+  for(int anIndex = size() - 1; anIndex >= 0; anIndex--) 
+  {
+    AttributeSelectionPtr anAttr = value(anIndex);
+    if(anAttr->isCopyToSwallow())
+    {
+        return true;
+    }
+  }
+  return false;
+}
index 82f62afc88ca9de1cdbead24b02d7d5d90d69a33..362d46808e7517cfd1b71f886c341c5ebe9e7743 100644 (file)
@@ -126,6 +126,9 @@ public:
   /// Sets a selection filters feature if it is defined for this selection list
   MODEL_EXPORT virtual void setFilters(FiltersFeaturePtr theFeature);
 
+  /// Return true if contain at least one attr witch context is a copy of persistent result.
+  MODEL_EXPORT virtual bool isContainCopiesToSwallow();
+
 protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeSelectionList(TDF_Label& theLabel);
index 28237c24e897b1958993d31f2ca4156525d35dcd..3d65946cb7564982855a3b4fdd4ede471f580b9a 100644 (file)
@@ -121,7 +121,7 @@ std::wstring Model_Data::name()
   return L"";  // not defined
 }
 
-void Model_Data::setName(const std::wstring& theName)
+void Model_Data::setName(const std::wstring& theName, bool isUserDefined)
 {
   bool isModified = false;
   std::wstring anOldName = name();
@@ -136,9 +136,9 @@ void Model_Data::setName(const std::wstring& theName)
 
       // check the name of result is defined by user
       // (name of result does not composed of the name of feature and the result index)
-      bool isUserDefined = true;
+      //bool isUserDefined = true;
       ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
-      if (aResult) {
+      if (aResult && isUserDefined) {
         std::wstring aDefaultName = ModelAPI_Tools::getDefaultName(aResult, false).first;
         isUserDefined = aDefaultName != theName;
       }
index 82703d70c0a54357bbf37cdcb4d114df1e5f83fc..0c7b411c127b77fadc1c5c6d2d9a23bf87c55ab7 100644 (file)
@@ -105,7 +105,7 @@ class Model_Data : public ModelAPI_Data
   /// Returns the name of the feature visible by the user in the object browser
   MODEL_EXPORT virtual std::wstring name();
   /// Defines the name of the feature visible by the user in the object browser
-  MODEL_EXPORT virtual void setName(const std::wstring& theName);
+  MODEL_EXPORT virtual void setName(const std::wstring& theName, bool isUserDefined = true);
   /// Return \c true if the object has been renamed by the user
   MODEL_EXPORT virtual bool hasUserDefinedName() const;
   /// Returns version of the feature (empty string if not applicable)
index 5f313a85519112845c586862b6ada79476d43b7b..cdcebe1e2b5b4b686aec39f51a929092b7cf5cdb 100644 (file)
@@ -833,6 +833,7 @@ bool Model_Document::finishOperation()
       setCurrentFeature(aMain, false);
   }
   myObjs->synchronizeBackRefs();
+  processPersistentResult(true);
   Events_Loop* aLoop = Events_Loop::loop();
   static const Events_ID kCreatedEvent = aLoop->eventByName(EVENT_OBJECT_CREATED);
   static const Events_ID kUpdatedEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED);
@@ -999,6 +1000,7 @@ void Model_Document::abortOperation()
     subDoc(*aSubIter)->abortOperation();
   // references may be changed because they are set in attributes on the fly
   myObjs->synchronizeFeatures(aDeltaLabels, true, false, false, isRoot());
+  processPersistentResult();
 }
 
 bool Model_Document::isOperation() const
@@ -2363,3 +2365,18 @@ bool Model_Document::autoRecomutationState() const
 {
   return !generalLabel().FindChild(TAG_CURRENT_TRANSACTION).IsAttribute(kAutoRecomputationID);
 }
+
+bool Model_Document::processPersistentResult(const bool isAddedNewCopy)
+{
+    std::list<FeaturePtr> aSubFeatures = allFeatures();
+    for(auto& aFeat: aSubFeatures){
+        if(aFeat->lastResult() && aFeat->lastResult()->isPersistent()){
+            ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aFeat->lastResult());
+            if(aBody)
+                aBody->nullifyTempCopy();
+            
+            if(isAddedNewCopy)
+                ModelAPI_Tools::increaseCopyAmount(aFeat->lastResult());
+        }
+    }
+}
index 0017589196a7ca69e9475d5951634b6c60e8169b..23352cad0ae38b580246781b6f535b3e0a4f8abe 100644 (file)
@@ -412,6 +412,9 @@ class Model_Document : public ModelAPI_Document
   /// Returns the current automatic recomputation flag: true means enabled
   bool autoRecomutationState() const;
 
+  /// Process persistent result: do some necessary actions with persistent results while finish/abort operation
+  bool processPersistentResult(const bool isAddedNewCopy = false);
+
   friend class Model_Application;
   friend class Model_Session;
   friend class Model_Update;
index 544b5bef8bba5879774fbbc71db22b6de98cccef..f608219fecc5e84e920d19a57c3fddf3caa66254 100644 (file)
@@ -1126,8 +1126,7 @@ static void collectReferences(std::shared_ptr<ModelAPI_Data> theData,
   }
 }
 
-void Model_Objects::synchronizeBackRefs()
-{
+void Model_Objects::synchronizeBackRefs(){
   // collect all back references in the separated container: to update everything at once,
   // without additional Concealment switching on and off: only the final modification
 
index f6bc7d31a6154e3a4064b34baa34b5b867300c22..b61716217bcccc8865a3d31785fb6aca9f004c3a 100644 (file)
@@ -44,10 +44,18 @@ Standard_GUID kIsConnectedTopology("e51392e0-3a4d-405d-8e36-bbfe19858ef5");
 // if this attribute exists, the connected topology flag must be recomputed
 Standard_GUID kUpdateConnectedTopology("01ef7a45-0bec-4266-b0b4-4aa570921818");
 
+// consts for creating copy
+const std::string COPY_FEATURE = "Copy";
+const std::string COPY_ATTR_OBJECTS = "objects";
+const std::string COPY_ATTR_NUMBER = "number";
+const std::string COPY_ATTR_NAMESUF = "name_suffix";
+
 Model_ResultBody::Model_ResultBody() : ModelAPI_ResultBody()
 {
   myBuilder = new Model_BodyBuilder(this);
   myLastConcealed = false;
+  myTempCopy = nullptr;
+  myIsBlockedNewCopy = false;
   updateSubs(shape()); // in case of open, etc.
 }
 
@@ -497,6 +505,43 @@ static void collectSubs(
   }
 }
 
+std::shared_ptr<ModelAPI_Result> Model_ResultBody::getCopyToSwallow()
+{
+    if(!isPersistent() || myIsBlockedNewCopy)
+      return nullptr;
+
+    std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
+    if(!aDoc)
+      return nullptr;
+
+    if(myTempCopy)
+      return myTempCopy;
+
+    ResultPtr aCopyResult(nullptr);
+    FeaturePtr aCopyFeature = aDoc->addFeature(COPY_FEATURE);
+    if(aCopyFeature){
+        myIsBlockedNewCopy = true;
+        ResultPtr context = std::dynamic_pointer_cast<ModelAPI_Result>(shared_from_this());
+        aCopyFeature->selectionList(COPY_ATTR_OBJECTS)->append(context, shape());
+        aCopyFeature->integer(COPY_ATTR_NUMBER)->setValue(1);
+        aCopyFeature->integer(COPY_ATTR_NAMESUF)->setValue(ModelAPI_Tools::getCopyAmount(context));
+        aCopyFeature->setInHistory(aCopyFeature,false);
+        aCopyFeature->execute();
+        aCopyFeature->data()->execState(ModelAPI_StateDone);
+        aCopyResult = aCopyFeature->lastResult();
+        ModelAPI_Tools::setIsCopyToSwallow(aCopyResult, true);
+        ModelAPI_Tools::setOriginalObject(aCopyResult, context);
+        myTempCopy = aCopyResult;
+        myIsBlockedNewCopy = false;
+    }
+    return myTempCopy;
+}
+
+void Model_ResultBody::nullifyTempCopy()
+{
+    myTempCopy = nullptr;
+}
+
 void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
   const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
 {
index bda42cdf5a33b8be02050ab5df5c295b84086aa1..9dc28fd2e9d064facb9dd95ac165b41e2950ee5c 100644 (file)
@@ -36,7 +36,7 @@
 * of result must be optimized.
 * Also provides a container of sub-body result in case it is compound or compsolid.
 */
-class Model_ResultBody : public ModelAPI_ResultBody
+class Model_ResultBody : public ModelAPI_ResultBody, public std::enable_shared_from_this<Model_ResultBody> 
 {
   /// Sub-bodies if this is compsolid or compound: zero-based index to subs
   std::vector<ResultBodyPtr> mySubs;
@@ -52,6 +52,10 @@ class Model_ResultBody : public ModelAPI_ResultBody
   bool myIsGenerated;
   /// Map from old shape to list of new shapes, cash for computeOldForSub method
   TopTools_DataMapOfShapeListOfShape myHistoryCash;
+  /// Store temporary copy of persistent result during one operation
+  std::shared_ptr<ModelAPI_Result> myTempCopy;
+  /// Auxiliary, helps to prevent creating copy when it is prohibited (for example prevent recursive copy)
+  bool myIsBlockedNewCopy;
 
 public:
 
@@ -123,6 +127,13 @@ public:
   /// Returns empty vector if not found.
   MODEL_EXPORT virtual const std::vector<int>& findShapeColor(const std::wstring& theShapeName);
 
+  /// For persistent result - creates/return a copy of this result, so the copy can be swallowed
+  /// by the new feature instead of original result
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Result> getCopyToSwallow();
+
+  MODEL_EXPORT virtual void nullifyTempCopy();
+
+
 protected:
   /// Makes a body on the given feature
   Model_ResultBody();
index 4a86874e4127192232b01c736002062ba1106899..abab2b62d021c4414ea1bc0eae7d28112dfa5bbf 100644 (file)
 
 #include <Model_Tools.h>
 #include <Model_Data.h>
+#include <Model_Document.h>
 
 #include <ModelAPI_Document.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Result.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_AttributeSelection.h>
+#include <ModelAPI_AttributeSelectionList.h>
+#include <ModelAPI_Tools.h>
+#include <GeomAPI_Shape.h>
 
 #include <ConstructionPlugin_Axis.h>
 #include <ConstructionPlugin_Plane.h>
@@ -183,3 +188,30 @@ void Model_Tools::labelsOfCoordinates(std::set<TCollection_AsciiString>& theCoor
     }
   }
 }
+
+void Model_Tools::substituteSelectionWithCopy(FeaturePtr &theFeature, ResultPtr &theResult, AttributeSelectionPtr &theSelAttr)
+{
+    if(!theResult || !theResult->isPersistent() || !theSelAttr)
+      return;
+
+    //if the result of the feature already a copy to be swallowed - skip
+    if(ModelAPI_Tools::isCopyToSwallow(theFeature->lastResult()))
+      return;
+    
+    ResultBodyPtr aBodyRes = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
+    ResultPtr aCopyResult = aBodyRes->getCopyToSwallow();
+
+    if(aCopyResult){
+        GeomShapePtr aGeomObj = theSelAttr->value();
+        GeomAPI_Shape::ShapeType aCurType = aGeomObj->shapeType();
+        ListOfShape aCopySubs = aCopyResult->shape()->subShapes(aCurType,true);
+        for(auto aCopySub: aCopySubs)
+        {
+            if(aCopySub->isSameGeometry(aGeomObj))
+            {
+                theSelAttr->setValue(aCopyResult, aCopySub);
+                return;
+            }
+        }
+    }
+}
index bdd857e39ae8977721250d82b2f538f86b2c06fe..8de09e39c97f9c4eff40db9f21b874f1e0966e86 100644 (file)
@@ -24,6 +24,9 @@
 
 #include <TDF_Label.hxx>
 #include <TDF_RelocationTable.hxx>
+#include <ModelAPI_Result.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_AttributeSelection.h>
 
 #include <memory>
 #include <set>
@@ -51,6 +54,12 @@ public:
   static void labelsOfCoordinates(
       std::set<TCollection_AsciiString>& theCoordinateLabels,
       Handle(TDF_RelocationTable) theRelocTable);
+
+  /// Create a copy of persistent result and substitute the original selecttion attribute with a copy.
+  /// \param theFeature a feature that wants to swallow the result
+  /// \param theResult a persistent result to copy
+  /// \param theSelAttr an attribute to substitute
+  static void substituteSelectionWithCopy(FeaturePtr &theFeature, ResultPtr &theResult, AttributeSelectionPtr &theSelAttr);
 };
 
 #endif
index a2fb93b5adbfd7960f530b1c4a738704c6668565..f129ade60bf32c943c9286e6b8682252284a11fa 100644 (file)
@@ -21,6 +21,7 @@
 #include <Model_Document.h>
 #include <Model_Data.h>
 #include <Model_Objects.h>
+#include <Model_Tools.h>
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Document.h>
@@ -96,7 +97,6 @@ bool Model_Update::addModified(FeaturePtr theFeature, FeaturePtr theReason) {
   if (!theFeature->data()->isValid())
     return false; // delete an extrusion created on the sketch
 
-
   bool isNotExecuted = theFeature->isPersistentResult() &&
     !std::dynamic_pointer_cast<Model_Document>((theFeature)->document())->executeFeatures();
   if (isNotExecuted) {
@@ -889,7 +889,12 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
     ObjectPtr aContext = aSel->context();
     // update argument only if the referenced object is ready to use
     if (aContext.get() && !aContext->isDisabled()) {
+      std::shared_ptr<ModelAPI_Result> resultPtr = std::dynamic_pointer_cast<ModelAPI_Result>(aContext);
+      if(resultPtr && resultPtr->isPersistent()){
+        Model_Tools::substituteSelectionWithCopy(theFeature, resultPtr, aSel);
+      }
       if (isReason(theFeature, aContext)) {
+
         if (!aSel->update()) { // this must be done on execution since it may be long operation
           bool isObligatory = !aFactory->isNotObligatory(
             theFeature->getKind(), theFeature->data()->id(aSel)) &&
@@ -927,6 +932,12 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
       if (aSelAttr) {
         ObjectPtr aContext = aSelAttr->context();
+
+        std::shared_ptr<ModelAPI_Result> resultPtr = std::dynamic_pointer_cast<ModelAPI_Result>(aContext);
+        if(resultPtr && resultPtr->isPersistent()){
+            Model_Tools::substituteSelectionWithCopy(theFeature, resultPtr, aSelAttr);
+        }
+
         // update argument only if the referenced object is ready to use
         if (aContext.get() && !aContext->isDisabled()) {
           if (isReason(theFeature, aContext)) {
index e4a09c9b6b1de47e300b5a78c85156f729e1f4f6..92263030f8532ffc1cee5b3def884b069127fc7c 100644 (file)
@@ -28,6 +28,7 @@
 #include <map>
 
 class ModelAPI_Object;
+class ModelAPI_Result;
 class ModelAPI_Feature;
 class ModelAPI_CompositeFeature;
 class Model_Objects;
index e8d3adffeb6f11f3992a130e339d27aa7d8c1fb3..76ba6c0e95a1133d75903f89829c62507a22e16a 100644 (file)
@@ -23,6 +23,8 @@
 #include "ModelAPI_Attribute.h"
 #include <ModelAPI_Result.h>
 
+#include <utility>
+
 class GeomAPI_Edge;
 class GeomAPI_Pnt;
 
@@ -128,6 +130,13 @@ class ModelAPI_AttributeSelection : public ModelAPI_Attribute
   /// Returns theRemove true if this attribute must be removed (become deleted)
   MODELAPI_EXPORT virtual void updateInHistory(bool& theRemove) = 0;
 
+  /// Return true if context of the atribute is a copy of persistent result
+  MODELAPI_EXPORT virtual bool isCopyToSwallow() = 0;
+
+  /// Return original context and shape of this copy atribute
+  MODELAPI_EXPORT virtual std::pair<ResultPtr, std::shared_ptr<GeomAPI_Shape>> getOriginalContext() = 0;
+
+
  protected:
   /// Objects are created for features automatically
   MODELAPI_EXPORT ModelAPI_AttributeSelection();
index 3c25a0d0f9b1aa0471137524df719f170c3e3153..bc8ef3ecbeb7c596c4327f1dda8f9fa82d16ff94 100644 (file)
@@ -24,6 +24,9 @@
 #include <ModelAPI_Result.h>
 #include <ModelAPI_Filter.h>
 
+#include <list>
+#include <utility>
+
 class GeomAPI_Pnt;
 class GeomAPI_Shape;
 
@@ -151,6 +154,9 @@ public:
     myMakeCopy = theFlag;
   }
 
+  /// Return true if contain at least one attr witch context is a copy of persistent result.
+  MODELAPI_EXPORT virtual bool isContainCopiesToSwallow() = 0;
+
 protected:
   /// Default constructor
   MODELAPI_EXPORT ModelAPI_AttributeSelectionList() : ModelAPI_Attribute()
index 8518d284dda1c78b5f1764fd40dc63378c9cf141..5e4f21d1953e76b4647d5224d4b326a48e26870b 100644 (file)
@@ -75,7 +75,7 @@ class MODELAPI_EXPORT ModelAPI_Data
   /// Returns the name of the feature visible by the user in the object browser
   virtual std::wstring name() = 0;
   /// Defines the name of the feature visible by the user in the object browser
-  virtual void setName(const std::wstring& theName) = 0;
+  virtual void setName(const std::wstring& theName, bool isUserDefined = true) = 0;
   /// Return \c true if the object has been renamed by the user
   virtual bool hasUserDefinedName() const = 0;
 
index 2c3bdc9f9acaebbc921fc95b367c14249921db77..cf64c36e96c44657957819971895bfc9962745ce 100644 (file)
@@ -24,6 +24,8 @@
 #include <ModelAPI_AttributeIntArray.h>
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeBoolean.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeReference.h>
 
 #include <GeomAPI_Shape.h>
 
@@ -52,6 +54,35 @@ void ModelAPI_Result::initAttributes()
   // Add the "Bring To Front" attribute to the Result base class, as we may support it in the future
   // for all type of results. Actually, only ResultGroups are supported.
   aData->addAttribute(BRING_TO_FRONT_ID(), ModelAPI_AttributeBoolean::typeId())->setIsArgument(false);
+
+  AttributeBooleanPtr aIsPersistentAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
+    aData->addAttribute(IS_PERSISTENT_ID(), ModelAPI_AttributeBoolean::typeId()));
+  aIsPersistentAttr->setIsArgument(false);
+  if (!aIsPersistentAttr->isInitialized()){
+    aIsPersistentAttr->setValue(false);
+  }
+
+  AttributeBooleanPtr aCopyAttr = std::dynamic_pointer_cast<ModelAPI_AttributeBoolean>(
+    aData->addAttribute(IS_COPY_TO_SWALLOW(), ModelAPI_AttributeBoolean::typeId()));
+  aCopyAttr->setIsArgument(false);
+  if (!aCopyAttr->isInitialized()){
+    aCopyAttr->setValue(false);
+  }
+
+  AttributeReferencePtr anOrigRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeReference>(
+    aData->addAttribute(ORIGINAL_REFERENCE(), ModelAPI_AttributeReference::typeId()));
+  anOrigRefAttr->setIsArgument(false);
+  if (!anOrigRefAttr->isInitialized()){
+    anOrigRefAttr->setValue(nullptr);
+  }
+
+  AttributeIntegerPtr aCopyAmountAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>(
+    aData->addAttribute(COPY_AMOUNT(), ModelAPI_AttributeInteger::typeId()));
+  aCopyAmountAttr->setIsArgument(false);
+
+  if (!aCopyAmountAttr->isInitialized()){
+    aCopyAmountAttr->setValue(0);
+  }
 }
 
 bool ModelAPI_Result::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, const bool theFlag)
@@ -86,6 +117,23 @@ bool ModelAPI_Result::isDisabled()
   return myIsDisabled;
 }
 
+void ModelAPI_Result::setPersistent(const bool theValue)
+{
+  AttributeBooleanPtr aAttr = data()->boolean(ModelAPI_Result::IS_PERSISTENT_ID());
+  if (aAttr.get() != NULL) {
+    aAttr->setValue(theValue);
+  }
+}
+
+bool ModelAPI_Result::isPersistent()
+{
+  AttributeBooleanPtr aAttr = data()->boolean(ModelAPI_Result::IS_PERSISTENT_ID());
+  if (aAttr.get() != NULL) {
+    return aAttr->value();
+  }
+  return false;
+}
+
 bool ModelAPI_Result::isConcealed()
 {
   return myIsConcealed;
@@ -109,6 +157,12 @@ void ModelAPI_Result::setIsConcealed(const bool theValue, const bool /*theForced
   }
 }
 
+// std::shared_ptr<ModelAPI_Result> ModelAPI_Result::createCopyToSwallow()
+// {
+//     return std::shared_ptr<ModelAPI_Result>();
+// }
+
+
 std::shared_ptr<GeomAPI_Shape> ModelAPI_Result::shape()
 {
   return std::shared_ptr<GeomAPI_Shape>();
index e82ea2f355d123eb0f36f26dd450ecac3567a876..0d189f86265073ed49d1ed1efe7534b433ac1267 100644 (file)
@@ -35,6 +35,8 @@ typedef std::list<std::shared_ptr<GeomAPI_Shape> > ListOfShape;
  */
 class ModelAPI_Result : public ModelAPI_Object
 {
+//   std::shared_ptr<ModelAPI_Result> myTempCopy;
+//   bool myIsCreatingCopy;
   bool myIsConcealed; ///< the result is concealed from the data tree (referenced by other objects)
  protected:
   bool myIsDisabled; ///< the result is disabled: removed for the user, but keeps the general info
@@ -97,6 +99,39 @@ class ModelAPI_Result : public ModelAPI_Object
     return MY_BRING_TO_FRONT_ID;
   }
 
+  /// Reference to the IsPersistent flag of the result.
+  /// Persistent means the result will remain even after generating a new feature from it.
+  /// The bool value is used.
+  inline static const std::string& IS_PERSISTENT_ID()
+  {
+    static const std::string MY_IS_PERSISTENT_ID("Is_persistent");
+    return MY_IS_PERSISTENT_ID;
+  }
+
+  ///True if the result is a copy of persistent result.
+  /// The bool value is used.
+  inline static const std::string& IS_COPY_TO_SWALLOW()
+  {
+    static const std::string MY_COPY_TO_SWALLOW("is_copy_to_swallow");
+    return MY_COPY_TO_SWALLOW;
+  }
+
+  /// If this result is a copy to swallow - stores the original result in this attribute
+  /// The reference value is used.
+  inline static const std::string& ORIGINAL_REFERENCE()
+  {
+    static const std::string MY_ORIGINAL_REFERENCE("original_reference");
+    return MY_ORIGINAL_REFERENCE;
+  }
+
+  /// Reference to the amount of copies of the result.
+  /// The int value is used.
+  inline static const std::string& COPY_AMOUNT()
+  {
+    static const std::string MY_COPY_AMOUNT("Copy_amount");
+    return MY_COPY_AMOUNT;
+  }
+
   /// Returns true if the result is concealed from the data tree (referenced by other objects)
   MODELAPI_EXPORT virtual bool isConcealed();
 
@@ -115,6 +150,16 @@ class ModelAPI_Result : public ModelAPI_Object
   /// Returns the result is disabled or not.
   MODELAPI_EXPORT virtual bool isDisabled();
 
+  /// Set whether the result should be persistent or not (persistent means the result will
+  /// remain even after generating a new feature from it)
+  MODELAPI_EXPORT virtual void setPersistent(const bool theValue);
+
+  /// Returns the result is persistent or not.
+  MODELAPI_EXPORT virtual bool isPersistent();
+
+//   /// For persistent result - creates a copy to be swallowed by the new feature instead of original result
+//   MODELAPI_EXPORT virtual std::shared_ptr<ModelAPI_Result> createCopyToSwallow();
+
   /// Request for initialization of data model of the result: adding all attributes
   MODELAPI_EXPORT virtual void initAttributes();
 
index 223c91d55ea72936d20677622fd33d4ddf6270af..1d9ca77d015ef130025d4beec20c823a4ecb2e59 100644 (file)
@@ -216,6 +216,12 @@ public:
   MODELAPI_EXPORT virtual const std::vector<int>& findShapeColor(
     const std::wstring& theShapeName) = 0;
 
+  /// For persistent result - creates/return a copy of this result, so the copy can be swallowed
+  //  by the new feature instead of original result
+  MODELAPI_EXPORT virtual std::shared_ptr<ModelAPI_Result> getCopyToSwallow() = 0;
+
+  MODELAPI_EXPORT virtual void nullifyTempCopy() = 0;
+
 
 protected:
   /// Default constructor accessible only from Model_Objects
index 508ca38e8ed97fcdc92c6849bb28d7086ce012bf..2ef9b0857a9dd62dec4b638fa380c1e9c22ff7d2 100644 (file)
@@ -22,6 +22,8 @@
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_AttributeImage.h>
 #include <ModelAPI_AttributeIntArray.h>
+#include <ModelAPI_AttributeInteger.h>
+#include <ModelAPI_AttributeReference.h>
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_CompositeFeature.h>
 #include <ModelAPI_Document.h>
@@ -1231,6 +1233,7 @@ void setTransparency(ResultPtr theResult, double theTransparency)
   }
 }
 
+//**************************************************************
 double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult)
 {
   double aTransparency = -1;
@@ -1245,6 +1248,84 @@ double getTransparency(const std::shared_ptr<ModelAPI_Result>& theResult)
   return aTransparency;
 }
 
+//**************************************************************
+void increaseCopyAmount(std::shared_ptr<ModelAPI_Result> theResult)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeIntegerPtr anAttribute = theResult->data()->integer(ModelAPI_Result::COPY_AMOUNT());
+  if (anAttribute.get() != NULL) {
+    int aCurrentValue = anAttribute->value();
+    anAttribute->setValue(++aCurrentValue);
+  }
+
+}
+
+//**************************************************************
+int getCopyAmount(std::shared_ptr<ModelAPI_Result> theResult)
+{
+  int anAmountOfCopies = 0;
+  if (theResult.get() != NULL &&
+    theResult->data()->attribute(ModelAPI_Result::COPY_AMOUNT()).get() != NULL) {
+    AttributeIntegerPtr anIntAttr = theResult->data()->integer(ModelAPI_Result::COPY_AMOUNT());
+    if (anIntAttr.get() && anIntAttr->isInitialized()) {
+      anAmountOfCopies = anIntAttr->value();
+    }
+  }
+  return anAmountOfCopies;
+}
+
+//******************************************************
+void setIsCopyToSwallow(std::shared_ptr<ModelAPI_Result> theResult, bool theFlag)
+{
+  if (!theResult.get())
+    return;
+
+  AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::IS_COPY_TO_SWALLOW());
+  if (aAttr.get() != NULL) {
+    aAttr->setValue(theFlag);
+  }
+}
+
+//******************************************************
+bool isCopyToSwallow(std::shared_ptr<ModelAPI_Result> theResult)
+{
+  if (!theResult.get())
+    return false;
+
+  AttributeBooleanPtr aAttr = theResult->data()->boolean(ModelAPI_Result::IS_COPY_TO_SWALLOW());
+  if (aAttr.get() != NULL) {
+    return aAttr->value();
+  }
+  return false;
+}
+
+//******************************************************
+void setOriginalObject(std::shared_ptr<ModelAPI_Result> theCopyResult, std::shared_ptr<ModelAPI_Result> theOriginalResult)
+{
+  if (!theCopyResult.get())
+    return;
+
+  AttributeReferencePtr aAttr = theCopyResult->data()->reference(ModelAPI_Result::ORIGINAL_REFERENCE());
+  if (aAttr.get() != NULL) {
+    aAttr->setValue(theOriginalResult);
+  }
+}
+
+//******************************************************
+ObjectPtr getOriginalObject(std::shared_ptr<ModelAPI_Result> theCopyResult)
+{
+  if (!theCopyResult.get())
+    return;
+
+  AttributeReferencePtr aAttr = theCopyResult->data()->reference(ModelAPI_Result::ORIGINAL_REFERENCE());
+  if (aAttr.get() != NULL) {
+    return aAttr->value();
+  }
+  return nullptr;
+}
+
 void copyVisualizationAttrs(
   std::shared_ptr<ModelAPI_Result> theSource, std::shared_ptr<ModelAPI_Result> theDest)
 {
index beb380f867d783603585ba9e5107744d543283ca..597d38e268dcebbca7aa14c42f5cab6c8006169d 100644 (file)
@@ -320,6 +320,28 @@ MODELAPI_EXPORT void bringToFront(std::shared_ptr<ModelAPI_Result> theResult, bo
 
 MODELAPI_EXPORT bool isBringToFront(std::shared_ptr<ModelAPI_Result> theResult);
 
+/*! Increase copy amount of the result
+* \param[in] theResult a result object
+*/
+MODELAPI_EXPORT void increaseCopyAmount(std::shared_ptr<ModelAPI_Result> theResult);
+
+MODELAPI_EXPORT int getCopyAmount(std::shared_ptr<ModelAPI_Result> theResult);
+
+/*! Set result is copy or not
+* \param[in] theResult a result object
+*/
+MODELAPI_EXPORT void setIsCopyToSwallow(std::shared_ptr<ModelAPI_Result> theResult, bool theFlag);
+
+MODELAPI_EXPORT bool isCopyToSwallow(std::shared_ptr<ModelAPI_Result> theResult);
+
+/*! Set the original result  to a copy result
+* \param[in] theCopyResult a copy result object
+* \param[in] theOriginalResult an original result object
+*/
+MODELAPI_EXPORT void setOriginalObject(std::shared_ptr<ModelAPI_Result> theCopyResult, std::shared_ptr<ModelAPI_Result> theOriginalResult);
+
+MODELAPI_EXPORT ObjectPtr getOriginalObject(std::shared_ptr<ModelAPI_Result> theCopyResult);
+
 /*! Returns current transparency in the given result
 * \param theResult a result object
 * \return a transparency value or -1 if it was not defined
index cc22e0d1c828fb2afed210bb98dced0c9127e24a..67018cb57b62b3f6d11ec8334828cd1954450e80 100644 (file)
@@ -291,8 +291,18 @@ static void getShapeAndContext(const AttributeSelectionPtr& theAttrSelect,
                                GeomShapePtr& theShape, ResultPtr& theContext)
 {
   if (theAttrSelect->isInitialized()) {
-    theShape = theAttrSelect->value();
-    theContext = theAttrSelect->context();
+    // if(theAttrSelect->isCopyToSwallow())
+    // {
+    //     auto aPairContextShape = theAttrSelect->getOriginalContext();
+    //     theContext = aPairContextShape.first;
+    //     theShape = aPairContextShape.second;
+    // }
+    // else
+    // {
+        theShape = theAttrSelect->value();
+        theContext = theAttrSelect->context();
+    //}
+
     if (!theShape.get())
       theShape = theContext->shape();
 
@@ -736,8 +746,12 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theD
         dumpFolder(aFolder);
       else {
         FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anObjIt);
-        if (aFeature) // dump common feature
+        if (aFeature){ // dump common feature
           dumpFeature(aFeature);
+          if(aFeature->lastResult() && aFeature->lastResult()->isPersistent())
+            *this << aFeature << ".defaultResult().setPersistent(True)"  << std::endl;
+        }
+
       }
     }
   }
@@ -863,7 +877,9 @@ void ModelHighAPI_Dumper::dumpPostponed(bool theDumpFolders)
     else {
       FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
       if (aFeature)
+      {
         dumpFeature(aFeature, true);
+      }
     }
   }
   myDumpPostponedInProgress = false;
@@ -1524,33 +1540,51 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 
     GeomShapePtr aShape;
     std::string aShapeTypeStr;
+    ResultPtr aContext;
 
     bool isAdded = false;
+    bool isCopy = false;
 
     for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
       AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
-      aShape = anAttribute->value();
-      if(!aShape.get()) {
-        ResultPtr aContext = anAttribute->context();
-        if (aContext.get())
-          aShape = aContext->shape();
+      if(anAttribute->isCopyToSwallow())
+      {
+        isCopy = true;
+        auto aPairContextShape = anAttribute->getOriginalContext();
+        aContext = aPairContextShape.first;
+        aShape = aPairContextShape.second;
+        theAttrSelList->append(aContext,aShape);
+        anAttribute = theAttrSelList->value(theAttrSelList->size()-1);
       }
+      else
+      {
+        aShape = anAttribute->value();
+        if(!aShape.get()) {
+            aContext = anAttribute->context();
+            if (aContext.get())
+            aShape = aContext->shape();
+        }
 
-      if(!aShape.get()) {
-        continue;
-      }
+        if(!aShape.get()) {
+            continue;
+        }
 
-      if(isAdded) {
-        // print each attribute on separate line with the appropriate shift
-        if (aNbSpaces > 0) {
-          std::string aSpaces(aNbSpaces + 1, ' ');
-          *myDumpStorage << ",\n" << aSpaces;
-        } else
-          *myDumpStorage << ", ";
-      } else {
-        isAdded = true;
+        if(isAdded) {
+            // print each attribute on separate line with the appropriate shift
+            if (aNbSpaces > 0) {
+            std::string aSpaces(aNbSpaces + 1, ' ');
+            *myDumpStorage << ",\n" << aSpaces;
+            } else
+            *myDumpStorage << ", ";
+        } else {
+            isAdded = true;
+        }
       }
       *this << anAttribute;
+      if(isCopy)
+      {
+       theAttrSelList->removeLast();
+      }
     }
 
     // check selection list is obtained by filters
index b678584b2a3f8cc6074939f1615418e844c1a331..f8a64551e515b469094c75b0abac7283f22342de 100644 (file)
@@ -143,16 +143,16 @@ QIcon PartSet_IconFactory::getIcon(ObjectPtr theObj)
           }
           ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResult);
           if (aBody.get() && aBody->isConnectedTopology())
-            return QIcon(":pictures/compoundofsolids.png");
-          return QIcon(":pictures/compound.png");
+            return aResult->isPersistent()? QIcon(":pictures/compoundofsolids_persistent.png") : QIcon(":pictures/compoundofsolids.png");
+          return aResult->isPersistent()? QIcon(":pictures/compound_persistent.png") : QIcon(":pictures/compound.png");
         }
-        case GeomAPI_Shape::COMPSOLID: return QIcon(":pictures/compsolid.png");
-        case GeomAPI_Shape::SOLID:     return QIcon(":pictures/solid.png");
-        case GeomAPI_Shape::SHELL:     return QIcon(":pictures/shell.png");
-        case GeomAPI_Shape::FACE:      return QIcon(":pictures/face.png");
-        case GeomAPI_Shape::WIRE:      return QIcon(":pictures/wire.png");
-        case GeomAPI_Shape::EDGE:      return QIcon(":pictures/edge.png");
-        case GeomAPI_Shape::VERTEX:    return QIcon(":pictures/vertex.png");
+        case GeomAPI_Shape::COMPSOLID: return aResult->isPersistent()? QIcon(":pictures/compsolid_persistent.png") : QIcon(":pictures/compsolid.png");
+        case GeomAPI_Shape::SOLID:     return aResult->isPersistent()? QIcon(":pictures/solid_persistent.png") : QIcon(":pictures/solid.png");
+        case GeomAPI_Shape::SHELL:     return aResult->isPersistent()? QIcon(":pictures/shell_persistent.png") : QIcon(":pictures/shell.png");
+        case GeomAPI_Shape::FACE:      return aResult->isPersistent()? QIcon(":pictures/face_persistent.png") : QIcon(":pictures/face.png");
+        case GeomAPI_Shape::WIRE:      return aResult->isPersistent()? QIcon(":pictures/wire_persistent.png") : QIcon(":pictures/wire.png");
+        case GeomAPI_Shape::EDGE:      return aResult->isPersistent()? QIcon(":pictures/edge_persistent.png") :QIcon(":pictures/edge.png");
+        case GeomAPI_Shape::VERTEX:    return aResult->isPersistent()? QIcon(":pictures/vertex_persistent.png") :QIcon(":pictures/vertex.png");
         default: // [to avoid compilation warning]
           break;
       }
index 5b43656584e52835956c83072522196be2309908..c764385fe69767a3cce67150ace20d4fd7786884 100644 (file)
@@ -174,6 +174,10 @@ void XGUI_ContextMenuMgr::createActions()
   anAction->setCheckable(true);
   addAction("BRING_TO_FRONT_CMD", anAction);
 
+  anAction = ModuleBase_Tools::createAction(QIcon(), tr("Is persistent"), aDesktop);
+  anAction->setCheckable(true);
+  addAction("PERSISTENT_CMD", anAction);
+
   mySeparator1 = ModuleBase_Tools::createAction(QIcon(), "", aDesktop);
   mySeparator1->setSeparator(true);
 
@@ -362,6 +366,9 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
           action("SHOW_ISOLINES_CMD")->setEnabled(true);
           action("SHOW_ISOLINES_CMD")->setChecked(ModelAPI_Tools::isShownIsoLines(aResult));
           action("ISOLINES_CMD")->setEnabled(true);
+
+          action("PERSISTENT_CMD")->setEnabled(true);
+          action("PERSISTENT_CMD")->setChecked(aResult->isPersistent());
         }
         if (!hasFeature) {
           bool aHasSubResults = ModelAPI_Tools::hasSubResults(aResult);
@@ -419,6 +426,7 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         action("BRING_TO_FRONT_CMD")->setEnabled(hasGroupsOnly);
         action("SHOW_ISOLINES_CMD")->setEnabled(true);
         action("ISOLINES_CMD")->setEnabled(true);
+        action("PERSISTENT_CMD")->setEnabled(true);
       }
       if (hasFeature && myWorkshop->canMoveFeature()) {
         action("MOVE_CMD")->setEnabled(true);
@@ -741,6 +749,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.append(action("SHOW_ISOLINES_CMD"));
   aList.append(action("ISOLINES_CMD"));
   aList.append(action("SHOW_FEATURE_CMD"));
+  aList.append(action("PERSISTENT_CMD"));
   aList.append(mySeparator3);
   aList.append(action("DELETE_CMD"));
   // Result body menu
@@ -848,6 +857,7 @@ void XGUI_ContextMenuMgr::buildViewerMenu()
   aList.append(action("TRANSPARENCY_CMD"));
   aList.append(action("SHOW_ISOLINES_CMD"));
   aList.append(action("ISOLINES_CMD"));
+  aList.append(action("PERSISTENT_CMD"));
   aList.append(mySeparator3);
   aList.append(action("SET_VIEW_NORMAL_CMD"));
   aList.append(action("SET_VIEW_INVERTEDNORMAL_CMD"));
@@ -928,6 +938,7 @@ void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
       anActions.append(action("SHOW_ISOLINES_CMD"));
       anActions.append(action("ISOLINES_CMD"));
       anActions.append(action("CLEAN_HISTORY_CMD"));
+      anActions.append(action("PERSISTENT_CMD"));
       anActions.append(action("DELETE_CMD"));
   }
 #ifdef _DEBUG
index 0df895c850db18a1e6de7e1528bcddf0d0bdf874..e0c6323295c13c965d51074c91f87597bf0d06a4 100644 (file)
@@ -1808,6 +1808,14 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
     mySelector->clearSelection();
     Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
   }
+  else if (theId == "PERSISTENT_CMD") {
+    foreach(ObjectPtr aObj, anObjects) {
+      ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
+      if (aResult.get())
+        aResult->setPersistent(!aResult->isPersistent());
+    }
+    mySelector->clearSelection();
+  }
   else if (theId == "DEFLECTION_CMD")
     changeDeflection(anObjects);
   else if (theId == "TRANSPARENCY_CMD")
index f598306b4f82b193e297ddc6b88dbc2c3ac2bf1d..1aadf26c729bd2ae7ee9d0ddb4e9d6f994e8be85 100644 (file)
      <file>pictures/result.png</file>
      <file>pictures/find_result.png</file>
 
+     <file>pictures/compsolid_persistent.png</file>
+     <file>pictures/compoundofsolids_persistent.png</file>
+     <file>pictures/solid_persistent.png</file>
+     <file>pictures/edge_persistent.png</file>
+     <file>pictures/vertex_persistent.png</file>
+     <file>pictures/face_persistent.png</file>
+     <file>pictures/compound_persistent.png</file>
+     <file>pictures/shell_persistent.png</file>
+     <file>pictures/wire_persistent.png</file>
+
      <file>pictures/eyeclosed.png</file>
      <file>pictures/eyemiclosed.png</file>
      <file>pictures/eyeopen.png</file>
diff --git a/src/XGUI/pictures/compound_persistent.png b/src/XGUI/pictures/compound_persistent.png
new file mode 100755 (executable)
index 0000000..03347e3
Binary files /dev/null and b/src/XGUI/pictures/compound_persistent.png differ
diff --git a/src/XGUI/pictures/compoundofsolids_persistent.png b/src/XGUI/pictures/compoundofsolids_persistent.png
new file mode 100755 (executable)
index 0000000..a7c0432
Binary files /dev/null and b/src/XGUI/pictures/compoundofsolids_persistent.png differ
diff --git a/src/XGUI/pictures/compsolid_persistent.png b/src/XGUI/pictures/compsolid_persistent.png
new file mode 100755 (executable)
index 0000000..ec9ab45
Binary files /dev/null and b/src/XGUI/pictures/compsolid_persistent.png differ
diff --git a/src/XGUI/pictures/edge_persistent.png b/src/XGUI/pictures/edge_persistent.png
new file mode 100755 (executable)
index 0000000..d58fae3
Binary files /dev/null and b/src/XGUI/pictures/edge_persistent.png differ
diff --git a/src/XGUI/pictures/face_persistent.png b/src/XGUI/pictures/face_persistent.png
new file mode 100755 (executable)
index 0000000..847fcc1
Binary files /dev/null and b/src/XGUI/pictures/face_persistent.png differ
diff --git a/src/XGUI/pictures/shell_persistent.png b/src/XGUI/pictures/shell_persistent.png
new file mode 100755 (executable)
index 0000000..da6f908
Binary files /dev/null and b/src/XGUI/pictures/shell_persistent.png differ
diff --git a/src/XGUI/pictures/solid_persistent.png b/src/XGUI/pictures/solid_persistent.png
new file mode 100755 (executable)
index 0000000..fc74b0c
Binary files /dev/null and b/src/XGUI/pictures/solid_persistent.png differ
diff --git a/src/XGUI/pictures/vertex_persistent.png b/src/XGUI/pictures/vertex_persistent.png
new file mode 100755 (executable)
index 0000000..3915e06
Binary files /dev/null and b/src/XGUI/pictures/vertex_persistent.png differ
diff --git a/src/XGUI/pictures/wire_persistent.png b/src/XGUI/pictures/wire_persistent.png
new file mode 100755 (executable)
index 0000000..138a261
Binary files /dev/null and b/src/XGUI/pictures/wire_persistent.png differ