diff --git a/src/App/Link.cpp b/src/App/Link.cpp index f5b152e7e8..dc1b3a396a 100644 --- a/src/App/Link.cpp +++ b/src/App/Link.cpp @@ -44,7 +44,7 @@ using namespace Base; EXTENSION_PROPERTY_SOURCE(App::LinkBaseExtension, App::DocumentObjectExtension) LinkBaseExtension::LinkBaseExtension(void) - :enableLabelCache(false),myOwner(0) + :myOwner(0),enableLabelCache(false),hasOldSubElement(false) { initExtensionType(LinkBaseExtension::getExtensionClassTypeId()); EXTENSION_ADD_PROPERTY_TYPE(_LinkTouched, (false), " Link", @@ -1076,12 +1076,57 @@ void LinkBaseExtension::syncElementList() { void LinkBaseExtension::onExtendedDocumentRestored() { inherited::onExtendedDocumentRestored(); - auto parent = getContainer(); myHiddenElements.clear(); - if(parent) { - update(parent,getVisibilityListProperty()); - update(parent,getLinkedObjectProperty()); - update(parent,getElementListProperty()); + auto parent = getContainer(); + if(!parent) + return; + if(hasOldSubElement) { + hasOldSubElement = false; + // SubElements was stored as a PropertyStringList. It is now migrated to be + // stored inside PropertyXLink. + auto xlink = freecad_dynamic_cast(getLinkedObjectProperty()); + if(!xlink) + FC_ERR("Failed to restore SubElements for " << parent->getFullName()); + else if(!xlink->getValue()) + FC_ERR("Discard SubElements of " << parent->getFullName() << " due to null link"); + else if(xlink->getSubValues().size() > 1) + FC_ERR("Failed to restore SubElements for " << parent->getFullName() + << " due to conflict subnames"); + else if(xlink->getSubValues().empty()) { + auto subs = xlink->getSubValues(); + xlink->setSubValues(std::move(subs)); + } else { + std::set subset(mySubElements.begin(),mySubElements.end()); + auto sub = xlink->getSubValues().front(); + auto element = Data::ComplexGeoData::findElementName(sub.c_str()); + if(element && element[0]) { + subset.insert(element); + sub.resize(element - sub.c_str()); + } + std::vector subs; + for(auto &s : subset) + subs.push_back(sub + s); + xlink->setSubValues(std::move(subs)); + } + } + update(parent,getVisibilityListProperty()); + update(parent,getLinkedObjectProperty()); + update(parent,getElementListProperty()); +} + +void LinkBaseExtension::_handleChangedPropertyName( + Base::XMLReader &reader, const char * TypeName, const char *PropName) +{ + if(strcmp(PropName,"SubElements")==0 + && strcmp(TypeName,PropertyStringList::getClassTypeId().getName())==0) + { + PropertyStringList prop; + prop.setContainer(getContainer()); + prop.Restore(reader); + if(prop.getSize()) { + mySubElements = prop.getValues(); + hasOldSubElement = true; + } } } diff --git a/src/App/Link.h b/src/App/Link.h index 5b85626451..95c5bed0e7 100644 --- a/src/App/Link.h +++ b/src/App/Link.h @@ -204,7 +204,7 @@ public: return static_cast(prop);\ }\ - // defines get##Name() and get##Name##Property() accessor + // defines get##Name##Property() and get##Name##Value() accessor BOOST_PP_SEQ_FOR_EACH(LINK_PROP_GET,_,LINK_PARAMS) PropertyLinkList *_getElementListProperty() const; @@ -284,6 +284,8 @@ public: void cacheChildLabel(int enable=-1) const; protected: + void _handleChangedPropertyName(Base::XMLReader &reader, + const char * TypeName, const char *PropName); void parseSubName() const; void update(App::DocumentObject *parent, const Property *prop); void syncElementList(); @@ -302,10 +304,12 @@ protected: std::unordered_map plainGroupConns; + long myOwner; + mutable std::unordered_map myLabelCache; // for label based subname lookup mutable bool enableLabelCache; - long myOwner; + bool hasOldSubElement; }; /////////////////////////////////////////////////////////////////////////// @@ -452,6 +456,12 @@ public: inherited::onDocumentRestored(); } + void handleChangedPropertyName(Base::XMLReader &reader, + const char * TypeName, const char *PropName) override + { + _handleChangedPropertyName(reader,TypeName,PropName); + } + bool canLinkProperties() const override; }; @@ -485,6 +495,12 @@ public: } bool canDelete() const; + + void handleChangedPropertyName(Base::XMLReader &reader, + const char * TypeName, const char *PropName) override + { + _handleChangedPropertyName(reader,TypeName,PropName); + } }; typedef App::FeaturePythonT LinkElementPython;