App: Property related API changes
Property: * Extended property status bitset. Mirror most of PropertyType and allow dynamic change property type. * Cache property name and type to improve performance * Centralize property status change signalling * Change aboutToSetValue()/hasSetValue() to virtual * Add new API getFullName() to obtain full quanlified name of the property AtomicPropertyChangeInterface: * Allow calling aboutToSetValue()/hasSetValue() when actually changed PropertyLists: * Refactor implementation by an abstract class PropertyListBase and a template class PropertyListsT, to allow better code reuse. PropertyListT is derived from AtomicPropertyChangeInterface to allow more efficient change on individual elements. * All list type property now accept setting python value as a dictionary with index as key to set individual element of a list. * Add touch list for more efficient handling of value changes. The list contains the index of changed value. And empty touch list should be treated as the entire list is changed. PropertyContainerPy expose this functionality with getPropertyTouchList(). PropertyPersistentObject: * New property to allow dynamic creation of any FreeCAD object derived from Base::Persistence, and use it as a property. DynamicProperty: * Use boost multi_index_container for efficient property lookup while keeping order. * Modify to be allowed to use in PropertyContainer directly PropertyContainer: * Use boost multi_index_container for efficient property lookup while keeping order. * Allow adding/removing dynamic property on all property container * Modify Save/Restore() to persist property status, and better handle transient property which can now be dynamically enabled/disabled per object. * Add new API getFullName() to obtain full quanlified name of the property. Implemented by Document, DocumentObject, and also ViewProviderDocumentObject if future patch DocumentObject and FeaturePython are modified to accommondate the dynamic property changes. Removed get/setCustomAttribute() implementation from DocumentObjectPy, and rely on PropertyContainerPy for the implementation, because of the additional dynamic property support in property container. Gui::ViewProviderDocumentObject, which is derived from PropertyContainer, is also modified accordingly
This commit is contained in:
@@ -35,10 +35,13 @@
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Exception.h>
|
||||
|
||||
#include "Application.h"
|
||||
#include "Property.h"
|
||||
#include "PropertyContainer.h"
|
||||
#include "PropertyLinks.h"
|
||||
|
||||
FC_LOG_LEVEL_INIT("App",true,true)
|
||||
|
||||
using namespace App;
|
||||
using namespace Base;
|
||||
using namespace std;
|
||||
@@ -71,18 +74,30 @@ unsigned int PropertyContainer::getMemSize (void) const
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
App::Property* PropertyContainer::addDynamicProperty(
|
||||
const char* type, const char* name, const char* group, const char* doc,
|
||||
short attr, bool ro, bool hidden)
|
||||
{
|
||||
return dynamicProps.addDynamicProperty(*this,type,name,group,doc,attr,ro,hidden);
|
||||
}
|
||||
|
||||
Property *PropertyContainer::getPropertyByName(const char* name) const
|
||||
{
|
||||
auto prop = dynamicProps.getDynamicPropertyByName(name);
|
||||
if(prop) return prop;
|
||||
return getPropertyData().getPropertyByName(this,name);
|
||||
}
|
||||
|
||||
void PropertyContainer::getPropertyMap(std::map<std::string,Property*> &Map) const
|
||||
{
|
||||
dynamicProps.getPropertyMap(Map);
|
||||
getPropertyData().getPropertyMap(this,Map);
|
||||
}
|
||||
|
||||
void PropertyContainer::getPropertyList(std::vector<Property*> &List) const
|
||||
{
|
||||
dynamicProps.getPropertyList(List);
|
||||
getPropertyData().getPropertyList(this,List);
|
||||
}
|
||||
|
||||
@@ -96,31 +111,39 @@ void PropertyContainer::setPropertyStatus(unsigned char bit,bool value)
|
||||
|
||||
short PropertyContainer::getPropertyType(const Property* prop) const
|
||||
{
|
||||
return getPropertyData().getType(this,prop);
|
||||
return prop?prop->getType():0;
|
||||
}
|
||||
|
||||
short PropertyContainer::getPropertyType(const char *name) const
|
||||
{
|
||||
return getPropertyData().getType(this,name);
|
||||
return getPropertyType(getPropertyByName(name));
|
||||
}
|
||||
|
||||
const char* PropertyContainer::getPropertyGroup(const Property* prop) const
|
||||
{
|
||||
auto group = dynamicProps.getPropertyGroup(prop);
|
||||
if(group) return group;
|
||||
return getPropertyData().getGroup(this,prop);
|
||||
}
|
||||
|
||||
const char* PropertyContainer::getPropertyGroup(const char *name) const
|
||||
{
|
||||
auto group = dynamicProps.getPropertyGroup(name);
|
||||
if(group) return group;
|
||||
return getPropertyData().getGroup(this,name);
|
||||
}
|
||||
|
||||
const char* PropertyContainer::getPropertyDocumentation(const Property* prop) const
|
||||
{
|
||||
auto doc = dynamicProps.getPropertyDocumentation(prop);
|
||||
if(doc) return doc;
|
||||
return getPropertyData().getDocumentation(this,prop);
|
||||
}
|
||||
|
||||
const char* PropertyContainer::getPropertyDocumentation(const char *name) const
|
||||
{
|
||||
auto doc = dynamicProps.getPropertyDocumentation(name);
|
||||
if(doc) return doc;
|
||||
return getPropertyData().getDocumentation(this,name);
|
||||
}
|
||||
|
||||
@@ -146,10 +169,12 @@ bool PropertyContainer::isHidden(const char *name) const
|
||||
|
||||
const char* PropertyContainer::getPropertyName(const Property* prop)const
|
||||
{
|
||||
return getPropertyData().getName(this,prop);
|
||||
auto res = dynamicProps.getPropertyName(prop);
|
||||
if(!res)
|
||||
res = getPropertyData().getName(this,prop);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
const PropertyData * PropertyContainer::getPropertyDataPtr(void){return &propertyData;}
|
||||
const PropertyData & PropertyContainer::getPropertyData(void) const{return propertyData;}
|
||||
|
||||
@@ -193,66 +218,82 @@ void PropertyContainer::handleChangedPropertyType(XMLReader &reader, const char
|
||||
|
||||
PropertyData PropertyContainer::propertyData;
|
||||
|
||||
/**
|
||||
* Binary function to query the flags for use with generic STL functions.
|
||||
*/
|
||||
template <class TCLASS>
|
||||
class PropertyAttribute : public std::binary_function<TCLASS, typename App::PropertyType, bool>
|
||||
{
|
||||
public:
|
||||
PropertyAttribute(const PropertyContainer* c) : cont(c) {}
|
||||
bool operator () (const TCLASS& prop, typename App::PropertyType attr) const
|
||||
{ return (cont->getPropertyType(prop.second) & attr) == attr; }
|
||||
private:
|
||||
const PropertyContainer* cont;
|
||||
};
|
||||
|
||||
void PropertyContainer::Save (Base::Writer &writer) const
|
||||
void PropertyContainer::Save (Base::Writer &writer) const
|
||||
{
|
||||
std::map<std::string,Property*> Map;
|
||||
getPropertyMap(Map);
|
||||
|
||||
// ignore the properties we won't store
|
||||
size_t ct = std::count_if(Map.begin(), Map.end(), std::bind2nd(PropertyAttribute
|
||||
<std::pair<std::string,Property*> >(this), Prop_Transient));
|
||||
size_t size = Map.size() - ct;
|
||||
std::vector<Property*> transients;
|
||||
for(auto it=Map.begin();it!=Map.end();) {
|
||||
auto prop = it->second;
|
||||
if(prop->testStatus(Property::PropNoPersist)) {
|
||||
it = Map.erase(it);
|
||||
continue;
|
||||
}
|
||||
if(!prop->testStatus(Property::PropDynamic)
|
||||
&& (prop->testStatus(Property::Transient) ||
|
||||
getPropertyType(prop) & Prop_Transient))
|
||||
{
|
||||
transients.push_back(prop);
|
||||
it = Map.erase(it);
|
||||
}else
|
||||
++it;
|
||||
}
|
||||
|
||||
writer.incInd(); // indentation for 'Properties Count'
|
||||
writer.Stream() << writer.ind() << "<Properties Count=\"" << size << "\">" << endl;
|
||||
std::map<std::string,Property*>::iterator it;
|
||||
for (it = Map.begin(); it != Map.end(); ++it)
|
||||
writer.Stream() << writer.ind() << "<Properties Count=\"" << Map.size()
|
||||
<< "\" TransientCount=\"" << transients.size() << "\">" << endl;
|
||||
|
||||
// First store transient properties to persisit their status value. We use
|
||||
// a new element named "_Property" so that the save file can be opened by
|
||||
// older version FC.
|
||||
writer.incInd();
|
||||
for(auto prop : transients) {
|
||||
writer.Stream() << writer.ind() << "<_Property name=\"" << prop->getName()
|
||||
<< "\" type=\"" << prop->getTypeId().getName()
|
||||
<< "\" status=\"" << prop->getStatus() << "\"/>" << std::endl;
|
||||
}
|
||||
writer.decInd();
|
||||
|
||||
// Now store normal properties
|
||||
for (auto it = Map.begin(); it != Map.end(); ++it)
|
||||
{
|
||||
// Don't write transient properties
|
||||
if (!(getPropertyType(it->second) & Prop_Transient))
|
||||
{
|
||||
writer.incInd(); // indentation for 'Property name'
|
||||
writer.Stream() << writer.ind() << "<Property name=\"" << it->first << "\" type=\""
|
||||
<< it->second->getTypeId().getName() << "\">" << endl;;
|
||||
writer.incInd(); // indentation for the actual property
|
||||
try {
|
||||
// We must make sure to handle all exceptions accordingly so that
|
||||
// the project file doesn't get invalidated. In the error case this
|
||||
// means to proceed instead of aborting the write operation.
|
||||
it->second->Save(writer);
|
||||
}
|
||||
catch (const Base::Exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const char* e) {
|
||||
Base::Console().Error("%s\n", e);
|
||||
}
|
||||
#ifndef FC_DEBUG
|
||||
catch (...) {
|
||||
Base::Console().Error("PropertyContainer::Save: Unknown C++ exception thrown. Try to continue...\n");
|
||||
}
|
||||
#endif
|
||||
writer.decInd(); // indentation for the actual property
|
||||
writer.Stream() << writer.ind() << "</Property>" << endl;
|
||||
writer.decInd(); // indentation for 'Property name'
|
||||
writer.incInd(); // indentation for 'Property name'
|
||||
writer.Stream() << writer.ind() << "<Property name=\"" << it->first << "\" type=\""
|
||||
<< it->second->getTypeId().getName();
|
||||
|
||||
dynamicProps.save(it->second,writer);
|
||||
|
||||
auto status = it->second->getStatus();
|
||||
if(status)
|
||||
writer.Stream() << "\" status=\"" << status;
|
||||
writer.Stream() << "\">" << std::endl;
|
||||
|
||||
writer.incInd(); // indentation for the actual property
|
||||
|
||||
try {
|
||||
// We must make sure to handle all exceptions accordingly so that
|
||||
// the project file doesn't get invalidated. In the error case this
|
||||
// means to proceed instead of aborting the write operation.
|
||||
it->second->Save(writer);
|
||||
}
|
||||
catch (const Base::Exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
Base::Console().Error("%s\n", e.what());
|
||||
}
|
||||
catch (const char* e) {
|
||||
Base::Console().Error("%s\n", e);
|
||||
}
|
||||
#ifndef FC_DEBUG
|
||||
catch (...) {
|
||||
Base::Console().Error("PropertyContainer::Save: Unknown C++ exception thrown. Try to continue...\n");
|
||||
}
|
||||
#endif
|
||||
writer.decInd(); // indentation for the actual property
|
||||
writer.Stream() << writer.ind() << "</Property>" << endl;
|
||||
writer.decInd(); // indentation for 'Property name'
|
||||
}
|
||||
writer.Stream() << writer.ind() << "</Properties>" << endl;
|
||||
writer.decInd(); // indentation for 'Properties Count'
|
||||
@@ -264,11 +305,33 @@ void PropertyContainer::Restore(Base::XMLReader &reader)
|
||||
reader.readElement("Properties");
|
||||
int Cnt = reader.getAttributeAsInteger("Count");
|
||||
|
||||
int transientCount = 0;
|
||||
if(reader.hasAttribute("TransientCount"))
|
||||
transientCount = reader.getAttributeAsUnsigned("TransientCount");
|
||||
|
||||
for (int i=0;i<transientCount; ++i) {
|
||||
reader.readElement("_Property");
|
||||
Property* prop = getPropertyByName(reader.getAttribute("name"));
|
||||
if(prop)
|
||||
FC_TRACE("restore transient '" << prop->getName() << "'");
|
||||
if(prop && reader.hasAttribute("status"))
|
||||
prop->setStatusValue(reader.getAttributeAsUnsigned("status"));
|
||||
}
|
||||
|
||||
for (int i=0 ;i<Cnt ;i++) {
|
||||
reader.readElement("Property");
|
||||
std::string PropName = reader.getAttribute("name");
|
||||
std::string TypeName = reader.getAttribute("type");
|
||||
Property* prop = getPropertyByName(PropName.c_str());
|
||||
auto prop = dynamicProps.restore(*this,PropName.c_str(),TypeName.c_str(),reader);
|
||||
if(!prop)
|
||||
prop = getPropertyByName(PropName.c_str());
|
||||
|
||||
decltype(Property::StatusBits) status;
|
||||
if(reader.hasAttribute("status")) {
|
||||
status = decltype(status)(reader.getAttributeAsUnsigned("status"));
|
||||
if(prop)
|
||||
prop->setStatusValue(status.to_ulong());
|
||||
}
|
||||
// NOTE: We must also check the type of the current property because a
|
||||
// subclass of PropertyContainer might change the type of a property but
|
||||
// not its name. In this case we would force to read-in a wrong property
|
||||
@@ -276,7 +339,15 @@ void PropertyContainer::Restore(Base::XMLReader &reader)
|
||||
try {
|
||||
// name and type match
|
||||
if (prop && strcmp(prop->getTypeId().getName(), TypeName.c_str()) == 0) {
|
||||
prop->Restore(reader);
|
||||
if (!prop->testStatus(Property::Transient)
|
||||
&& !status.test(Property::Transient)
|
||||
&& !status.test(Property::PropTransient)
|
||||
&& !(getPropertyType(prop) & Prop_Transient))
|
||||
{
|
||||
FC_TRACE("restore proeprty '" << prop->getName() << "'");
|
||||
prop->Restore(reader);
|
||||
}else
|
||||
FC_TRACE("skip transient '" << prop->getName() << "'");
|
||||
}
|
||||
// name matches but not the type
|
||||
else if (prop) {
|
||||
@@ -315,58 +386,98 @@ void PropertyContainer::Restore(Base::XMLReader &reader)
|
||||
Base::Console().Error("PropertyContainer::Restore: Unknown C++ exception thrown\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
reader.readEndElement("Property");
|
||||
}
|
||||
reader.readEndElement("Properties");
|
||||
}
|
||||
|
||||
void PropertyContainer::onPropertyStatusChanged(const Property &prop, unsigned long oldStatus)
|
||||
{
|
||||
(void)prop;
|
||||
(void)oldStatus;
|
||||
}
|
||||
|
||||
void PropertyData::addProperty(OffsetBase offsetBase,const char* PropName, Property *Prop, const char* PropertyGroup , PropertyType Type, const char* PropertyDocu)
|
||||
{
|
||||
bool IsIn = false;
|
||||
for (vector<PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
|
||||
if(strcmp(It->Name,PropName)==0)
|
||||
IsIn = true;
|
||||
#ifdef FC_DEBUG
|
||||
if(!parentMerged)
|
||||
#endif
|
||||
{
|
||||
short offset = offsetBase.getOffsetTo(Prop);
|
||||
if(offset < 0)
|
||||
throw Base::RuntimeError("Invalid static property");
|
||||
auto &index = propertyData.get<1>();
|
||||
auto it = index.find(PropName);
|
||||
if(it == index.end()) {
|
||||
if(parentMerged)
|
||||
throw Base::RuntimeError("Cannot add static property");
|
||||
index.emplace(PropName, PropertyGroup, PropertyDocu, offset, Type);
|
||||
} else{
|
||||
#ifdef FC_DEBUG
|
||||
if(it->Offset != offset) {
|
||||
FC_ERR("Duplicate property '" << PropName << "'");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if( !IsIn )
|
||||
{
|
||||
PropertySpec temp;
|
||||
temp.Name = PropName;
|
||||
temp.Offset = offsetBase.getOffsetTo(Prop);
|
||||
assert(temp.Offset>=0);
|
||||
temp.Group = PropertyGroup;
|
||||
temp.Type = Type;
|
||||
temp.Docu = PropertyDocu;
|
||||
propertyData.push_back(temp);
|
||||
}
|
||||
Prop->syncType(Type);
|
||||
Prop->myName = PropName;
|
||||
}
|
||||
|
||||
void PropertyData::merge(PropertyData *other) const {
|
||||
if(!other)
|
||||
other = const_cast<PropertyData*>(parentPropertyData);
|
||||
if(other == parentPropertyData) {
|
||||
if(parentMerged)
|
||||
return;
|
||||
parentMerged = true;
|
||||
}
|
||||
if(other) {
|
||||
other->merge();
|
||||
auto &index = propertyData.get<0>();
|
||||
for(const auto &spec : other->propertyData.get<0>())
|
||||
index.push_back(spec);
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyData::split(PropertyData *other) {
|
||||
if(other == parentPropertyData) {
|
||||
if(!parentMerged)
|
||||
return;
|
||||
parentMerged = false;
|
||||
}
|
||||
if(other) {
|
||||
auto &index = propertyData.get<2>();
|
||||
for(const auto &spec : other->propertyData.get<0>())
|
||||
index.erase(spec.Offset);
|
||||
}
|
||||
}
|
||||
|
||||
const PropertyData::PropertySpec *PropertyData::findProperty(OffsetBase offsetBase,const char* PropName) const
|
||||
{
|
||||
for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
|
||||
if(strcmp(It->Name,PropName)==0)
|
||||
return &(*It);
|
||||
|
||||
if(parentPropertyData)
|
||||
return parentPropertyData->findProperty(offsetBase,PropName);
|
||||
|
||||
return 0;
|
||||
(void)offsetBase;
|
||||
merge();
|
||||
auto &index = propertyData.get<1>();
|
||||
auto it = index.find(PropName);
|
||||
if(it != index.end())
|
||||
return &(*it);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const PropertyData::PropertySpec *PropertyData::findProperty(OffsetBase offsetBase,const Property* prop) const
|
||||
{
|
||||
const int diff = offsetBase.getOffsetTo(prop);
|
||||
if(diff<0)
|
||||
return 0;
|
||||
merge();
|
||||
int diff = offsetBase.getOffsetTo(prop);
|
||||
if(diff<0)
|
||||
return 0;
|
||||
|
||||
for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
|
||||
if(diff == It->Offset)
|
||||
return &(*It);
|
||||
|
||||
if(parentPropertyData)
|
||||
return parentPropertyData->findProperty(offsetBase,prop);
|
||||
|
||||
return 0;
|
||||
auto &index = propertyData.get<2>();
|
||||
auto it = index.find(diff);
|
||||
if(it!=index.end())
|
||||
return &(*it);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* PropertyData::getName(OffsetBase offsetBase,const Property* prop) const
|
||||
@@ -377,17 +488,6 @@ const char* PropertyData::getName(OffsetBase offsetBase,const Property* prop) co
|
||||
return Spec->Name;
|
||||
else
|
||||
return 0;
|
||||
/*
|
||||
|
||||
for(std::map<std::string,PropertySpec>::const_iterator pos = propertyData.begin();pos != propertyData.end();++pos)
|
||||
if(pos->second.Offset == diff)
|
||||
return pos->first.c_str();
|
||||
|
||||
if(parentPropertyData)
|
||||
return parentPropertyData->getName(container,prop);
|
||||
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
short PropertyData::getType(OffsetBase offsetBase,const Property* prop) const
|
||||
@@ -398,19 +498,6 @@ short PropertyData::getType(OffsetBase offsetBase,const Property* prop) const
|
||||
return Spec->Type;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/*
|
||||
const int diff = (int) ((char*)prop - (char*)container);
|
||||
|
||||
for(std::map<std::string,PropertySpec>::const_iterator pos = propertyData.begin();pos != propertyData.end();++pos)
|
||||
if(pos->second.Offset == diff)
|
||||
return pos->second.Type;
|
||||
|
||||
if(parentPropertyData)
|
||||
return parentPropertyData->getType(container,prop);
|
||||
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
short PropertyData::getType(OffsetBase offsetBase,const char* name) const
|
||||
@@ -431,19 +518,6 @@ const char* PropertyData::getGroup(OffsetBase offsetBase,const Property* prop) c
|
||||
return Spec->Group;
|
||||
else
|
||||
return 0;
|
||||
|
||||
/*
|
||||
const int diff = (int) ((char*)prop - (char*)container);
|
||||
|
||||
for(std::map<std::string,PropertySpec>::const_iterator pos = propertyData.begin();pos != propertyData.end();++pos)
|
||||
if(pos->second.Offset == diff)
|
||||
return pos->second.Group;
|
||||
|
||||
if(parentPropertyData)
|
||||
return parentPropertyData->getGroup(container,prop);
|
||||
|
||||
return 0;
|
||||
*/
|
||||
}
|
||||
|
||||
const char* PropertyData::getGroup(OffsetBase offsetBase,const char* name) const
|
||||
@@ -476,8 +550,6 @@ const char* PropertyData::getDocumentation(OffsetBase offsetBase,const char* nam
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Property *PropertyData::getPropertyByName(OffsetBase offsetBase,const char* name) const
|
||||
{
|
||||
const PropertyData::PropertySpec* Spec = findProperty(offsetBase,name);
|
||||
@@ -486,53 +558,22 @@ Property *PropertyData::getPropertyByName(OffsetBase offsetBase,const char* name
|
||||
return (Property *) (Spec->Offset + offsetBase.getOffset());
|
||||
else
|
||||
return 0;
|
||||
/*
|
||||
std::map<std::string,PropertySpec>::const_iterator pos = propertyData.find(name);
|
||||
|
||||
if(pos != propertyData.end())
|
||||
{
|
||||
// calculate propterty by offset
|
||||
return (Property *) (pos->second.Offset + (char *)container);
|
||||
}else{
|
||||
if(parentPropertyData)
|
||||
return parentPropertyData->getPropertyByName(container,name);
|
||||
else
|
||||
return 0;
|
||||
}*/
|
||||
}
|
||||
|
||||
void PropertyData::getPropertyMap(OffsetBase offsetBase,std::map<std::string,Property*> &Map) const
|
||||
{
|
||||
for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
|
||||
Map[It->Name] = (Property *) (It->Offset + offsetBase.getOffset());
|
||||
/*
|
||||
std::map<std::string,PropertySpec>::const_iterator pos;
|
||||
|
||||
for(pos = propertyData.begin();pos != propertyData.end();++pos)
|
||||
{
|
||||
Map[pos->first] = (Property *) (pos->second.Offset + (char *)container);
|
||||
}
|
||||
*/
|
||||
|
||||
if(parentPropertyData)
|
||||
parentPropertyData->getPropertyMap(offsetBase,Map);
|
||||
|
||||
merge();
|
||||
for(auto &spec : propertyData.get<0>())
|
||||
Map[spec.Name] = (Property *) (spec.Offset + offsetBase.getOffset());
|
||||
}
|
||||
|
||||
void PropertyData::getPropertyList(OffsetBase offsetBase,std::vector<Property*> &List) const
|
||||
{
|
||||
for (vector<PropertyData::PropertySpec>::const_iterator It = propertyData.begin(); It != propertyData.end(); ++It)
|
||||
List.push_back((Property *) (It->Offset + offsetBase.getOffset()) );
|
||||
|
||||
/* std::map<std::string,PropertySpec>::const_iterator pos;
|
||||
|
||||
for(pos = propertyData.begin();pos != propertyData.end();++pos)
|
||||
{
|
||||
List.push_back((Property *) (pos->second.Offset + (char *)container) );
|
||||
}*/
|
||||
if(parentPropertyData)
|
||||
parentPropertyData->getPropertyList(offsetBase,List);
|
||||
|
||||
merge();
|
||||
size_t base = List.size();
|
||||
List.reserve(base+propertyData.size());
|
||||
for (auto &spec : propertyData.get<0>())
|
||||
List.push_back((Property *) (spec.Offset + offsetBase.getOffset()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user