void Chamfer::Restore(Base::XMLReader &reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); try { if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) { prop->Restore(reader); } else if (prop && strcmp(TypeName,"App::PropertyFloatConstraint") == 0 && strcmp(prop->getTypeId().getName(), "App::PropertyQuantityConstraint") == 0) { App::PropertyFloatConstraint p; p.Restore(reader); static_cast<App::PropertyQuantityConstraint*>(prop)->setValue(p.getValue()); } } catch (const Base::XMLParseException&) { throw; // re-throw } catch (const Base::Exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const std::exception &e) { Base::Console().Error("%s\n", e.what()); } reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void DynamicProperty::Restore(Base::XMLReader &reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); Property* prop = getPropertyByName(PropName); try { if (!prop) { short attribute = 0; bool readonly = false, hidden = false; const char *group=0, *doc=0, *attr=0, *ro=0, *hide=0; if (reader.hasAttribute("group")) group = reader.getAttribute("group"); if (reader.hasAttribute("doc")) doc = reader.getAttribute("doc"); if (reader.hasAttribute("attr")) { attr = reader.getAttribute("attr"); if (attr) attribute = attr[0]-48; } if (reader.hasAttribute("ro")) { ro = reader.getAttribute("ro"); if (ro) readonly = (ro[0]-48) != 0; } if (reader.hasAttribute("hide")) { hide = reader.getAttribute("hide"); if (hide) hidden = (hide[0]-48) != 0; } prop = addDynamicProperty(TypeName, PropName, group, doc, attribute, readonly, hidden); } } catch(const Base::Exception& e) { // only handle this exception type Base::Console().Warning(e.what()); } //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 type and the behaviour would be //undefined. // Don't read transient properties if (!(getPropertyType(prop) & Prop_Transient)) { if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) prop->Restore(reader); else if (prop) Base::Console().Warning("%s: Overread data for property %s of type %s, expected type is %s\n", pc->getTypeId().getName(), prop->getName(), prop->getTypeId().getName(), TypeName); else Base::Console().Warning("%s: No property found with name %s and type %s\n", pc->getTypeId().getName(), PropName, TypeName); } reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void Part2DObject::Restore(Base::XMLReader &reader) { //override generic restoration to convert Support property from PropertyLinkSub to PropertyLinkSubList reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); // 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 // type and the behaviour would be undefined. try { if(prop){ if (strcmp(prop->getTypeId().getName(), TypeName) == 0){ prop->Restore(reader); } else if (prop->isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())){ //reading legacy Support - when the Support could only be a single flat face. App::PropertyLinkSub tmp; if (0 == strcmp(tmp.getTypeId().getName(),TypeName)) { tmp.setContainer(this); tmp.Restore(reader); static_cast<App::PropertyLinkSubList*>(prop)->setValue(tmp.getValue(), tmp.getSubValues()); } this->MapMode.setValue(Attacher::mmFlatFace); } } } catch (const Base::XMLParseException&) { throw; // re-throw } 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::Restore: Unknown C++ exception thrown"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void Primitive::Restore(Base::XMLReader &reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); // For #0001652 the property types of many primitive features have changed // from PropertyFloat or PropertyFloatConstraint to a more meaningful type. // In order to load older project files there must be checked in case the // types don't match if both inherit from PropertyFloat because all derived // classes do not re-implement the Save/Restore methods. try { if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) { prop->Restore(reader); } else if (prop) { Base::Type inputType = Base::Type::fromName(TypeName); if (prop->getTypeId().isDerivedFrom(App::PropertyFloat::getClassTypeId()) && inputType.isDerivedFrom(App::PropertyFloat::getClassTypeId())) { // Do not directly call the property's Restore method in case the implmentation // has changed. So, create a temporary PropertyFloat object and assign the value. App::PropertyFloat floatProp; floatProp.Restore(reader); static_cast<App::PropertyFloat*>(prop)->setValue(floatProp.getValue()); } } } catch (const Base::XMLParseException&) { throw; // re-throw } 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("Primitive::Restore: Unknown C++ exception thrown"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void ProfileBased::Restore(Base::XMLReader& reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); // 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 // type and the behaviour would be undefined. try { //check if we load the old sketch property if(!prop && (strcmp("Sketch", PropName) == 0) && (strcmp("App::PropertyLink", TypeName) == 0)) { std::vector<std::string> vec; // read my element reader.readElement("Link"); // get the value of my attribute std::string name = reader.getAttribute("value"); if (name != "") { App::Document* document = getDocument(); DocumentObject* object = document ? document->getObject(name.c_str()) : 0; Profile.setValue(object, vec); } else { Profile.setValue(0, vec); } } else if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) prop->Restore(reader); } catch (const Base::XMLParseException&) { throw; // re-throw } 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); } reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void Transformed::Restore(Base::XMLReader &reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); // The property 'Angle' of PolarPattern has changed from PropertyFloat // to PropertyAngle and the property 'Length' has changed to PropertyLength. try { if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) { prop->Restore(reader); } else if (prop) { Base::Type inputType = Base::Type::fromName(TypeName); if (prop->getTypeId().isDerivedFrom(App::PropertyFloat::getClassTypeId()) && inputType.isDerivedFrom(App::PropertyFloat::getClassTypeId())) { // Do not directly call the property's Restore method in case the implmentation // has changed. So, create a temporary PropertyFloat object and assign the value. App::PropertyFloat floatProp; floatProp.Restore(reader); static_cast<App::PropertyFloat*>(prop)->setValue(floatProp.getValue()); } } } catch (const Base::XMLParseException&) { throw; // re-throw } 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("Primitive::Restore: Unknown C++ exception thrown"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void PropertyLinkSub::Restore(Base::XMLReader &reader) { // 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.empty()) { 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); } }
void PropertyFileIncluded::Restore(Base::XMLReader &reader) { reader.readElement("FileIncluded"); if (reader.hasAttribute("file")) { string file (reader.getAttribute("file") ); if (!file.empty()) { // initate a file read reader.addFile(file.c_str(),this); // is in the document transient path aboutToSetValue(); _cValue = getDocTransientPath() + "/" + file; _BaseFileName = file; hasSetValue(); } } // section is XML stream else if (reader.hasAttribute("data")) { string file (reader.getAttribute("data") ); if (!file.empty()) { // is in the document transient path aboutToSetValue(); _cValue = getDocTransientPath() + "/" + file; reader.readBinFile(_cValue.c_str()); reader.readEndElement("FileIncluded"); _BaseFileName = file; hasSetValue(); } } }
void PropertyConstraintList::Restore(Base::XMLReader &reader) { // read my element reader.readElement("ConstraintList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); std::vector<Constraint*> values; values.reserve(count); for (int i = 0; i < count; i++) { Constraint *newC = new Constraint(); newC->Restore(reader); // To keep upward compatibility ignore unknown constraint types if (newC->Type < Sketcher::NumConstraintTypes) { values.push_back(newC); } else { // reading a new constraint type which this version cannot handle delete newC; } } reader.readEndElement("ConstraintList"); // assignment setValues(values); for (Constraint* it : values) delete it; }
void PropertyColumnWidths::Restore(Base::XMLReader &reader) { int Cnt; // Column info reader.readElement("ColumnInfo"); Cnt = reader.hasAttribute("Count") ? reader.getAttributeAsInteger("Count") : 0; for (int i = 0; i < Cnt; i++) { reader.readElement("Column"); const char* name = reader.hasAttribute("name") ? reader.getAttribute("name") : 0; const char * width = reader.hasAttribute("width") ? reader.getAttribute("width") : 0; try { if (name && width) { int col = App::decodeColumn(name); int colWidth = atoi(width); setValue(col, colWidth); } } catch (...) { // Something is wrong, skip this column } } reader.readEndElement("ColumnInfo"); }
void PropertyLinkSubList::Restore(Base::XMLReader &reader) { // read my element reader.readElement("LinkSubList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); std::vector<DocumentObject*> values; values.reserve(count); std::vector<std::string> SubNames; SubNames.reserve(count); for (int i = 0; i < count; i++) { reader.readElement("Link"); std::string name = reader.getAttribute("obj"); // In order to do copy/paste it must be allowed to have defined some // referenced objects in XML which do not exist anymore in the new // document. Thus, we should silently ignore this. // Property not in an object! DocumentObject* father = static_cast<DocumentObject*>(getContainer()); App::Document* document = father->getDocument(); DocumentObject* child = document ? document->getObject(name.c_str()) : 0; if (child) values.push_back(child); else if (reader.isVerbose()) Base::Console().Warning("Lost link to '%s' while loading, maybe " "an object was not loaded correctly\n",name.c_str()); std::string subName = reader.getAttribute("sub"); SubNames.push_back(subName); } reader.readEndElement("LinkSubList"); // assignment setValues(values,SubNames); }
void PropertyRowHeights::Restore(Base::XMLReader &reader) { int Cnt; // Row info reader.readElement("RowInfo"); Cnt = reader.hasAttribute("Count") ? reader.getAttributeAsInteger("Count") : 0; for (int i = 0; i < Cnt; i++) { reader.readElement("Row"); const char* name = reader.hasAttribute("name") ? reader.getAttribute("name") : 0; const char * height = reader.hasAttribute("height") ? reader.getAttribute("height") : 0; try { if (name && height) { int row = App::decodeRow(name); int rowHeight = atoi(height); setValue(row, rowHeight); } } catch (...) { // Something is wrong, skip this row } } reader.readEndElement("RowInfo"); }
void PropertyGeometryList::Restore(Base::XMLReader &reader) { // read my element reader.readElement("GeometryList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); std::vector<Geometry*> values; values.reserve(count); for (int i = 0; i < count; i++) { reader.readElement("Geometry"); const char* TypeName = reader.getAttribute("type"); Geometry *newG = (Geometry *)Base::Type::fromName(TypeName).createInstance(); newG->Restore(reader); values.push_back(newG); reader.readEndElement("Geometry"); } reader.readEndElement("GeometryList"); // assignment setValues(values); }
void PropertyIntegerList::Restore(Base::XMLReader &reader) { // read my Element reader.readElement("IntegerList"); // get the value of my Attribute int count = reader.getAttributeAsInteger("count"); std::vector<long> values(count); for(int i = 0; i < count; i++) { reader.readElement("I"); values[i] = reader.getAttributeAsInteger("v"); } reader.readEndElement("IntegerList"); //assignment setValues(values); }
void PropertyExpressionEngine::Restore(Base::XMLReader &reader) { reader.readElement("ExpressionEngine"); int count = reader.getAttributeAsFloat("count"); for (int i = 0; i < count; ++i) { DocumentObject * docObj = freecad_dynamic_cast<DocumentObject>(getContainer()); reader.readElement("Expression"); ObjectIdentifier path = ObjectIdentifier::parse(docObj, reader.getAttribute("path")); boost::shared_ptr<Expression> expression(ExpressionParser::parse(docObj, reader.getAttribute("expression"))); const char * comment = reader.hasAttribute("comment") ? reader.getAttribute("comment") : 0; setValue(path, expression, comment); } reader.readEndElement("ExpressionEngine"); }
void PropertyLinkList::Restore(Base::XMLReader &reader) { // read my element reader.readElement("LinkList"); // get the value of my attribute int count = reader.getAttributeAsInteger("count"); App::PropertyContainer* container = getContainer(); if (!container) throw Base::RuntimeError("Property is not part of a container"); if (!container->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { std::stringstream str; str << "Container is not a document object (" << container->getTypeId().getName() << ")"; throw Base::TypeError(str.str()); } std::vector<DocumentObject*> values; values.reserve(count); for (int i = 0; i < count; i++) { reader.readElement("Link"); std::string name = reader.getAttribute("value"); // In order to do copy/paste it must be allowed to have defined some // referenced objects in XML which do not exist anymore in the new // document. Thus, we should silently ignore this. // Property not in an object! DocumentObject* father = static_cast<DocumentObject*>(getContainer()); App::Document* document = father->getDocument(); DocumentObject* child = document ? document->getObject(name.c_str()) : 0; if (child) values.push_back(child); else if (reader.isVerbose()) Base::Console().Warning("Lost link to '%s' while loading, maybe " "an object was not loaded correctly\n", name.c_str()); } reader.readEndElement("LinkList"); // assignment setValues(values); }
void PropertyEnumeration::Restore(Base::XMLReader &reader) { // read my Element reader.readElement("Integer"); // get the value of my Attribute long val = reader.getAttributeAsInteger("value"); if (reader.hasAttribute("CustomEnum")) { reader.readElement("CustomEnumList"); int count = reader.getAttributeAsInteger("count"); std::vector<std::string> values(count); for(int i = 0; i < count; i++) { reader.readElement("Enum"); values[i] = reader.getAttribute("value"); } reader.readEndElement("CustomEnumList"); _CustomEnum = true; setEnumVector(values); } setValue(val); }
//DVA is still Source PropertyLink so needs different logic vs DV::Restore void DrawViewArch::Restore(Base::XMLReader &reader) { // this is temporary code for backwards compat (within v0.17). can probably be deleted once there are no development // fcstd files with old property types in use. reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ;i<Cnt ;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* schemaProp = getPropertyByName(PropName); try { if(schemaProp){ if (strcmp(schemaProp->getTypeId().getName(), TypeName) == 0){ //if the property type in obj == type in schema schemaProp->Restore(reader); //nothing special to do } else if (strcmp(PropName, "Source") == 0) { App::PropertyLinkGlobal glink; App::PropertyLink link; if (strcmp(glink.getTypeId().getName(),TypeName) == 0) { //property in file is plg glink.setContainer(this); glink.Restore(reader); if (glink.getValue() != nullptr) { static_cast<App::PropertyLink*>(schemaProp)->setScope(App::LinkScope::Global); static_cast<App::PropertyLink*>(schemaProp)->setValue(glink.getValue()); } } else if (strcmp(link.getTypeId().getName(),TypeName) == 0) { //property in file is pl link.setContainer(this); link.Restore(reader); if (link.getValue() != nullptr) { static_cast<App::PropertyLink*>(schemaProp)->setScope(App::LinkScope::Global); static_cast<App::PropertyLink*>(schemaProp)->setValue(link.getValue()); } } else { // has Source prop isn't PropertyLink or PropertyLinkGlobal! Base::Console().Log("DrawViewArch::Restore - old Document Source is weird: %s\n", TypeName); // no idea } } else { Base::Console().Log("DrawViewArch::Restore - old Document has unknown Property\n"); } } } catch (const Base::XMLParseException&) { throw; // re-throw } 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::Restore: Unknown C++ exception thrown\n"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void PropertyContainer::Restore(Base::XMLReader &reader) { reader.clearPartialRestoreProperty(); reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); 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()); // 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 // type and the behaviour would be undefined. try { // name and type match if (prop && strcmp(prop->getTypeId().getName(), TypeName.c_str()) == 0) { prop->Restore(reader); } // name matches but not the type else if (prop) { handleChangedPropertyType(reader, TypeName.c_str(), prop); } // name doesn't match, the sub-class then has to know // if the property has been renamed or removed else { handleChangedPropertyName(reader, TypeName.c_str(), PropName.c_str()); } if (reader.testStatus(Base::XMLReader::ReaderStatus::PartialRestoreInProperty)) { Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str()); reader.clearPartialRestoreProperty(); } } catch (const Base::XMLParseException&) { throw; // re-throw } catch (const Base::RestoreError &) { reader.setPartialRestore(true); reader.clearPartialRestoreProperty(); Base::Console().Error("Property %s of type %s was subject to a partial restore.\n",PropName.c_str(),TypeName.c_str()); } 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::Restore: Unknown C++ exception thrown\n"); } #endif reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
void DynamicProperty::Restore(Base::XMLReader &reader) { //first all extensions must be initialised so that they can handle their properties if(this->pc->isDerivedFrom(App::ExtensionContainer::getClassTypeId())) static_cast<App::ExtensionContainer*>(this->pc)->restoreExtensions(reader); reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); for (int i=0 ; i<Cnt ; i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); Property* prop = getPropertyByName(PropName); try { if (!prop) { short attribute = 0; bool readonly = false, hidden = false; const char *group=0, *doc=0, *attr=0, *ro=0, *hide=0; if (reader.hasAttribute("group")) group = reader.getAttribute("group"); if (reader.hasAttribute("doc")) doc = reader.getAttribute("doc"); if (reader.hasAttribute("attr")) { attr = reader.getAttribute("attr"); if (attr) attribute = attr[0]-48; } if (reader.hasAttribute("ro")) { ro = reader.getAttribute("ro"); if (ro) readonly = (ro[0]-48) != 0; } if (reader.hasAttribute("hide")) { hide = reader.getAttribute("hide"); if (hide) hidden = (hide[0]-48) != 0; } prop = addDynamicProperty(TypeName, PropName, group, doc, attribute, readonly, hidden); } } catch(const Base::Exception& e) { // only handle this exception type Base::Console().Warning(e.what()); } //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 type and the behaviour would be //undefined. // Don't read transient properties if (!(getPropertyType(prop) & Prop_Transient)) { if (prop && strcmp(prop->getTypeId().getName(), TypeName) == 0) { try { prop->Restore(reader); } catch (const Base::XMLParseException&) { throw; // re-throw } catch (const Base::Exception &e) { Base::Console().Error("%s\n", e.what()); } catch (const std::exception &e) { Base::Console().Error("%s\n", e.what()); } #ifndef FC_DEBUG catch (...) { Base::Console().Error("DynamicProperty::Restore: Unknown C++ exception thrown"); } #endif } else if (prop) { Base::Console().Warning("%s: Overread data for property %s of type %s, expected type is %s\n", pc->getTypeId().getName(), prop->getName(), prop->getTypeId().getName(), TypeName); } else { Base::Console().Warning("%s: No property found with name %s and type %s\n", pc->getTypeId().getName(), PropName, TypeName); } } reader.readEndElement("Property"); } reader.readEndElement("Properties"); }
/** * This method was added for backward-compatibility. In former versions * of Box we had the properties x,y,z and l,h,w which have changed to * Location -- as replacement for x,y and z and Length, Height and Width. */ void Box::Restore(Base::XMLReader &reader) { reader.readElement("Properties"); int Cnt = reader.getAttributeAsInteger("Count"); bool location_xyz = false; bool location_axis = false; bool distance_lhw = false; Base::Placement plm; App::PropertyDistance x,y,z; App::PropertyDistance l,w,h; App::PropertyVector Axis, Location; Axis.setValue(0.0f,0.0f,1.0f); for (int i=0 ;i<Cnt;i++) { reader.readElement("Property"); const char* PropName = reader.getAttribute("name"); const char* TypeName = reader.getAttribute("type"); App::Property* prop = getPropertyByName(PropName); if (!prop) { // in case this comes from an old document we must use the new properties if (strcmp(PropName, "l") == 0) { distance_lhw = true; prop = &l; } else if (strcmp(PropName, "w") == 0) { distance_lhw = true; prop = &h; // by mistake w was considered as height } else if (strcmp(PropName, "h") == 0) { distance_lhw = true; prop = &w; // by mistake h was considered as width } else if (strcmp(PropName, "x") == 0) { location_xyz = true; prop = &x; } else if (strcmp(PropName, "y") == 0) { location_xyz = true; prop = &y; } else if (strcmp(PropName, "z") == 0) { location_xyz = true; prop = &z; } else if (strcmp(PropName, "Axis") == 0) { location_axis = true; prop = &Axis; } else if (strcmp(PropName, "Location") == 0) { location_axis = true; prop = &Location; } } else if (strcmp(PropName, "Length") == 0 && strcmp(TypeName,"PropertyDistance") == 0) { distance_lhw = true; prop = &l; } else if (strcmp(PropName, "Height") == 0 && strcmp(TypeName,"PropertyDistance") == 0) { distance_lhw = true; prop = &h; } else if (strcmp(PropName, "Width") == 0 && strcmp(TypeName,"PropertyDistance") == 0) { distance_lhw = true; prop = &w; } // 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 type and the behaviour // would be undefined. std::string tn = TypeName; if (strcmp(TypeName,"PropertyDistance") == 0) // missing prefix App:: tn = std::string("App::") + tn; if (prop && strcmp(prop->getTypeId().getName(), tn.c_str()) == 0) prop->Restore(reader); reader.readEndElement("Property"); } if (distance_lhw) { this->Length.setValue(l.getValue()); this->Height.setValue(h.getValue()); this->Width.setValue(w.getValue()); } // for 0.7 releases or earlier if (location_xyz) { plm.setPosition(Base::Vector3d(x.getValue(),y.getValue(),z.getValue())); this->Placement.setValue(this->Placement.getValue() * plm); this->Shape.setStatus(App::Property::User1, true); // override the shape's location later on } // for 0.8 releases else if (location_axis) { Base::Vector3d d = Axis.getValue(); Base::Vector3d p = Location.getValue(); Base::Rotation rot(Base::Vector3d(0.0,0.0,1.0), Base::Vector3d(d.x,d.y,d.z)); plm.setRotation(rot); plm.setPosition(Base::Vector3d(p.x,p.y,p.z)); this->Placement.setValue(this->Placement.getValue() * plm); this->Shape.setStatus(App::Property::User1, true); // override the shape's location later on } reader.readEndElement("Properties"); }