PropertyLinkSubList: make it backwards-compatible with PropertyLinkSub
To assist porting Sketch's Support property from linkSub to linkSubList. Includes file reading backwards compatibility.
This commit is contained in:
parent
eccff10d90
commit
ac5730996d
|
@ -233,9 +233,18 @@ void PropertyContainer::Restore(Base::XMLReader &reader)
|
|||
// 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
|
||||
// type and the behaviour would be undefined.
|
||||
// Exception: PropertyLinkSubList can read PropertyLinkSub
|
||||
try {
|
||||
if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0)
|
||||
prop->Restore(reader);
|
||||
if(prop){
|
||||
if (strcmp(prop->getTypeId().getName(), TypeName) == 0){
|
||||
prop->Restore(reader);
|
||||
} else if (prop->isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())){
|
||||
App::PropertyLinkSub tmp;//getTypeId() is not static =(
|
||||
if (0 == strcmp(tmp.getTypeId().getName(),TypeName)) {
|
||||
static_cast<App::PropertyLinkSubList*>(prop)->Restore_FromLinkSub(reader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const Base::XMLParseException&) {
|
||||
throw; // re-throw
|
||||
|
|
|
@ -547,11 +547,18 @@ void PropertyLinkSubList::setValue(DocumentObject* lValue,const char* SubName)
|
|||
_lSubList.resize(1);
|
||||
_lSubList[0]=SubName;
|
||||
hasSetValue();
|
||||
} else {
|
||||
aboutToSetValue();
|
||||
_lValueList.clear();
|
||||
_lSubList.clear();
|
||||
hasSetValue();
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyLinkSubList::setValues(const std::vector<DocumentObject*>& lValue,const std::vector<const char*>& lSubNames)
|
||||
{
|
||||
if (lValue.size() != lSubNames.size())
|
||||
throw Base::Exception("PropertyLinkSubList::setValues: size of subelements list != size of objects list");
|
||||
aboutToSetValue();
|
||||
_lValueList = lValue;
|
||||
_lSubList.resize(lSubNames.size());
|
||||
|
@ -563,12 +570,71 @@ void PropertyLinkSubList::setValues(const std::vector<DocumentObject*>& lValue,c
|
|||
|
||||
void PropertyLinkSubList::setValues(const std::vector<DocumentObject*>& lValue,const std::vector<std::string>& lSubNames)
|
||||
{
|
||||
if (lValue.size() != lSubNames.size())
|
||||
throw Base::Exception("PropertyLinkSubList::setValues: size of subelements list != size of objects list");
|
||||
aboutToSetValue();
|
||||
_lValueList = lValue;
|
||||
_lSubList = lSubNames;
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
void PropertyLinkSubList::setValue(DocumentObject* lValue, const std::vector<string> &SubList)
|
||||
{
|
||||
aboutToSetValue();
|
||||
int size = SubList.size();
|
||||
this->_lValueList.clear();
|
||||
if (size == 0) {
|
||||
if (lValue)
|
||||
this->_lValueList.push_back(lValue);
|
||||
this->_lSubList.clear();
|
||||
} else {
|
||||
this->_lSubList = SubList;
|
||||
this->_lValueList.insert(this->_lValueList.begin(), size, lValue);
|
||||
}
|
||||
hasSetValue();
|
||||
}
|
||||
|
||||
const string PropertyLinkSubList::getPyReprString()
|
||||
{
|
||||
assert(this->_lValueList.size() == this->_lSubList.size());
|
||||
|
||||
if (this->_lValueList.size() == 0)
|
||||
return std::string("None");
|
||||
|
||||
std::stringstream strm;
|
||||
strm << "[";
|
||||
for ( int i = 0 ; i < this->_lSubList.size() ; i++) {
|
||||
if (i>0)
|
||||
strm << ",(";
|
||||
else
|
||||
strm << "(";
|
||||
App::DocumentObject* obj = this->_lValueList[i];
|
||||
if (obj) {
|
||||
strm << "App.getDocument('" << obj->getDocument()->getName() << "')." << obj->getNameInDocument();
|
||||
} else {
|
||||
strm << "None";
|
||||
}
|
||||
strm << ",";
|
||||
strm << "'" << this->_lSubList[i] << "'";
|
||||
strm << ")";
|
||||
}
|
||||
strm << "]";
|
||||
return strm.str();
|
||||
}
|
||||
|
||||
DocumentObject *PropertyLinkSubList::getValue() const
|
||||
{
|
||||
App::DocumentObject* ret = 0;
|
||||
//FIXME: cache this to avoid iterating each time, to improve speed
|
||||
for (int i = 0 ; i < this->_lValueList.size() ; i++){
|
||||
if (ret == 0)
|
||||
ret = this->_lValueList[i];
|
||||
if (ret != this->_lValueList[i])
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PropertyLinkSubList::getPyObject(void)
|
||||
{
|
||||
unsigned int count = getSize();
|
||||
|
@ -591,44 +657,50 @@ PyObject *PropertyLinkSubList::getPyObject(void)
|
|||
|
||||
void PropertyLinkSubList::setPyObject(PyObject *value)
|
||||
{
|
||||
if (PyTuple_Check(value) || PyList_Check(value)) {
|
||||
Py::Sequence list(value);
|
||||
Py::Sequence::size_type size = list.size();
|
||||
try { //try PropertyLinkSub syntax
|
||||
PropertyLinkSub dummy;
|
||||
dummy.setPyObject(value);
|
||||
this->setValue(dummy.getValue(), dummy.getSubValues());
|
||||
} catch (Base::TypeError) {
|
||||
|
||||
std::vector<DocumentObject*> values;
|
||||
values.reserve(size);
|
||||
std::vector<std::string> SubNames;
|
||||
SubNames.reserve(size);
|
||||
if (PyTuple_Check(value) || PyList_Check(value)) {
|
||||
Py::Sequence list(value);
|
||||
Py::Sequence::size_type size = list.size();
|
||||
|
||||
for (Py::Sequence::size_type i=0; i<size; i++) {
|
||||
Py::Object item = list[i];
|
||||
if (item.isTuple()) {
|
||||
Py::Tuple tup(item);
|
||||
if (PyObject_TypeCheck(tup[0].ptr(), &(DocumentObjectPy::Type))){
|
||||
DocumentObjectPy *pcObj;
|
||||
pcObj = static_cast<DocumentObjectPy*>(tup[0].ptr());
|
||||
values.push_back(pcObj->getDocumentObjectPtr());
|
||||
if (Py::Object(tup[1].ptr()).isString()){
|
||||
SubNames.push_back(Py::String(tup[1].ptr()));
|
||||
std::vector<DocumentObject*> values;
|
||||
values.reserve(size);
|
||||
std::vector<std::string> SubNames;
|
||||
SubNames.reserve(size);
|
||||
for (Py::Sequence::size_type i=0; i<size; i++) {
|
||||
Py::Object item = list[i];
|
||||
if (item.isTuple()) {
|
||||
Py::Tuple tup(item);
|
||||
if (PyObject_TypeCheck(tup[0].ptr(), &(DocumentObjectPy::Type))){
|
||||
DocumentObjectPy *pcObj;
|
||||
pcObj = static_cast<DocumentObjectPy*>(tup[0].ptr());
|
||||
values.push_back(pcObj->getDocumentObjectPtr());
|
||||
if (Py::Object(tup[1].ptr()).isString()){
|
||||
SubNames.push_back(Py::String(tup[1].ptr()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) {
|
||||
DocumentObjectPy *pcObj;
|
||||
pcObj = static_cast<DocumentObjectPy*>(*item);
|
||||
values.push_back(pcObj->getDocumentObjectPtr());
|
||||
}
|
||||
else if (item.isString()) {
|
||||
SubNames.push_back(Py::String(item));
|
||||
}
|
||||
}
|
||||
else if (PyObject_TypeCheck(*item, &(DocumentObjectPy::Type))) {
|
||||
DocumentObjectPy *pcObj;
|
||||
pcObj = static_cast<DocumentObjectPy*>(*item);
|
||||
values.push_back(pcObj->getDocumentObjectPtr());
|
||||
}
|
||||
else if (item.isString()) {
|
||||
SubNames.push_back(Py::String(item));
|
||||
}
|
||||
}
|
||||
|
||||
setValues(values,SubNames);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
setValues(values,SubNames);
|
||||
}
|
||||
else {
|
||||
std::string error = std::string("type must be 'DocumentObject' or list of 'DocumentObject', not ");
|
||||
error += value->ob_type->tp_name;
|
||||
throw Base::TypeError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,6 +755,44 @@ void PropertyLinkSubList::Restore(Base::XMLReader &reader)
|
|||
setValues(values,SubNames);
|
||||
}
|
||||
|
||||
void PropertyLinkSubList::Restore_FromLinkSub(XMLReader &reader)
|
||||
{
|
||||
//Copy-paste from PropertyLinkSub::Restore()
|
||||
// read my element
|
||||
reader.readElement("LinkSub");
|
||||
// get the values of my attributes
|
||||
std::string name = reader.getAttribute("value");
|
||||
int count = reader.getAttributeAsInteger("count");
|
||||
|
||||
// Property not in a DocumentObject!
|
||||
assert(getContainer()->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId()) );
|
||||
|
||||
std::vector<std::string> values(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
reader.readElement("Sub");
|
||||
values[i] = reader.getAttribute("value");
|
||||
}
|
||||
|
||||
reader.readEndElement("LinkSub");
|
||||
|
||||
DocumentObject *pcObject;
|
||||
if (name != ""){
|
||||
App::Document* document = static_cast<DocumentObject*>(getContainer())->getDocument();
|
||||
pcObject = document ? document->getObject(name.c_str()) : 0;
|
||||
if (!pcObject) {
|
||||
if (reader.isVerbose()) {
|
||||
Base::Console().Warning("Lost link to '%s' while loading, maybe "
|
||||
"an object was not loaded correctly\n",name.c_str());
|
||||
}
|
||||
}
|
||||
setValue(pcObject,values);
|
||||
}
|
||||
else {
|
||||
setValue(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Property *PropertyLinkSubList::Copy(void) const
|
||||
{
|
||||
PropertyLinkSubList *p = new PropertyLinkSubList();
|
||||
|
|
|
@ -247,12 +247,19 @@ public:
|
|||
virtual void setSize(int newSize);
|
||||
virtual int getSize(void) const;
|
||||
|
||||
/** Sets the property
|
||||
/** Sets the property.
|
||||
* setValue(0, whatever) clears the property
|
||||
*/
|
||||
void setValue(DocumentObject*,const char*);
|
||||
void setValues(const std::vector<DocumentObject*>&,const std::vector<const char*>&);
|
||||
void setValues(const std::vector<DocumentObject*>&,const std::vector<std::string>&);
|
||||
|
||||
/**
|
||||
* @brief setValue: PropertyLinkSub-compatible overload
|
||||
* @param SubList
|
||||
*/
|
||||
void setValue(App::DocumentObject *lValue, const std::vector<std::string> &SubList=std::vector<std::string>());
|
||||
|
||||
// index operator
|
||||
SubSet operator[] (const int idx) const {
|
||||
return SubSet(_lValueList.operator[] (idx),_lSubList.operator [](idx));
|
||||
|
@ -262,6 +269,16 @@ public:
|
|||
return _lValueList;
|
||||
}
|
||||
|
||||
const std::string getPyReprString();
|
||||
|
||||
/**
|
||||
* @brief getValue emulates the action of a single-object link.
|
||||
* @return reference to object, if the link os to only one object. NULL if
|
||||
* the link is empty, or links to subelements of more than one documant
|
||||
* object.
|
||||
*/
|
||||
DocumentObject* getValue() const;
|
||||
|
||||
const std::vector<std::string> &getSubValues(void) const {
|
||||
return _lSubList;
|
||||
}
|
||||
|
@ -271,6 +288,7 @@ public:
|
|||
|
||||
virtual void Save (Base::Writer &writer) const;
|
||||
virtual void Restore(Base::XMLReader &reader);
|
||||
virtual void Restore_FromLinkSub(Base::XMLReader &reader);
|
||||
|
||||
virtual Property *Copy(void) const;
|
||||
virtual void Paste(const Property &from);
|
||||
|
|
Loading…
Reference in New Issue
Block a user