Salome HOME
Merge branch 'Dev_0.6.1' of newgeom:newgeom into Dev_0.6.1
[modules/shaper.git] / src / Model / Model_Document.cpp
index 557ee00e59e6fc53e2e96ee73eccc9793c3df541..1f5eedfe9a7a11639486087bc77cb32616532026 100644 (file)
@@ -40,7 +40,7 @@
 # define _separator_ '/'
 #endif
 
-static const int UNDO_LIMIT = 10;  // number of possible undo operations
+static const int UNDO_LIMIT = 1000;  // number of possible undo operations (big for sketcher)
 
 static const int TAG_GENERAL = 1;  // general properties tag
 static const int TAG_OBJECTS = 2;  // tag of the objects sub-tree (features, results)
@@ -50,6 +50,11 @@ static const int TAG_HISTORY = 3;  // tag of the history sub-tree (python dump)
 static const int TAG_FEATURE_ARGUMENTS = 1;  ///< where the arguments are located
 static const int TAG_FEATURE_RESULTS = 2;  ///< where the results are located
 
+///
+/// 0:1:2 - where features are located
+/// 0:1:2:N:1 - data of the feature N
+/// 0:1:2:N:2:K:1 - data of the K result of the feature N
+
 Model_Document::Model_Document(const std::string theID, const std::string theKind)
     : myID(theID), myKind(theKind),
       myDoc(new TDocStd_Document("BinOcaf"))  // binary OCAF format
@@ -99,7 +104,7 @@ bool Model_Document::load(const char* theFileName)
   if (isError) {
     switch (aStatus) {
       case PCDM_RS_UnknownDocument:
-        Events_Error::send(std::string("Can not open document: unknown format"));
+        Events_Error::send(std::string("Can not open document"));
         break;
       case PCDM_RS_AlreadyRetrieved:
         Events_Error::send(std::string("Can not open document: already opened"));
@@ -200,33 +205,29 @@ bool Model_Document::save(const char* theFileName, std::list<std::string>& theRe
   myTransactionSave = myTransactionsCounter;
   if (isDone) {  // save also sub-documents if any
     theResults.push_back(TCollection_AsciiString(aPath).ToCString());
-    std::set<std::string>::iterator aSubIter = mySubs.begin();
-    for (; aSubIter != mySubs.end() && isDone; aSubIter++) {
-      isDone = subDoc(*aSubIter)->save(theFileName, theResults);
-    }
-    if (isDone) { // also try to copy the not-activated sub-documents
-      // they are not in mySubs but as ResultParts
-      int aPartsNum = size(ModelAPI_ResultPart::group());
-      for(int aPart = 0; aPart < aPartsNum; aPart++) {
-        ResultPartPtr aPartRes = std::dynamic_pointer_cast<ModelAPI_ResultPart>
-          (object(ModelAPI_ResultPart::group(), aPart));
-        if (aPartRes) {
-          std::string aDocName = aPartRes->data()->name();
-          if (!aDocName.empty() && mySubs.find(aDocName) == mySubs.end()) {
-            // just copy file
-            TCollection_AsciiString aSubPath(DocFileName(anApp->loadPath().c_str(), aDocName));
-            OSD_Path aPath(aSubPath);
-            OSD_File aFile(aPath);
-            if (aFile.Exists()) {
-              TCollection_AsciiString aDestinationDir(DocFileName(theFileName, aDocName));
-              OSD_Path aDestination(aDestinationDir);
-              aFile.Copy(aDestination);
-            } else {
-              Events_Error::send(
-                std::string("Can not open file ") + aSubPath.ToCString() + " for saving");
-            }
+    const std::set<std::string> aSubs = subDocuments(false);
+    std::set<std::string>::iterator aSubIter = aSubs.begin();
+    for (; aSubIter != aSubs.end() && isDone; aSubIter++) {
+      if (anApp->isLoadByDemand(*aSubIter)) { 
+        // copy not-activated document that is not in the memory
+        std::string aDocName = *aSubIter;
+        if (!aDocName.empty()) {
+          // just copy file
+          TCollection_AsciiString aSubPath(DocFileName(anApp->loadPath().c_str(), aDocName));
+          OSD_Path aPath(aSubPath);
+          OSD_File aFile(aPath);
+          if (aFile.Exists()) {
+            TCollection_AsciiString aDestinationDir(DocFileName(theFileName, aDocName));
+            OSD_Path aDestination(aDestinationDir);
+            aFile.Copy(aDestination);
+            theResults.push_back(aDestinationDir.ToCString());
+          } else {
+            Events_Error::send(
+              std::string("Can not open file ") + aSubPath.ToCString() + " for saving");
           }
         }
+      } else { // simply save opened document
+        isDone = subDoc(*aSubIter)->save(theFileName, theResults);
       }
     }
   }
@@ -240,10 +241,10 @@ void Model_Document::close(const bool theForever)
     aPM->setActiveDocument(aPM->moduleDocument());
   }
   // close all subs
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->close(theForever);
-  mySubs.clear();
 
   // close for thid document needs no transaction in this document
   std::static_pointer_cast<Model_Session>(Model_Session::get())->setCheckTransactions(false);
@@ -288,8 +289,9 @@ void Model_Document::startOperation()
     myDoc->NewCommand();
   }
   // new command for all subs
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->startOperation();
 }
 
@@ -347,8 +349,9 @@ void Model_Document::finishOperation()
         ->setCheckTransactions(true);  // for nested transaction commit
 
   // finish for all subs first: to avoid nested finishing and "isOperation" calls problems inside
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->finishOperation();
 
   if (myNestedNum != -1)  // this nested transaction is owervritten
@@ -382,8 +385,9 @@ void Model_Document::abortOperation()
   }
   synchronizeFeatures(true, false); // references were not changed since transaction start
   // abort for all subs
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->abortOperation();
 }
 
@@ -405,8 +409,9 @@ bool Model_Document::canUndo()
       && myTransactionsCounter != 0 /* for omitting the first useless transaction */)
     return true;
   // check other subs contains operation that can be undoed
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     if (subDoc(*aSubIter)->canUndo())
       return true;
   return false;
@@ -421,8 +426,9 @@ void Model_Document::undo()
     myDoc->Undo();
   synchronizeFeatures(true, true);
   // undo for all subs
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->undo();
 }
 
@@ -431,8 +437,9 @@ bool Model_Document::canRedo()
   if (myDoc->GetAvailableRedos() > 0)
     return true;
   // check other subs contains operation that can be redoed
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     if (subDoc(*aSubIter)->canRedo())
       return true;
   return false;
@@ -447,8 +454,9 @@ void Model_Document::redo()
   myTransactionsCounter++;
   synchronizeFeatures(true, true);
   // redo for all subs
-  std::set<std::string>::iterator aSubIter = mySubs.begin();
-  for (; aSubIter != mySubs.end(); aSubIter++)
+  const std::set<std::string> aSubs = subDocuments(true);
+  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->redo();
 }
 
@@ -573,7 +581,7 @@ void Model_Document::removeFeature(FeaturePtr theFeature, const bool theCheck)
   ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
 }
 
-FeaturePtr Model_Document::feature(TDF_Label& theLabel)
+FeaturePtr Model_Document::feature(TDF_Label& theLabel) const
 {
   if (myObjs.IsBound(theLabel))
     return myObjs.Find(theLabel);
@@ -603,17 +611,37 @@ ObjectPtr Model_Document::object(TDF_Label theLabel)
 
 std::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string theDocID)
 {
-  // just store sub-document identifier here to manage it later
-  if (mySubs.find(theDocID) == mySubs.end())
-    mySubs.insert(theDocID);
   return Model_Application::getApplication()->getDocument(theDocID);
 }
 
+const std::set<std::string> Model_Document::subDocuments(const bool theActivatedOnly) const
+{
+  std::set<std::string> aResult;
+  // comment must be in any feature: it is kind
+  int anIndex = 0;
+  TDF_ChildIDIterator aLabIter(featuresLabel(), TDataStd_Comment::GetID());
+  for (; aLabIter.More(); aLabIter.Next()) {
+    TDF_Label aFLabel = aLabIter.Value()->Label();
+    FeaturePtr aFeature = feature(aFLabel);
+    if (aFeature.get()) { // if document is closed the feature may be not in myObjs map
+      const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
+      std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      for (; aRIter != aResults.cend(); aRIter++) {
+        if ((*aRIter)->groupName() != ModelAPI_ResultPart::group()) continue;
+        if ((*aRIter)->isInHistory()) {
+          ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aRIter);
+          if (aPart && (!theActivatedOnly || aPart->isActivated()))
+            aResult.insert(aPart->data()->name());
+        }
+      }
+    }
+  }
+  return aResult;
+}
+
 std::shared_ptr<Model_Document> Model_Document::subDoc(std::string theDocID)
 {
   // just store sub-document identifier here to manage it later
-  if (mySubs.find(theDocID) == mySubs.end())
-    mySubs.insert(theDocID);
   return std::dynamic_pointer_cast<Model_Document>(
     Model_Application::getApplication()->getDocument(theDocID));
 }
@@ -704,7 +732,7 @@ int Model_Document::size(const std::string& theGroupID, const bool theHidden)
   return aResult;
 }
 
-TDF_Label Model_Document::featuresLabel()
+TDF_Label Model_Document::featuresLabel() const
 {
   return myDoc->Main().FindChild(TAG_OBJECTS);
 }
@@ -1089,3 +1117,16 @@ Standard_Boolean IsEqual(const TDF_Label& theLab1, const TDF_Label& theLab2)
 {
   return TDF_LabelMapHasher::IsEqual(theLab1, theLab2);
 }
+
+void Model_Document::addNamingName(const TDF_Label theLabel, std::string theName)
+{
+  myNamingNames[theName] = theLabel;
+}
+
+TDF_Label Model_Document::findNamingName(std::string theName)
+{
+  std::map<std::string, TDF_Label>::iterator aFind = myNamingNames.find(theName);
+  if (aFind == myNamingNames.end())
+    return TDF_Label(); // not found
+  return aFind->second;
+}