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 c4fb2e7aaa8c1003d46b2782231fad0ed83f5ae3..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)
@@ -104,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"));
@@ -205,34 +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);
-              theResults.push_back(aDestinationDir.ToCString());
-            } 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);
       }
     }
   }
@@ -246,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);
@@ -294,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();
 }
 
@@ -353,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
@@ -388,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();
 }
 
@@ -411,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;
@@ -427,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();
 }
 
@@ -437,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;
@@ -453,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();
 }
 
@@ -579,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);
@@ -609,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));
 }
@@ -710,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);
 }