Salome HOME
Correction of icon
[modules/shaper.git] / src / Model / Model_Document.cpp
index fb00ed5bf3f3c43e29ecf690de1d39317e8ca79b..0d5a39941290618b33ec3e5bbba5e3f945633225 100644 (file)
@@ -75,7 +75,8 @@ static TCollection_ExtendedString DocFileName(const char* theFileName, const std
 {
   TCollection_ExtendedString aPath((const Standard_CString) theFileName);
   // remove end-separators
-  while(aPath.Length() && (aPath.Value(aPath.Length()) == '\\' || aPath.Value(aPath.Length()) == '/'))
+  while(aPath.Length() && 
+        (aPath.Value(aPath.Length()) == '\\' || aPath.Value(aPath.Length()) == '/'))
     aPath.Remove(aPath.Length());
   aPath += _separator_;
   aPath += theID.c_str();
@@ -548,8 +549,12 @@ FeaturePtr Model_Document::addFeature(std::string theID)
   FeaturePtr aFeature = ModelAPI_Session::get()->createFeature(theID);
   if (!aFeature)
     return aFeature;
-  std::shared_ptr<Model_Document> aDocToAdd = std::dynamic_pointer_cast<Model_Document>(
-      aFeature->documentToAdd());
+  Model_Document* aDocToAdd;
+  if (aFeature->documentToAdd().get()) { // use the customized document to add
+    aDocToAdd = std::dynamic_pointer_cast<Model_Document>(aFeature->documentToAdd()).get();
+  } else { // if customized is not presented, add to "this" document
+    aDocToAdd = this;
+  }
   if (aFeature) {
     TDF_Label aFeatureLab;
     if (!aFeature->isAction()) {  // do not add action to the data model
@@ -577,10 +582,10 @@ FeaturePtr Model_Document::addFeature(std::string theID)
 }
 
 /// Appenad to the array of references a new referenced label.
-/// If theIndex is not -1, removes element at thisindex, not theReferenced.
+/// If theIndex is not -1, removes element at this index, not theReferenced.
 /// \returns the index of removed element
-static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, const int theIndex =
-                                  -1)
+static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, 
+  const int theIndex = -1)
 {
   int aResult = -1;  // no returned
   Handle(TDataStd_ReferenceArray) aRefs;
@@ -685,6 +690,22 @@ void Model_Document::removeFeature(FeaturePtr theFeature/*, const bool theCheck*
   }
 }
 
+void Model_Document::addToHistory(const std::shared_ptr<ModelAPI_Object> theObject)
+{
+  TDF_Label aFeaturesLab = featuresLabel();
+  std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theObject->data());
+  if (!aData) {
+      return;  // not found feature => do not remove
+  }
+  TDF_Label aFeatureLabel = aData->label().Father();
+  // store feature in the history of features array
+  if (theObject->isInHistory()) {
+    AddToRefArray(aFeaturesLab, aFeatureLabel);
+  } else {
+    RemoveFromRefArray(aFeaturesLab, aFeatureLabel);
+  }
+}
+
 FeaturePtr Model_Document::feature(TDF_Label& theLabel) const
 {
   if (myObjs.IsBound(theLabel))
@@ -903,9 +924,15 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
     Model_Application::getApplication()->getDocument(myID);
   // after all updates, sends a message that groups of features were created or updated
   Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aDispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static Events_ID aCreateEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
+  static Events_ID anUpdateEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+  static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   aLoop->activateFlushes(false);
 
-  // update all objects by checking are they of labels or not
+  // update all objects by checking are they on labels or not
   std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
   TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
   for (; aLabIter.More(); aLabIter.Next()) {
@@ -914,8 +941,8 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
     if (!myObjs.IsBound(aFeatureLabel)) {  // a new feature is inserted
       // create a feature
       aFeature = ModelAPI_Session::get()->createFeature(
-          TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
-              .ToCString());
+        TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get())
+        .ToCString());
       if (!aFeature) {  // somethig is wrong, most probably, the opened document has invalid structure
         Events_Error::send("Invalid type of object in the document");
         aLabIter.Value()->Label().ForgetAllAttributes();
@@ -927,18 +954,16 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
       initData(aFeature, aFeatureLabel, TAG_FEATURE_ARGUMENTS);
 
       // event: model is updated
-      static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-      ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
+      ModelAPI_EventCreator::get()->sendUpdated(aFeature, aCreateEvent);
     } else {  // nothing is changed, both iterators are incremented
       aFeature = myObjs.Find(aFeatureLabel);
       aKeptFeatures.insert(aFeature);
       if (theMarkUpdated) {
-        static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_UPDATED);
-        ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
+        ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent);
       }
     }
   }
-  // update results of thefeatures (after features created because they may be connected, like sketch and sub elements)
+  // update results of the features (after features created because they may be connected, like sketch and sub elements)
   std::list<FeaturePtr> aComposites; // composites must be updated after their subs (issue 360)
   TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID());
   for (; aLabIter2.More(); aLabIter2.Next()) {
@@ -959,23 +984,20 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
   NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator aFIter(myObjs);
   while (aFIter.More()) {
     if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
-        && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
-      FeaturePtr aFeature = aFIter.Value();
-      // event: model is updated
-      //if (aFeature->isInHistory()) {
+      && aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
+        FeaturePtr aFeature = aFIter.Value();
+        // event: model is updated
+        //if (aFeature->isInHistory()) {
         ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
-      //}
-      // results of this feature must be redisplayed (hided)
-      static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
-      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-      // redisplay also removed feature (used for sketch and AISObject)
-      ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
-      aFeature->erase();
-      // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
-      myObjs.UnBind(aFIter.Key());
-      // reinitialize iterator because unbind may corrupt the previous order in the map
-      aFIter.Initialize(myObjs);
+        //}
+        // results of this feature must be redisplayed (hided)
+        // redisplay also removed feature (used for sketch and AISObject)
+        ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent);
+        aFeature->erase();
+        // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter
+        myObjs.UnBind(aFIter.Key());
+        // reinitialize iterator because unbind may corrupt the previous order in the map
+        aFIter.Initialize(myObjs);
     } else
       aFIter.Next();
   }
@@ -987,11 +1009,11 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t
   myExecuteFeatures = false;
   aLoop->activateFlushes(true);
 
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_DELETED));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TOHIDE));
+  aLoop->flush(aCreateEvent);
+  aLoop->flush(aDeleteEvent);
+  aLoop->flush(anUpdateEvent);
+  aLoop->flush(aRedispEvent);
+  aLoop->flush(aToHideEvent);
   myExecuteFeatures = true;
 }
 
@@ -1031,7 +1053,8 @@ void Model_Document::synchronizeBackRefs()
     if (aFData) {
       std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
       aFData->referencesToObjects(aRefs);
-      std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRefsIter = aRefs.begin();
+      std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator 
+        aRefsIter = aRefs.begin();
       for(; aRefsIter != aRefs.end(); aRefsIter++) {
         std::list<ObjectPtr>::iterator aRefTo = aRefsIter->second.begin();
         for(; aRefTo != aRefsIter->second.end(); aRefTo++) {
@@ -1078,7 +1101,11 @@ void Model_Document::storeResult(std::shared_ptr<ModelAPI_Data> theFeatureData,
   theResult->setDoc(aThis);
   initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS);
   if (theResult->data()->name().empty()) {  // if was not initialized, generate event and set a name
-    theResult->data()->setName(theFeatureData->name());
+    std::stringstream aNewName;
+    aNewName<<theFeatureData->name();
+    if (theResultIndex > 0) // if there are several results, add unique prefix starting from second
+      aNewName<<"_"<<theResultIndex + 1;
+    theResult->data()->setName(aNewName.str());
   }
 }