Salome HOME
Update the internal persistence mechanism of documents identification: on load/save...
authormpv <mpv@opencascade.com>
Wed, 3 Feb 2016 09:21:45 +0000 (12:21 +0300)
committerdbv <dbv@opencascade.com>
Tue, 16 Feb 2016 14:04:34 +0000 (17:04 +0300)
19 files changed:
src/Model/Model_Application.cpp
src/Model/Model_Application.h
src/Model/Model_AttributeDocRef.cpp
src/Model/Model_AttributeDocRef.h
src/Model/Model_AttributeReference.cpp
src/Model/Model_Document.cpp
src/Model/Model_Document.h
src/Model/Model_Objects.cpp
src/Model/Model_Objects.h
src/Model/Model_ResultPart.cpp
src/Model/Model_ResultPart.h
src/Model/Model_Session.cpp
src/Model/Model_Session.h
src/ModelAPI/ModelAPI_AttributeDocRef.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Session.h
src/ModelAPI/Test/TestDocument.py
src/PartSetPlugin/PartSetPlugin_Duplicate.cpp
src/PartSetPlugin/PartSetPlugin_Duplicate.h

index 4dddb449daf686c24185616677b8f45a6df6bed1..24a16b9adc591dabeb538e99cede5adc840288fa 100644 (file)
@@ -23,35 +23,51 @@ Handle(Model_Application) Model_Application::getApplication()
 }
 
 //=======================================================================
-const std::shared_ptr<Model_Document>& Model_Application::getDocument(string theDocID)
+std::shared_ptr<Model_Document> Model_Application::document(const int theDocID)
 {
   if (myDocs.find(theDocID) != myDocs.end())
     return myDocs[theDocID];
+  return std::shared_ptr<Model_Document>(); // not loaded, so return null
+}
 
+//=======================================================================
+void Model_Application::createDocument(const int theDocID)
+{
   static const std::string thePartSetKind("PartSet");
   static const std::string thePartKind("Part");
-  bool isRoot = theDocID == "root"; // the document is root
   std::shared_ptr<Model_Document> aNew(
-    new Model_Document(theDocID, isRoot ? thePartSetKind : thePartKind));
+    new Model_Document(theDocID, theDocID == 0 ? thePartSetKind : thePartKind));
   myDocs[theDocID] = aNew;
 
+  aNew->setThis(aNew);
+  static Events_ID anId = ModelAPI_DocumentCreatedMessage::eventId();
+  std::shared_ptr<ModelAPI_DocumentCreatedMessage> aMessage = std::shared_ptr
+    <ModelAPI_DocumentCreatedMessage>(new ModelAPI_DocumentCreatedMessage(anId, this));
+  aMessage->setDocument(aNew);
+  Events_Loop::loop()->send(aMessage);
+}
+
+//=======================================================================
+bool Model_Application::loadDocument(const std::string theDocName, const int theDocID)
+{
+  static const std::string thePartKind("Part"); // root document is never loaded here
+  std::shared_ptr<Model_Document> aNew(new Model_Document(theDocID, thePartKind));
+  myDocs[theDocID] = aNew;
+
+  bool aRes = true;
   // load it if it must be loaded by demand
-  if (myLoadedByDemand.find(theDocID) != myLoadedByDemand.end() && !myPath.empty()) {
-    aNew->load(myPath.c_str(), aNew);
-    myLoadedByDemand.erase(theDocID);  // done, don't do it anymore
-  } else {
-    aNew->setThis(aNew);
-    static Events_ID anId = ModelAPI_DocumentCreatedMessage::eventId();
-    std::shared_ptr<ModelAPI_DocumentCreatedMessage> aMessage = std::shared_ptr
-      <ModelAPI_DocumentCreatedMessage>(new ModelAPI_DocumentCreatedMessage(anId, this));
-    aMessage->setDocument(aNew);
-    Events_Loop::loop()->send(aMessage);
+  if (myLoadedByDemand.find(theDocName) != myLoadedByDemand.end() && !myPath.empty()) {
+    aRes = aNew->load(myPath.c_str(), theDocName.c_str(), aNew);
+    myLoadedByDemand.erase(theDocName);  // done, don't do it anymore
+  } else { // error
+    aRes = false;
   }
 
-  return myDocs[theDocID];
+  return aRes;
 }
 
-void Model_Application::deleteDocument(string theDocID)
+//=======================================================================
+void Model_Application::deleteDocument(const int theDocID)
 {
   if (myDocs.find(theDocID) != myDocs.end()) {
     myDocs[theDocID]->close(true);
@@ -60,22 +76,36 @@ void Model_Application::deleteDocument(string theDocID)
   myLoadedByDemand.clear();
 }
 
+//=======================================================================
 void Model_Application::deleteAllDocuments()
 {
-  std::map<std::string, std::shared_ptr<Model_Document> >::iterator aDoc = myDocs.begin();
+  std::map<int, std::shared_ptr<Model_Document> >::iterator aDoc = myDocs.begin();
   for(; aDoc != myDocs.end(); aDoc++) {
-    aDoc->second->close(true);
+    if (!aDoc->second->isOpened()) // here is main document was closed before subs and closed subs
+      aDoc->second->close(true);
   }
   myDocs.clear();
   myLoadedByDemand.clear();
 }
 
 //=======================================================================
-bool Model_Application::hasDocument(std::string theDocID)
+bool Model_Application::hasDocument(const int theDocID)
 {
   return myDocs.find(theDocID) != myDocs.end();
 }
 
+//=======================================================================
+bool Model_Application::hasRoot()
+{
+  return !myDocs.empty();
+}
+
+//=======================================================================
+std::shared_ptr<Model_Document> Model_Application::rootDocument()
+{
+  return myDocs[0];
+}
+
 //=======================================================================
 void Model_Application::setLoadPath(std::string thePath)
 {
@@ -104,7 +134,7 @@ bool Model_Application::isLoadByDemand(std::string theID)
 void Model_Application::removeUselessDocuments(
   std::list<std::shared_ptr<ModelAPI_Document> > theUsedDocs)
 {
-  std::map<std::string, std::shared_ptr<Model_Document> >::iterator aDoc = myDocs.begin();
+  std::map<int, std::shared_ptr<Model_Document> >::iterator aDoc = myDocs.begin();
   while(aDoc != myDocs.end()) {
     bool aFound = false;
     std::list<std::shared_ptr<ModelAPI_Document> >::iterator aUsed = theUsedDocs.begin();
@@ -121,6 +151,13 @@ void Model_Application::removeUselessDocuments(
   }
 }
 
+int Model_Application::generateDocumentId()
+{
+  int aResult = myDocs.size();
+  for(; myDocs.find(aResult) != myDocs.end(); aResult++); // count until the result id is unique
+  return aResult;
+}
+
 //=======================================================================
 Model_Application::Model_Application()
 {
index b5a2af8e026ccc1adab9b76a03289f23f49e0cbf..728c2a807a66771979f9f5f7a0b373ff8441970f 100644 (file)
@@ -34,14 +34,27 @@ public:
 
   //! Retuns the application: one per process    
   MODEL_EXPORT static Handle_Model_Application getApplication();
-  //! Returns the main document (on first call creates it) by the string identifier
-  MODEL_EXPORT const std::shared_ptr<Model_Document>& getDocument(std::string theDocID);
+  //! Returns the document by the identifier
+  //! \returns false of document is not yet created/not loaded
+  MODEL_EXPORT std::shared_ptr<Model_Document> document(const int theDocID);
   //! Returns true if document has been created
-  MODEL_EXPORT bool hasDocument(std::string theDocID);
+  MODEL_EXPORT bool hasDocument(const int theDocID);
+  //! Returns true if root document has been created
+  MODEL_EXPORT bool hasRoot();
+  //! Returns root document, if created (or null otherwise)
+  MODEL_EXPORT std::shared_ptr<Model_Document> rootDocument();
   //! Deletes the document from the application
-  MODEL_EXPORT void deleteDocument(std::string theDocID);
+  MODEL_EXPORT void deleteDocument(const int theDocID);
   //! Deletes all documents existing in the application
   MODEL_EXPORT void deleteAllDocuments();
+  //! Creates a new document an returns an id of this document
+  //! \param theDocID if it is zero, the root document is created
+  MODEL_EXPORT void createDocument(const int theDocID);
+  //! Loads document by the file name (if it is registered as load by demand)
+  //! \param theDocName name of the document file
+  //! \param theDocID the identifier of the loaded document (to be created)
+  //! \returns true if load is ok
+  MODEL_EXPORT bool loadDocument(const std::string theDocName, const int theDocID);
 
   //! Set path for the loaded by demand documents
   void setLoadPath(std::string thePath);
@@ -55,6 +68,9 @@ public:
   //! not in the given list
   void removeUselessDocuments(std::list<std::shared_ptr<ModelAPI_Document> > theUsedDocs);
 
+  //! produces new unique identifier of the document
+  int generateDocumentId();
+
  public:
   // Redefined OCAF methods
   //! Return name of resource (i.e. "Standard")
@@ -68,8 +84,8 @@ public:
   Model_Application();
 
  private:
-  /// Map from string identifiers to created documents of an application
-  std::map<std::string, std::shared_ptr<Model_Document> > myDocs;
+  /// Map from identifiers to created documents of an application
+  std::map<int, std::shared_ptr<Model_Document> > myDocs;
   /// Path for the loaded by demand documents
   std::string myPath;
   /// Path for the loaded by demand documents
index 2284226c262cb09819572a5c52e370623f5a7950..5c3eaf442de29aabcc5fd9f643be35d99bb02fdf 100644 (file)
@@ -13,30 +13,27 @@ using namespace std;
 
 void Model_AttributeDocRef::setValue(std::shared_ptr<ModelAPI_Document> theDoc)
 {
-  myDoc = theDoc;
-  TCollection_ExtendedString aNewID(theDoc->id().c_str());
-  if (!myIsInitialized || myComment->Get() != aNewID) {
-    myComment->Set(TCollection_ExtendedString(theDoc->id().c_str()));
+  if (myID->Get() != theDoc->id()) {
+    myID->Set(theDoc->id());
     owner()->data()->sendAttributeUpdated(this);
   }
 }
 
 std::shared_ptr<ModelAPI_Document> Model_AttributeDocRef::value()
 {
-  return myDoc;
+  return Model_Application::getApplication()->document(myID->Get());
+}
+
+int Model_AttributeDocRef::docId()
+{
+  return myID->Get();
 }
 
 Model_AttributeDocRef::Model_AttributeDocRef(TDF_Label& theLabel)
 {
-  myIsInitialized = theLabel.FindAttribute(TDataStd_Comment::GetID(), myComment) == Standard_True;
+  myIsInitialized = theLabel.FindAttribute(TDataStd_Integer::GetID(), myID) == Standard_True;
   if (!myIsInitialized) {
-    // create attribute: not initialized by value yet, just empty string
-    myComment = TDataStd_Comment::Set(theLabel, "");
-  } else {  // document was already referenced: try to set it as loaded by demand
-    Handle(Model_Application) anApp = Model_Application::getApplication();
-    string anID(TCollection_AsciiString(myComment->Get()).ToCString());
-    if (!anApp->hasDocument(anID)) {
-      anApp->setLoadByDemand(anID);
-    }
+    int aNewID = Model_Application::getApplication()->generateDocumentId();
+    myID = TDataStd_Integer::Set(theLabel, aNewID);
   }
 }
index 3a4638a69c69588cbd0013cd73821c4f06e90eff..04eacc4372978ddebb19e8e1f2f78c2fb55e2709 100644 (file)
@@ -9,7 +9,7 @@
 
 #include "Model.h"
 #include "ModelAPI_AttributeDocRef.h"
-#include <TDataStd_Comment.hxx>
+#include <TDataStd_Integer.hxx>
 #include <TDF_Label.hxx>
 
 /**\class Model_AttributeDocRef
 
 class Model_AttributeDocRef : public ModelAPI_AttributeDocRef
 {
-  Handle_TDataStd_Comment myComment;  ///< reference to document is identified as string-id
-  std::shared_ptr<ModelAPI_Document> myDoc; ///< document referenced by this attribute (if already loaded)
+  Handle(TDataStd_Integer) myID; ///< persistent and unique identifier of the document in the application
  public:
+
   /// Defines the document referenced from this attribute
   MODEL_EXPORT virtual void setValue(std::shared_ptr<ModelAPI_Document> theDoc);
 
   /// Returns document referenced from this attribute
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> value();
 
+  /// Returns the persisten ID of the document
+  MODEL_EXPORT virtual int docId();
+
  protected:
   /// Initializes attibutes
   Model_AttributeDocRef(TDF_Label& theLabel);
index beb04549cffe4a51c359d83158e386613ddb07e8..40ad13ad987acd868549bf29403c4a22167f5fc1 100644 (file)
@@ -46,7 +46,9 @@ void Model_AttributeReference::setValue(ObjectPtr theObject)
       myRef->Label().ForgetAttribute(TDataStd_AsciiString::GetID());
     } else { // different document: store the document name (comment) and entry (string): external
       // if these attributes exist, the link is external: keep reference to access the label
-      TDataStd_Comment::Set(myRef->Label(), theObject->document()->id().c_str());
+      std::ostringstream anIdString; // string with document Id
+      anIdString<<theObject->document()->id();
+      TDataStd_Comment::Set(myRef->Label(), anIdString.str().c_str());
       TCollection_AsciiString anEntry;
       TDF_Tool::Entry(anObjLab, anEntry);
       TDataStd_AsciiString::Set(myRef->Label(), anEntry);
@@ -64,9 +66,9 @@ ObjectPtr Model_AttributeReference::value()
   if (isInitialized()) {
     Handle(TDataStd_Comment) aDocID;
     if (myRef->Label().FindAttribute(TDataStd_Comment::GetID(), aDocID)) { // external ref
-      DocumentPtr aRefDoc =
-        ModelAPI_Session::get()->document(TCollection_AsciiString(aDocID->Get()).ToCString());
-      if (aRefDoc) {
+      int anID = atoi(TCollection_AsciiString(aDocID->Get()).ToCString());
+      DocumentPtr aRefDoc = Model_Application::getApplication()->document(anID);
+      if (aRefDoc.get()) {
         Handle(TDataStd_AsciiString) anEntry;
         if (myRef->Label().FindAttribute(TDataStd_AsciiString::GetID(), anEntry)) {
           std::shared_ptr<Model_Document> aDR = std::dynamic_pointer_cast<Model_Document>(aRefDoc);
index 645291f72e0ae720f3090cc3b72234a3559af720..280da04f29e8b543d1ee18e65eca7a1876e08b8d 100755 (executable)
@@ -59,7 +59,7 @@ static const int TAG_CURRENT_FEATURE = 1; ///< where the reference to the curren
 static const int TAG_CURRENT_TRANSACTION = 2; ///< integer, index of the transaction
 static const int TAG_SELECTION_FEATURE = 3; ///< integer, tag of the selection feature label
 
-Model_Document::Model_Document(const std::string theID, const std::string theKind)
+Model_Document::Model_Document(const int theID, const std::string theKind)
     : myID(theID), myKind(theKind), myIsActive(false),
       myDoc(new TDocStd_Document("BinOcaf"))  // binary OCAF format
 {
@@ -81,10 +81,10 @@ void Model_Document::setThis(DocumentPtr theDoc)
   myObjs->setOwner(theDoc);
 }
 
-/// Returns the file name of this document by the nameof directory and identifuer of a document
-static TCollection_ExtendedString DocFileName(const char* theFileName, const std::string& theID)
+/// Returns the file name of this document by the name of directory and identifier of a document
+static TCollection_ExtendedString DocFileName(const char* theDirName, const std::string& theID)
 {
-  TCollection_ExtendedString aPath((const Standard_CString) theFileName);
+  TCollection_ExtendedString aPath((const Standard_CString) theDirName);
   // remove end-separators
   while(aPath.Length() && 
         (aPath.Value(aPath.Length()) == '\\' || aPath.Value(aPath.Length()) == '/'))
@@ -100,13 +100,13 @@ bool Model_Document::isRoot() const
   return this == Model_Session::get()->moduleDocument().get();
 }
 
-bool Model_Document::load(const char* theFileName, DocumentPtr theThis)
+bool Model_Document::load(const char* theDirName, const char* theFileName, DocumentPtr theThis)
 {
   Handle(Model_Application) anApp = Model_Application::getApplication();
   if (isRoot()) {
-    anApp->setLoadPath(theFileName);
+    anApp->setLoadPath(theDirName);
   }
-  TCollection_ExtendedString aPath(DocFileName(theFileName, myID));
+  TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName));
   PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1;
   Handle(TDocStd_Document) aLoaded;
   try {
@@ -177,7 +177,7 @@ bool Model_Document::load(const char* theFileName, DocumentPtr theThis)
     myDoc = aLoaded;
     myDoc->SetUndoLimit(UNDO_LIMIT);
     // to avoid the problem that feature is created in the current, not this, document
-    aSession->setActiveDocument(anApp->getDocument(myID), false);
+    aSession->setActiveDocument(anApp->document(myID), false);
     aSession->setCheckTransactions(false);
     if (myObjs)
       delete myObjs;
@@ -189,13 +189,25 @@ bool Model_Document::load(const char* theFileName, DocumentPtr theThis)
     aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
     // this is done in Part result "activate", so no needed here. Causes not-blue active part.
     // aSession->setActiveDocument(anApp->getDocument(myID), true);
+
+    // make sub-parts as loaded by demand
+    std::list<ResultPtr> aPartResults;
+    myObjs->allResults(ModelAPI_ResultPart::group(), aPartResults);
+    std::list<ResultPtr>::iterator aPartRes = aPartResults.begin();
+    for(; aPartRes != aPartResults.end(); aPartRes++) {
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPartRes);
+      if (aPart.get())
+        anApp->setLoadByDemand(aPart->data()->name());
+    }
+
   } else { // open failed, but new documnet was created to work with it: inform the model
     aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false);
   } 
   return !isError;
 }
 
-bool Model_Document::save(const char* theFileName, std::list<std::string>& theResults)
+bool Model_Document::save(
+  const char* theDirName, const char* theFileName, std::list<std::string>& theResults)
 {
   // create a directory in the root document if it is not yet exist
   Handle(Model_Application) anApp = Model_Application::getApplication();
@@ -207,7 +219,7 @@ bool Model_Document::save(const char* theFileName, std::list<std::string>& theRe
 #endif
   }
   // filename in the dir is id of document inside of the given directory
-  TCollection_ExtendedString aPath(DocFileName(theFileName, myID));
+  TCollection_ExtendedString aPath(DocFileName(theDirName, theFileName));
   PCDM_StoreStatus aStatus;
   try {
     aStatus = anApp->SaveAs(myDoc, aPath);
@@ -234,20 +246,22 @@ bool Model_Document::save(const char* theFileName, std::list<std::string>& theRe
   }
   myTransactionSave = myTransactions.size();
   if (isDone) {  // save also sub-documents if any
-    theResults.push_back(TCollection_AsciiString(aPath).ToCString());
-    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)) { 
+    // iterate all result parts to find all loaded or not yet loaded documents
+    std::list<ResultPtr> aPartResults;
+    myObjs->allResults(ModelAPI_ResultPart::group(), aPartResults);
+    std::list<ResultPtr>::iterator aPartRes = aPartResults.begin();
+    for(; aPartRes != aPartResults.end(); aPartRes++) {
+      ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPartRes);
+      if (!aPart->isActivated()) {
         // copy not-activated document that is not in the memory
-        std::string aDocName = *aSubIter;
+        std::string aDocName = aPart->data()->name();
         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));
+            TCollection_AsciiString aDestinationDir(DocFileName(theDirName, aDocName));
             OSD_Path aDestination(aDestinationDir);
             aFile.Copy(aDestination);
             theResults.push_back(aDestinationDir.ToCString());
@@ -257,7 +271,8 @@ bool Model_Document::save(const char* theFileName, std::list<std::string>& theRe
           }
         }
       } else { // simply save opened document
-        isDone = subDoc(*aSubIter)->save(theFileName, theResults);
+        isDone = std::dynamic_pointer_cast<Model_Document>(aPart->partDoc())->
+          save(theDirName, aPart->data()->name().c_str(), theResults);
       }
     }
   }
@@ -274,8 +289,8 @@ void Model_Document::close(const bool theForever)
     aPM->setActiveDocument(DocumentPtr());
   }
   // close all subs
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++) {
     std::shared_ptr<Model_Document> aSub = subDoc(*aSubIter);
     if (aSub->myObjs) // if it was not closed before
@@ -322,8 +337,8 @@ void Model_Document::startOperation()
     (*myNestedNum.rbegin())++;
   myRedos.clear();
   // new command for all subs
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->startOperation();
 }
@@ -499,8 +514,8 @@ bool Model_Document::finishOperation()
 
   // finish for all subs first: to avoid nested finishing and "isOperation" calls problems inside
   bool aResult = false;
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++)
     if (subDoc(*aSubIter)->finishOperation())
       aResult = true;
@@ -594,8 +609,8 @@ void Model_Document::abortOperation()
     myDoc->ClearRedos();
   }
   // abort for all subs, flushes will be later, in the end of root abort
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->abortOperation();
   // references may be changed because they are set in attributes on the fly
@@ -623,8 +638,8 @@ bool Model_Document::canUndo()
       myTransactions.size() - aCurrentNum > 0 /* for omitting the first useless transaction */)
     return true;
   // check other subs contains operation that can be undoed
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++) {
     std::shared_ptr<Model_Document> aSub = subDoc(*aSubIter);
     if (aSub->myObjs) {// if it was not closed before
@@ -655,8 +670,8 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron
 
   if (theWithSubs) {
     // undo for all subs
-    const std::set<std::string> aSubs = subDocuments(true);
-    std::set<std::string>::iterator aSubIter = aSubs.begin();
+    const std::set<int> aSubs = subDocuments();
+    std::set<int>::iterator aSubIter = aSubs.begin();
     for (; aSubIter != aSubs.end(); aSubIter++) {
       if (!subDoc(*aSubIter)->myObjs)
         continue;
@@ -681,8 +696,8 @@ bool Model_Document::canRedo()
   if (!myRedos.empty())
     return true;
   // check other subs contains operation that can be redoed
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++) {
     if (!subDoc(*aSubIter)->myObjs)
       continue;
@@ -706,8 +721,8 @@ void Model_Document::redo()
   }
 
   // redo for all subs
-  const std::set<std::string> aSubs = subDocuments(true);
-  std::set<std::string>::iterator aSubIter = aSubs.begin();
+  const std::set<int> aSubs = subDocuments();
+  std::set<int>::iterator aSubIter = aSubs.begin();
   for (; aSubIter != aSubs.end(); aSubIter++)
     subDoc(*aSubIter)->redo();
 
@@ -825,31 +840,26 @@ void Model_Document::updateHistory(const std::string theGroup)
   myObjs->updateHistory(theGroup);
 }
 
-std::shared_ptr<ModelAPI_Document> Model_Document::subDocument(std::string theDocID)
+const std::set<int> Model_Document::subDocuments() const
 {
-  return Model_Application::getApplication()->getDocument(theDocID);
-}
-
-const std::set<std::string> Model_Document::subDocuments(const bool theActivatedOnly) const
-{
-  std::set<std::string> aResult;
+  std::set<int> aResult;
   std::list<ResultPtr> aPartResults;
   myObjs->allResults(ModelAPI_ResultPart::group(), aPartResults);
   std::list<ResultPtr>::iterator aPartRes = aPartResults.begin();
   for(; aPartRes != aPartResults.end(); aPartRes++) {
     ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPartRes);
-    if (aPart && (!theActivatedOnly || aPart->isActivated())) {
-      aResult.insert(aPart->original()->data()->name());
+    if (aPart && aPart->isActivated()) {
+      aResult.insert(aPart->original()->partDoc()->id());
     }
   }
   return aResult;
 }
 
-std::shared_ptr<Model_Document> Model_Document::subDoc(std::string theDocID)
+std::shared_ptr<Model_Document> Model_Document::subDoc(int theDocID)
 {
   // just store sub-document identifier here to manage it later
   return std::dynamic_pointer_cast<Model_Document>(
-    Model_Application::getApplication()->getDocument(theDocID));
+    Model_Application::getApplication()->document(theDocID));
 }
 
 ObjectPtr Model_Document::object(const std::string& theGroupID, const int theIndex)
@@ -1164,6 +1174,11 @@ std::shared_ptr<ModelAPI_Feature> Model_Document::internalFeature(const int theI
   return myObjs->internalFeature(theIndex);
 }
 
+std::shared_ptr<ModelAPI_Feature> Model_Document::featureById(const int theId)
+{
+  return myObjs->featureById(theId);
+}
+
 void Model_Document::synchronizeTransactions()
 {
   Model_Document* aRoot = 
index 25e467e717028272d13286069a13cfbf3aad7aab..6f0b2bee68a1f38058e8c8cf21669e560966614c 100644 (file)
@@ -36,16 +36,20 @@ class Model_Document : public ModelAPI_Document
   MODEL_EXPORT virtual const std::string& kind() const {return myKind;}
 
   //! Loads the OCAF document from the file.
-  //! \param theFileName full name of the file to load
+  //! \param theDirName directory of the loaded file
+  //! \param theFileName a name of the file to load
   //! \param theThis the common shared pointer to the document to manage with it later
   //! \returns true if file was loaded successfully
-  MODEL_EXPORT virtual bool load(const char* theFileName, DocumentPtr theThis);
+  MODEL_EXPORT virtual bool load(
+    const char* theDirName, const char* theFileName, DocumentPtr theThis);
 
   //! Saves the OCAF document to the file.
-  //! \param theFileName full name of the file to store
+  //! \param theDirName directory where the document will be saved
+  //! \param theFileName a name of the document file to store
   //! \param theResults the result full file names that were stored by "save"
   //! \returns true if file was stored successfully
-  MODEL_EXPORT virtual bool save(const char* theFileName, std::list<std::string>& theResults);
+  MODEL_EXPORT virtual bool save(
+    const char* theDirName, const char* theFileName, std::list<std::string>& theResults);
 
   //! Removes document data
   //! \param theForever if it is false, document is just hiden (to keep possibility make it back on Undo/Redo)
@@ -104,14 +108,11 @@ class Model_Document : public ModelAPI_Document
   //! \returns index started from zero, or -1 if object is invisible or belongs to another document
   MODEL_EXPORT virtual const int index(std::shared_ptr<ModelAPI_Object> theObject);
 
-  //! Adds a new sub-document by the identifier, or returns existing one if it is already exist
-  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> subDocument(std::string theDocID);
-
   //! Internal sub-document by ID
-  MODEL_EXPORT virtual std::shared_ptr<Model_Document> subDoc(std::string theDocID);
+  MODEL_EXPORT virtual std::shared_ptr<Model_Document> subDoc(int theDocID);
 
   ///! Returns the id of the document
-  MODEL_EXPORT virtual const std::string& id() const
+  MODEL_EXPORT virtual const int id() const
   {
     return myID;
   }
@@ -150,6 +151,9 @@ class Model_Document : public ModelAPI_Document
   //! wihtout this participation
   MODEL_EXPORT virtual void synchronizeTransactions();
 
+  //! Returns feature by the id of the feature (produced by the Data "featureId" method)
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Feature> featureById(const int theId);
+
 
   /// Creates a construction cresults
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
@@ -210,7 +214,7 @@ class Model_Document : public ModelAPI_Document
   TDF_Label generalLabel() const;
 
   //! Creates new document with binary file format
-  Model_Document(const std::string theID, const std::string theKind);
+  Model_Document(const int theID, const std::string theKind);
 
   //! Returns the internal OCCT document of this interface
   Handle_TDocStd_Document document()
@@ -222,8 +226,8 @@ class Model_Document : public ModelAPI_Document
   //! \returns true if resulting transaction is not empty and can be undoed
   void compactNested();
 
-  //! Returns all sub documents
-  const std::set<std::string> subDocuments(const bool theActivatedOnly) const;
+  //! Returns all loaded sub documents
+  const std::set<int> subDocuments() const;
 
   //! The implementation of undo: with or without recoursive calls in the sub-documents
   void undoInternal(const bool theWithSubs, const bool theSynchronize);
@@ -272,7 +276,7 @@ class Model_Document : public ModelAPI_Document
   friend class DFBrowser;
 
  private:
-  std::string myID;  ///< identifier of the document in the application
+  int myID;  ///< identifier of the document in the application
   std::string myKind;  ///< kind of the document in the application
   Handle_TDocStd_Document myDoc;  ///< OCAF document
 
index aa8e2751c0980532839c2fbb18ea9c247aa4ee42..63131d43ec89922ad406a64f3e9785e0ddc7da19 100644 (file)
@@ -568,12 +568,6 @@ void Model_Objects::setUniqueName(FeaturePtr theFeature)
         isSameName = (*aRIter)->data()->name() == aName;
       }
     }
-    // for new Parts create names that are not in the Postponed list
-    if (!isSameName && (theFeature->getKind() == "Part" || theFeature->getKind() == "Duplicate")) {
-      std::shared_ptr<Model_Session> aSession = 
-        std::dynamic_pointer_cast<Model_Session>(Model_Session::get());
-      isSameName = aSession->isLoadByDemand(aName) || aSession->hasDocument(aName);
-    }
 
     if (isSameName) {
       aNumObjects++;
@@ -602,6 +596,15 @@ void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTa
   theObj->initAttributes();
 }
 
+std::shared_ptr<ModelAPI_Feature> Model_Objects::featureById(const int theId)
+{
+  if (theId > 0) {
+    TDF_Label aLab = featuresLabel().FindChild(theId, Standard_False);
+    return feature(aLab);
+  }
+  return std::shared_ptr<ModelAPI_Feature>(); // not found
+}
+
 void Model_Objects::synchronizeFeatures(
   const TDF_LabelList& theUpdated, const bool theUpdateReferences, const bool theFlush)
 {
index 9f947c776f62d0f392f076e63198c4d11736242b..740a3d54250c758b248f352e96a6021ea12dda80 100644 (file)
@@ -95,6 +95,10 @@ class Model_Objects
   //! Returns the feature by zero-based index: features in the history or not
   std::shared_ptr<ModelAPI_Feature> internalFeature(const int theIndex);
 
+  //! Returns feature by the id of the feature (produced by the Data "featureId" method)
+  std::shared_ptr<ModelAPI_Feature> featureById(const int theId);
+
+
   /// Creates a construction result
   std::shared_ptr<ModelAPI_ResultConstruction> createConstruction(
       const std::shared_ptr<ModelAPI_Data>& theFeatureData, const int theIndex = 0);
index 772cbb3849b3affa7f4059dc56ae94a6e637aee5..57dcd9a783533374395cb04b82a11d998ae93f8d 100644 (file)
@@ -15,6 +15,7 @@
 #include <ModelAPI_AttributeSelectionList.h>
 #include <ModelAPI_AttributeReference.h>
 #include <Model_Document.h>
+#include <Model_Application.h>
 #include <Events_Loop.h>
 #include <ModelAPI_Events.h>
 
 void Model_ResultPart::initAttributes()
 {
   // append the color attribute. It is empty, the attribute will be filled by a request
-  data()->addAttribute(DOC_REF(), ModelAPI_AttributeDocRef::typeId());
+  AttributeDocRefPtr aDocRef = std::dynamic_pointer_cast<ModelAPI_AttributeDocRef>(
+    data()->addAttribute(DOC_REF(), ModelAPI_AttributeDocRef::typeId()));
   data()->addAttribute(COLOR_ID(), ModelAPI_AttributeIntArray::typeId());
   data()->addAttribute(BASE_REF_ID(), ModelAPI_AttributeReference::typeId());
+
+  if (aDocRef->isInitialized() && // initialized immideately means already exist and will be loaded
+      !Model_Application::getApplication()->hasDocument(aDocRef->docId()))
+    Model_Application::getApplication()->setLoadByDemand(data()->name());
 }
 
 std::shared_ptr<ModelAPI_Document> Model_ResultPart::partDoc()
@@ -42,15 +48,11 @@ std::shared_ptr<ModelAPI_Document> Model_ResultPart::partDoc()
     return baseRef()->partDoc();
   }
   DocumentPtr aRes = data()->document(DOC_REF())->value();
-  if (!aRes.get() && myIsInLoad) { // trying to get this document from the session
-    aRes = document()->subDocument(data()->name());
-  }
   return aRes;
 }
 
 Model_ResultPart::Model_ResultPart()
 {
-  myIsInLoad = false;
 }
 
 void Model_ResultPart::activate()
@@ -66,14 +68,18 @@ void Model_ResultPart::activate()
   bool isNewTransaction = false;
   SessionPtr aMgr = ModelAPI_Session::get();
   if (!aDocRef->value().get()) {  // create (or open) a document if it is not yet created
-    myIsInLoad = true;
+    Handle(Model_Application) anApp = Model_Application::getApplication();
     if (!aMgr->isOperation()) {
       aMgr->startOperation("Activation");
       isNewTransaction = true;
     }
-    std::shared_ptr<ModelAPI_Document> aDoc = document()->subDocument(data()->name());
-    myIsInLoad = false;
-    if (aDoc) {
+    if (anApp->isLoadByDemand(data()->name())) {
+      anApp->loadDocument(data()->name(), aDocRef->docId()); // if it is just ne part, load may fail
+    } else {
+      anApp->createDocument(aDocRef->docId());
+    }
+    std::shared_ptr<ModelAPI_Document> aDoc = aDocRef->value();
+    if (aDoc.get()) {
       aDoc->synchronizeTransactions();
       aDocRef->setValue(aDoc);
     }
index 220e1b408f50e5a6eb7cac65884bb98a818d7b67..49adb855ae316261456e5d9460e83dc17b9ca4cb 100644 (file)
@@ -23,7 +23,6 @@ class Model_ResultPart : public ModelAPI_ResultPart
 {
   TopoDS_Shape myShape; ///< shape of this part created from bodies (updated only of Part deactivation)
   std::shared_ptr<gp_Trsf> myTrsf; ///< if it is just copy of original shape, keep just transformation
-  bool myIsInLoad; ///< true if document of this part is in the loading process, so, it may be already received
  public:
 
   /// the reference to the base result document, may be null if this is the root, others make sequence of references
index 1bb0cebd23c67c73a3582fad03128e2750f1945b..e336d1652d3f7d2166cc095b231232cd09ece395 100644 (file)
@@ -38,13 +38,13 @@ static Model_Session* myImpl = new Model_Session();
 
 bool Model_Session::load(const char* theFileName)
 {
-  bool aRes = ROOT_DOC->load(theFileName, ROOT_DOC);
+  bool aRes = ROOT_DOC->load(theFileName, "root", ROOT_DOC);
   return aRes;
 }
 
 bool Model_Session::save(const char* theFileName, std::list<std::string>& theResults)
 {
-  return ROOT_DOC->save(theFileName, theResults);
+  return ROOT_DOC->save(theFileName, "root", theResults);
 }
 
 void Model_Session::closeAll()
@@ -186,34 +186,27 @@ FeaturePtr Model_Session::createFeature(string theFeatureID, Model_Document* the
 
 std::shared_ptr<ModelAPI_Document> Model_Session::moduleDocument()
 {
-  bool aFirstCall = !Model_Application::getApplication()->hasDocument("root");
+  Handle(Model_Application) anApp = Model_Application::getApplication();
+  bool aFirstCall = !anApp->hasRoot();
   if (aFirstCall) {
     // creation of the root document is always outside of the transaction, so, avoid checking it
     setCheckTransactions(false);
-  }
-  std::shared_ptr<ModelAPI_Document> aDoc = std::shared_ptr<ModelAPI_Document>(
-      Model_Application::getApplication()->getDocument("root"));
-  if (aFirstCall) {
+    anApp->createDocument(0); // 0 is a root ID
     // creation of the root document is always outside of the transaction, so, avoid checking it
     setCheckTransactions(true);
   }
-  return aDoc;
+  return anApp->rootDocument();
 }
 
-std::shared_ptr<ModelAPI_Document> Model_Session::document(std::string theDocID)
+std::shared_ptr<ModelAPI_Document> Model_Session::document(int theDocID)
 {
   return std::shared_ptr<ModelAPI_Document>(
-      Model_Application::getApplication()->getDocument(theDocID));
+      Model_Application::getApplication()->document(theDocID));
 }
 
 bool Model_Session::hasModuleDocument()
 {
-  return Model_Application::getApplication()->hasDocument("root");
-}
-
-bool Model_Session::hasDocument(std::string theDocID)
-{
-  return Model_Application::getApplication()->hasDocument(theDocID);
+  return Model_Application::getApplication()->hasRoot();
 }
 
 std::shared_ptr<ModelAPI_Document> Model_Session::activeDocument()
@@ -302,12 +295,10 @@ std::list<std::shared_ptr<ModelAPI_Document> > Model_Session::allOpenedDocuments
     DocumentPtr anAPIDoc = *aDoc;
     std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(anAPIDoc);
     if (aDoc) {
-      const std::set<std::string> aSubs = aDoc->subDocuments(true);
-      std::set<std::string>::const_iterator aSubIter = aSubs.cbegin();
+      const std::set<int> aSubs = aDoc->subDocuments();
+      std::set<int>::const_iterator aSubIter = aSubs.cbegin();
       for(; aSubIter != aSubs.cend(); aSubIter++) {
-        if (!Model_Application::getApplication()->isLoadByDemand(*aSubIter)) {
-          aResult.push_back(Model_Application::getApplication()->getDocument(*aSubIter));
-        }
+        aResult.push_back(Model_Application::getApplication()->document(*aSubIter));
       }
     }
   }
@@ -320,11 +311,9 @@ bool Model_Session::isLoadByDemand(const std::string theDocID)
 }
 
 std::shared_ptr<ModelAPI_Document> Model_Session::copy(
-    std::shared_ptr<ModelAPI_Document> theSource, std::string theID)
+    std::shared_ptr<ModelAPI_Document> theSource, const int theDestID)
 {
-  // create a new document
-  std::shared_ptr<Model_Document> aNew = std::dynamic_pointer_cast<Model_Document>(
-      Model_Application::getApplication()->getDocument(theID));
+  std::shared_ptr<Model_Document> aNew = Model_Application::getApplication()->document(theDestID);
   // make a copy of all labels
   TDF_Label aSourceRoot = std::dynamic_pointer_cast<Model_Document>(theSource)->document()->Main()
       .Father();
index 04eadff1c12646b0ddff5b51e99177fbe6922808..f31928620f78a87febc82bfbe2366db719a99524 100644 (file)
@@ -80,9 +80,7 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> moduleDocument();
 
   /// Returns the document by ID, loads if not loaded yet. Returns null if no such document.
-  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> document(std::string theDocID);
-  /// Return true if document with such ID has been already created
-  MODEL_EXPORT virtual bool hasDocument(std::string theDocID);
+  MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> document(int theDocID);
 
   /// Return true if root document has been already created
   MODEL_EXPORT virtual bool hasModuleDocument();
@@ -108,9 +106,9 @@ class Model_Session : public ModelAPI_Session, public Events_Listener
   /// Processes the configuration file reading
   MODEL_EXPORT virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
 
-  /// Copies the document to the new one with the given id
+  /// Copies the document to the new one
   MODEL_EXPORT virtual std::shared_ptr<ModelAPI_Document> copy(
-      std::shared_ptr<ModelAPI_Document> theSource, std::string theID);
+      std::shared_ptr<ModelAPI_Document> theSource, const int theDestID);
 
   /// Returns the validators factory: the only one instance per application
   MODEL_EXPORT virtual ModelAPI_ValidatorsFactory* validators();
index 0772c9fc3eba1aaaf538ff1a422ea073bfff16ef..c846235dd3bd1a9ee99039d916ed54d0b748d3a0 100644 (file)
@@ -24,6 +24,9 @@ class ModelAPI_AttributeDocRef : public ModelAPI_Attribute
   /// Returns document referenced from this attribute
   MODELAPI_EXPORT virtual std::shared_ptr<ModelAPI_Document> value() = 0;
 
+  /// Returns the persisten ID of the document
+  MODELAPI_EXPORT virtual int docId() = 0;
+
   /// Returns the type of this class of attributes
   MODELAPI_EXPORT static std::string typeId()
   {
index abf679546fa7ffdf410cfced299d96af3fdbbb58..8c1297359b113bdbe76c4156f6aa546717d14d64 100644 (file)
@@ -66,11 +66,8 @@ public:
   virtual void moveFeature(std::shared_ptr<ModelAPI_Feature> theMoved, 
                            std::shared_ptr<ModelAPI_Feature> theAfterThis) = 0;
 
-  ///! Adds a new sub-document by the identifier, or returns existing one if it is already exist
-  virtual std::shared_ptr<ModelAPI_Document> subDocument(std::string theDocID) = 0;
-
   ///! Returns the id of the document
-  virtual const std::string& id() const = 0;
+  virtual const int id() const = 0;
 
   //! Returns the object in the group by the index (started from zero)
   //! \param theGroupID group that contains an object
@@ -118,6 +115,8 @@ public:
   //! wihtout this participation
   virtual void synchronizeTransactions() = 0;
 
+  //! Returns feature by the id of the feature (produced by the Data "featureId" method)
+  virtual std::shared_ptr<ModelAPI_Feature> featureById(const int theId) = 0;
 
   //! To virtually destroy the fields of successors
   MODELAPI_EXPORT virtual ~ModelAPI_Document();
index df0e9c51902c6ba5195a23a9aff4254f9add7d7e..6d385ea5b7e023efd502ba15d83b4117fa5a4916 100644 (file)
@@ -80,8 +80,8 @@ class MODELAPI_EXPORT ModelAPI_Session
   /// Returns the root document of the application (that may contains sub-documents)
   virtual std::shared_ptr<ModelAPI_Document> moduleDocument() = 0;
 
-  /// Returns the document by ID, loads if not loaded yet. Returns null if no such document.
-  virtual std::shared_ptr<ModelAPI_Document> document(std::string theDocID) = 0;
+  /// Returns the document by ID. Returns null if no such document.
+  virtual std::shared_ptr<ModelAPI_Document> document(int theDocID) = 0;
 
   /// Return true if root document has been already created
   virtual bool hasModuleDocument() = 0;
@@ -100,8 +100,8 @@ class MODELAPI_EXPORT ModelAPI_Session
   virtual bool isLoadByDemand(const std::string theDocID) = 0;
 
   /// Copies the document to the new one with the given id
-  virtual std::shared_ptr<ModelAPI_Document> copy(std::shared_ptr<ModelAPI_Document> theSource,
-                                                    std::string theID) = 0;
+  virtual std::shared_ptr<ModelAPI_Document> copy(
+    std::shared_ptr<ModelAPI_Document> theSource, const int theDestID) =0;
 
   /// Returns the validators factory: the only one instance per application
   virtual ModelAPI_ValidatorsFactory* validators() = 0;
index 8080f3654ae3efc4ecf84c8842cdb5ccdae38728..14bf232bb49471b50036ce6d386266be157335fc 100644 (file)
@@ -18,7 +18,7 @@ __updated__ = "2014-12-26"
 aSession = ModelAPI_Session.get()
 # TODO: enable this assertion:
 assert(aSession.moduleDocument())
-assert(aSession.moduleDocument().id() == "root")
+assert(aSession.moduleDocument().id() == 0)
 assert(aSession.moduleDocument().kind() == "PartSet")
 assert(aSession.hasModuleDocument())
 # Create a new document
@@ -27,22 +27,22 @@ aSession.moduleDocument().addFeature("Part")
 aSession.finishOperation()
 
 assert(aSession.activeDocument())
-assert(aSession.activeDocument().id() == "Part_1")
+assert(aSession.activeDocument().id() == 1)
 assert(aSession.activeDocument().kind() == "Part")
 # Activate root doc
-aRootDoc = aSession.document("root")
+aRootDoc = aSession.document(0)
 assert(aRootDoc)
 aSession.startOperation()
 aSession.setActiveDocument(aRootDoc, False)
 aSession.finishOperation()
 assert(aSession.activeDocument())
-assert(aSession.activeDocument().id() == "root")
+assert(aSession.activeDocument().id() == 0)
 # check all opened docs
 allDocsList = aSession.allOpenedDocuments()
 assert(len(allDocsList) != 0)
 # Activate Part_1 doc back for further testing
 aSession.startOperation()
-aSession.setActiveDocument(aSession.document("Part_1"), False)
+aSession.setActiveDocument(aSession.document(1), False)
 aSession.finishOperation()
 #=========================================================================
 # Duplication of a document
@@ -66,7 +66,7 @@ aPart.addFeature("Duplicate")
 aSession.finishOperation()
 assert(aSession.moduleDocument().size("Parts") == 2)
 aCopyOfPart = aSession.activeDocument()
-assert(aCopyOfPart.id() == "Part_2")
+assert(aCopyOfPart.id() == 2)
 assert(aCopyOfPart.kind() == "Part")
 assert(aCopyOfPart.size("Features") == 1)
 assert(aCopyOfPart != aPart)
@@ -82,7 +82,7 @@ assert(aSession.moduleDocument().size("Parts") == 1)
 assert(aSession.activeDocument().id() == aCopyOfPart.id())
 # Remove another one document
 aSession.startOperation()
-aDoc2 = aSession.document("Part_2")
+aDoc2 = aSession.document(2)
 aSession.setActiveDocument(aDoc2, False)
 aDoc2.addFeature("Remove")
 aSession.finishOperation()
index 462a7366bdab45a2b9ebef798aa12ccf0bc41bdf..7b3e303d7e9738a94e5d6a467ca71dac4933c272 100644 (file)
@@ -5,6 +5,7 @@
 // Author:      Mikhail PONIKAROV
 
 #include "PartSetPlugin_Duplicate.h"
+#include "PartSetPlugin_Part.h"
 #include <ModelAPI_AttributeRefAttr.h>
 #include <ModelAPI_AttributeDocRef.h>
 #include <ModelAPI_Data.h>
 
 using namespace std;
 
-PartSetPlugin_Duplicate::PartSetPlugin_Duplicate()
-{
-}
-
-void PartSetPlugin_Duplicate::initAttributes()
+void PartSetPlugin_Duplicate::execute()
 {
-  PartSetPlugin_Part::initAttributes();
-
   std::shared_ptr<ModelAPI_Session> aPManager = ModelAPI_Session::get();
   std::shared_ptr<ModelAPI_Document> aRoot = aPManager->moduleDocument();
   std::shared_ptr<ModelAPI_ResultPart> aSource;  // searching for source document attribute
@@ -34,21 +29,12 @@ void PartSetPlugin_Duplicate::initAttributes()
     aSource.reset();
   }
   if (aSource) {
+    // create a new Part feature
+    FeaturePtr aNewPart = aRoot->addFeature(PartSetPlugin_Part::ID(), false);
+    aNewPart->execute(); // to make result and generate a unique name
+
     std::shared_ptr<ModelAPI_Document> aCopy = aPManager->copy(
-        aSource->data()->document(ModelAPI_ResultPart::DOC_REF())->value(), data()->name());
-  } else { // invalid part copy: do nothing, keep this in empty name
-    data()->setName("");
+      aSource->data()->document(ModelAPI_ResultPart::DOC_REF())->value(),
+      std::dynamic_pointer_cast<ModelAPI_ResultPart>(aNewPart->firstResult())->partDoc()->id());
   }
 }
-
-void PartSetPlugin_Duplicate::execute()
-{
-  if (!data()->name().empty())
-    PartSetPlugin_Part::execute();
-}
-
-const std::string& PartSetPlugin_Duplicate::documentToAdd()
-{
-  // part must be added only to the module document
-  return ModelAPI_Session::get()->moduleDocument()->kind();
-}
index 408d096e8ba5174caf57ec23ef33bd8e755fa47b..8553448bfa148a6a83efbd9d9668fed1a68317e2 100644 (file)
@@ -7,33 +7,56 @@
 #ifndef PartSetPlugin_Duplicate_H_
 #define PartSetPlugin_Duplicate_H_
 
-#include "PartSetPlugin_Part.h"
+#include "PartSetPlugin.h"
+#include <ModelAPI_Feature.h>
 
 /**\class PartSetPlugin_Duplicate
  * \ingroup Plugins
  * \brief Duplicates the active part (not root). Creates a new "part" feature.
  */
-class PartSetPlugin_Duplicate : public PartSetPlugin_Part
+class PartSetPlugin_Duplicate : public ModelAPI_Feature
 {
  public:
-    /// Duplicate kind
+  /// Duplicate kind
   inline static const std::string& ID()
   {
-    static const std::string MY_DUPLICATE_KIND("Duplicate");
-    return MY_DUPLICATE_KIND;
+    static const std::string MY_REMOVE_KIND("Duplicate");
+    return MY_REMOVE_KIND;
+  }
+  /// Returns the kind of a feature
+  PARTSETPLUGIN_EXPORT virtual const std::string& getKind()
+  {
+    static std::string MY_KIND = PartSetPlugin_Duplicate::ID();
+    return MY_KIND;
   }
 
-  /// Makes a new part, copy of active
-  PartSetPlugin_Duplicate();
-
-  /// Part must be added only to PartSet
-  PARTSETPLUGIN_EXPORT virtual const std::string& documentToAdd();
+  /// Returns to which group in the document must be added feature
+  PARTSETPLUGIN_EXPORT virtual const std::string& getGroup()
+  {
+    static std::string MY_GROUP = "Parts";
+    return MY_GROUP;
+  }
 
   /// Request for initialization of data model of the feature: adding all attributes
-  PARTSETPLUGIN_EXPORT virtual void initAttributes();
+  PARTSETPLUGIN_EXPORT virtual void initAttributes()
+  {
+  }
 
-  /// doesn't call creation of new document, just does nothing if document was not copied
+  /// Not normal feature that stored in the tree
+  PARTSETPLUGIN_EXPORT virtual bool isAction()
+  {
+    return true;
+  }
+
+  /// Performs the "duplicate"
   PARTSETPLUGIN_EXPORT virtual void execute();
+
+  /// Use plugin manager for features creation
+  PartSetPlugin_Duplicate()
+  {
+  }
+
 };
 
 #endif