diff --git a/src/App/Document.cpp b/src/App/Document.cpp index 7b8d560e99e1..b960cc8a9019 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -152,6 +152,8 @@ struct DocumentP // Array to preserve the creation order of created objects std::vector objectArray; std::map objectMap; + std::map objectIdMap; + long lastObjectId; DocumentObject* activeObject; Transaction *activeUndoTransaction; int iTransactionMode; @@ -169,6 +171,7 @@ struct DocumentP #endif //USE_OLD_DAG DocumentP() { + lastObjectId = 0; activeObject = 0; activeUndoTransaction = 0; iTransactionMode = 0; @@ -1666,6 +1669,7 @@ void Document::writeObjects(const std::vector& obj, writer.Stream() << writer.ind() << "getTypeId().getName() << "\" " << "name=\"" << (*it)->getExportName() << "\" " + << "id=\"" << (*it)->getID() << "\" " << "ViewType=\"" << (*it)->getViewProviderNameStored() << "\" "; // See DocumentObjectPy::getState @@ -1705,15 +1709,23 @@ Document::readObjects(Base::XMLReader& reader) setStatus(Document::KeepTrailingDigits, !reader.doNameMapping()); std::vector objs; + // read the object types reader.readElement("Objects"); int Cnt = reader.getAttributeAsInteger("Count"); + long lastId = 0; for (int i=0 ;ilastObjectId = reader.getAttributeAsInteger("id")-1; + } + // To prevent duplicate name when export/import of objects from // external documents, we append those external object name with // @. Before importing (here means we are called by @@ -1737,6 +1749,8 @@ Document::readObjects(Base::XMLReader& reader) // digits we make an object 'Cut' referencing itself. App::DocumentObject* obj = addObject(type.c_str(), obj_name, /*isNew=*/ false, viewType); if (obj) { + if(lastId < obj->_Id) + lastId = obj->_Id; objs.push_back(obj); // use this name for the later access because an object with // the given name may already exist @@ -1753,6 +1767,8 @@ Document::readObjects(Base::XMLReader& reader) Base::Console().Error("Cannot create object '%s': (%s)\n", name.c_str(), e.what()); } } + if(!testStatus(Status::Importing)) + d->lastObjectId = lastId; reader.readEndElement("Objects"); setStatus(Document::KeepTrailingDigits, keepDigits); @@ -2001,6 +2017,8 @@ void Document::restore (bool delaySignal) } d->objectArray.clear(); d->objectMap.clear(); + d->objectIdMap.clear(); + d->lastObjectId = 0; d->activeObject = 0; Base::FileInfo fi(FileName.getValue()); @@ -2930,6 +2948,9 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName, // insert in the name map d->objectMap[ObjectName] = pcObject; + // generate object id and add to id map; + pcObject->_Id = ++d->lastObjectId; + d->objectIdMap[pcObject->_Id] = pcObject; // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector @@ -3026,6 +3047,9 @@ std::vector Document::addObjects(const char* sType, const std: // insert in the name map d->objectMap[ObjectName] = pcObject; + // generate object id and add to id map; + pcObject->_Id = ++d->lastObjectId; + d->objectIdMap[pcObject->_Id] = pcObject; // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector @@ -3087,6 +3111,9 @@ void Document::addObject(DocumentObject* pcObject, const char* pObjectName) // insert in the name map d->objectMap[ObjectName] = pcObject; + // generate object id and add to id map; + if(!pcObject->_Id) pcObject->_Id = ++d->lastObjectId; + d->objectIdMap[pcObject->_Id] = pcObject; // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); // insert in the vector @@ -3114,6 +3141,9 @@ void Document::_addObject(DocumentObject* pcObject, const char* pObjectName) { std::string ObjectName = getUniqueObjectName(pObjectName); d->objectMap[ObjectName] = pcObject; + // generate object id and add to id map; + if(!pcObject->_Id) pcObject->_Id = ++d->lastObjectId; + d->objectIdMap[pcObject->_Id] = pcObject; d->objectArray.push_back(pcObject); // cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument()) pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first); @@ -3218,6 +3248,7 @@ void Document::removeObject(const char* sName) } pos->second->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side + d->objectIdMap.erase(pos->second->_Id); d->objectMap.erase(pos); } @@ -3261,6 +3292,7 @@ void Document::_removeObject(DocumentObject* pcObject) // remove from map pcObject->setStatus(ObjectStatus::Remove, false); // Unset the bit to be on the safe side + d->objectIdMap.erase(pcObject->_Id); d->objectMap.erase(pos); for (std::vector::iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it) { @@ -3528,6 +3560,15 @@ DocumentObject * Document::getObject(const char *Name) const return 0; } +DocumentObject * Document::getObjectByID(long id) const +{ + auto it = d->objectIdMap.find(id); + if(it!=d->objectIdMap.end()) + return it->second; + return 0; +} + + // Note: This method is only used in Tree.cpp slotChangeObject(), see explanation there bool Document::isIn(const DocumentObject *pFeat) const { diff --git a/src/App/Document.h b/src/App/Document.h index ed1061ff6725..c6fc60b4d03a 100644 --- a/src/App/Document.h +++ b/src/App/Document.h @@ -261,6 +261,8 @@ class AppExport Document : public App::PropertyContainer DocumentObject *getActiveObject(void) const; /// Returns a Object of this document DocumentObject *getObject(const char *Name) const; + /// Returns a Object of this document by its id + DocumentObject *getObjectByID(long id) const; /// Returns true if the DocumentObject is contained in this document bool isIn(const DocumentObject *pFeat) const; /// Returns a Name of an Object or 0 diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index 99c5f5eed9b8..be2bece1e030 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -54,7 +54,7 @@ DocumentObjectExecReturn *DocumentObject::StdReturn = 0; //=========================================================================== DocumentObject::DocumentObject(void) - : ExpressionEngine(),_pDoc(0),pcNameInDocument(0) + : ExpressionEngine(),_pDoc(0),pcNameInDocument(0),_Id(0) { // define Label of type 'Output' to avoid being marked as touched after relabeling ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)"); diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index f8d497522b41..acdca5cf82dc 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -106,6 +106,8 @@ class AppExport DocumentObject: public App::TransactionalObject /// returns the name which is set in the document for this object (not the name property!) const char *getNameInDocument(void) const; + /// + long getID() const {return _Id;} /// returns the name that is safe to be exported to other document std::string getExportName(bool forced=false) const; virtual bool isAttachedToDocument() const; @@ -416,6 +418,9 @@ class AppExport DocumentObject: public App::TransactionalObject private: // accessed by App::Document to record and restore the correct view provider type std::string _pcViewProviderName; + + // unique identifier (ammong a document) of this object. + long _Id; private: // Back pointer to all the fathers in a DAG of the document diff --git a/src/App/DocumentObjectPy.xml b/src/App/DocumentObjectPy.xml index 2069088e0a2e..9be5ea40d148 100644 --- a/src/App/DocumentObjectPy.xml +++ b/src/App/DocumentObjectPy.xml @@ -215,5 +215,11 @@ or None if the GUI is not up + + + The unique identifier (among its document) of this object + + + diff --git a/src/App/DocumentObjectPyImp.cpp b/src/App/DocumentObjectPyImp.cpp index c052b50e9587..6f92eca88fe1 100644 --- a/src/App/DocumentObjectPyImp.cpp +++ b/src/App/DocumentObjectPyImp.cpp @@ -686,3 +686,7 @@ int DocumentObjectPy::setCustomAttributes(const char* attr, PyObject *obj) return 0; } + +Py::Int DocumentObjectPy::getID() const { + return Py::Int(getDocumentObjectPtr()->getID()); +} diff --git a/src/App/DocumentPyImp.cpp b/src/App/DocumentPyImp.cpp index 5d939bb74cd1..e4f163c46764 100644 --- a/src/App/DocumentPyImp.cpp +++ b/src/App/DocumentPyImp.cpp @@ -550,11 +550,14 @@ PyObject* DocumentPy::recompute(PyObject * args) PyObject* DocumentPy::getObject(PyObject *args) { - char *sName; - if (!PyArg_ParseTuple(args, "s",&sName)) // convert args: Python->C - return NULL; // NULL triggers exception + long id = -1; + char *sName = 0; + if (!PyArg_ParseTuple(args, "s",&sName)) { // convert args: Python->C + if(!PyArg_ParseTuple(args, "i", &id)) + return NULL; // NULL triggers exception + } - DocumentObject *pcFtr = getDocumentPtr()->getObject(sName); + DocumentObject *pcFtr = sName?getDocumentPtr()->getObject(sName):getDocumentPtr()->getObjectByID(id); if (pcFtr) return pcFtr->getPyObject(); else