From ba4a6e6c1d8af75b0aac04f03aaec1cec16663c6 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Wed, 28 Feb 2018 19:51:53 +0800 Subject: [PATCH] DocumentObject: introduce object ID Each object now has an integer ID that is unique with its containing document. It is meant to serve the same purpose as internal object name but easier to manipulate. --- src/App/Document.cpp | 41 +++++++++++++++++++++++++++++++++ src/App/Document.h | 2 ++ src/App/DocumentObject.cpp | 2 +- src/App/DocumentObject.h | 5 ++++ src/App/DocumentObjectPy.xml | 6 +++++ src/App/DocumentObjectPyImp.cpp | 4 ++++ src/App/DocumentPyImp.cpp | 11 +++++---- 7 files changed, 66 insertions(+), 5 deletions(-) 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