Skip to content

Commit

Permalink
DocumentObject: introduce object ID
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
realthunder committed Mar 5, 2018
1 parent e057cc1 commit ba4a6e6
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 5 deletions.
41 changes: 41 additions & 0 deletions src/App/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@ struct DocumentP
// Array to preserve the creation order of created objects
std::vector<DocumentObject*> objectArray;
std::map<std::string,DocumentObject*> objectMap;
std::map<long,DocumentObject*> objectIdMap;
long lastObjectId;
DocumentObject* activeObject;
Transaction *activeUndoTransaction;
int iTransactionMode;
Expand All @@ -169,6 +171,7 @@ struct DocumentP
#endif //USE_OLD_DAG

DocumentP() {
lastObjectId = 0;
activeObject = 0;
activeUndoTransaction = 0;
iTransactionMode = 0;
Expand Down Expand Up @@ -1666,6 +1669,7 @@ void Document::writeObjects(const std::vector<App::DocumentObject*>& obj,
writer.Stream() << writer.ind() << "<Object "
<< "type=\"" << (*it)->getTypeId().getName() << "\" "
<< "name=\"" << (*it)->getExportName() << "\" "
<< "id=\"" << (*it)->getID() << "\" "
<< "ViewType=\"" << (*it)->getViewProviderNameStored() << "\" ";

// See DocumentObjectPy::getState
Expand Down Expand Up @@ -1705,15 +1709,23 @@ Document::readObjects(Base::XMLReader& reader)
setStatus(Document::KeepTrailingDigits, !reader.doNameMapping());
std::vector<App::DocumentObject*> objs;


// read the object types
reader.readElement("Objects");
int Cnt = reader.getAttributeAsInteger("Count");
long lastId = 0;
for (int i=0 ;i<Cnt ;i++) {
reader.readElement("Object");
std::string type = reader.getAttribute("type");
std::string name = reader.getAttribute("name");
const char *viewType = reader.hasAttribute("ViewType")?reader.getAttribute("ViewType"):0;

if(!testStatus(Status::Importing) && reader.hasAttribute("id")) {
// if not importing, then temporary reset lastObjectId and make the
// following addObject() generate the correct id for this object.
d->lastObjectId = reader.getAttributeAsInteger("id")-1;
}

// To prevent duplicate name when export/import of objects from
// external documents, we append those external object name with
// @<doccument name>. Before importing (here means we are called by
Expand All @@ -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
Expand All @@ -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);
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -3026,6 +3047,9 @@ std::vector<DocumentObject *> 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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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<DocumentObject*>::iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it) {
Expand Down Expand Up @@ -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
{
Expand Down
2 changes: 2 additions & 0 deletions src/App/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/App/DocumentObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)");
Expand Down
5 changes: 5 additions & 0 deletions src/App/DocumentObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions src/App/DocumentObjectPy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -215,5 +215,11 @@ or None if the GUI is not up</UserDocu>
</Documentation>
<Parameter Name="MustExecute" Type="Boolean"/>
</Attribute>
<Attribute Name="ID" ReadOnly="true">
<Documentation>
<UserDocu>The unique identifier (among its document) of this object</UserDocu>
</Documentation>
<Parameter Name="ID" Type="Int"/>
</Attribute>
</PythonExport>
</GenerateModel>
4 changes: 4 additions & 0 deletions src/App/DocumentObjectPyImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -686,3 +686,7 @@ int DocumentObjectPy::setCustomAttributes(const char* attr, PyObject *obj)

return 0;
}

Py::Int DocumentObjectPy::getID() const {
return Py::Int(getDocumentObjectPtr()->getID());
}
11 changes: 7 additions & 4 deletions src/App/DocumentPyImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit ba4a6e6

Please sign in to comment.