From 3109301e5278582dce929dbcc9eb4d217eb919a4 Mon Sep 17 00:00:00 2001 From: CalligaroV Date: Thu, 11 Apr 2024 18:09:40 +0200 Subject: [PATCH] App/Toponaming: import SubObjectT dependencies for SubShapeBinder * Formatted and refactored code imported for the DocumentObject class * Formatted and refactored code imported for the SubObjectT class Signed-off-by: CalligaroV --- src/App/DocumentObject.cpp | 107 ++++++++++++++++++----------- src/App/DocumentObject.h | 4 +- src/App/DocumentObserver.cpp | 69 ++++++++++++------- src/App/DocumentObserver.h | 9 +-- tests/src/App/DocumentObserver.cpp | 22 +++--- 5 files changed, 127 insertions(+), 84 deletions(-) diff --git a/src/App/DocumentObject.cpp b/src/App/DocumentObject.cpp index cd67807a6b..a427ac2ed0 100644 --- a/src/App/DocumentObject.cpp +++ b/src/App/DocumentObject.cpp @@ -888,70 +888,93 @@ DocumentObject *DocumentObject::getSubObject(const char *subname, return ret; } +namespace +{ std::vector -DocumentObject::getSubObjectList(const char *subname, - std::vector *sublist, - bool flatten) const +getSubObjectListFlatten(const std::vector& resNotFlatten, + std::vector* const subsizes, + const App::DocumentObject* sobj, + App::DocumentObject** container, + bool& lastChild) +{ + auto res {resNotFlatten}; + auto linked = sobj->getLinkedObject(); + if (container) { + auto grp = App::GeoFeatureGroupExtension::getGroupOfObject(linked); + if (grp != *container) { + container = nullptr; + } + else { + if (lastChild && !res.empty()) { + res.pop_back(); + if (subsizes) { + subsizes->pop_back(); + } + } + lastChild = true; + } + } + if (linked->getExtensionByType(true)) { + *container = linked; + lastChild = false; + } + else if (linked != sobj || sobj->hasChildElement()) { + // Check for Link or LinkGroup + container = nullptr; + } + else if (auto ext = sobj->getExtensionByType(true)) { + // check for Link array + if (ext->getElementCountValue() != 0) { + container = nullptr; + } + } + return res; +} +} // namespace + +std::vector DocumentObject::getSubObjectList(const char* subname, + std::vector* const subsizes, + bool flatten) const { std::vector res; res.push_back(const_cast(this)); - if (sublist) sublist->push_back(0); - if(!subname || !subname[0]) + if (subsizes) { + subsizes->push_back(0); + } + if (!subname || (subname[0] == 0)) { return res; + } auto element = Data::findElementName(subname); - std::string sub(subname,element-subname); - App::DocumentObject *container = nullptr; + std::string sub(subname, element - subname); + App::DocumentObject* container = nullptr; bool lastChild = false; if (flatten) { auto linked = getLinkedObject(); - if (linked->getExtensionByType(true)) + if (linked->getExtensionByType(true)) { container = const_cast(this); + } else if (auto grp = App::GeoFeatureGroupExtension::getGroupOfObject(linked)) { container = grp; lastChild = true; } } - for(auto pos=sub.find('.');pos!=std::string::npos;pos=sub.find('.',pos+1)) { - char c = sub[pos+1]; - sub[pos+1] = 0; + for (auto pos = sub.find('.'); pos != std::string::npos; pos = sub.find('.', pos + 1)) { + char subTail = sub[pos + 1]; + sub[pos + 1] = 0; auto sobj = getSubObject(sub.c_str()); - if(!sobj || !sobj->isAttachedToDocument()) + if (!sobj || !sobj->isAttachedToDocument()) { continue; + } if (flatten) { - auto linked = sobj->getLinkedObject(); - if (container) { - auto grp = App::GeoFeatureGroupExtension::getGroupOfObject(linked); - if (grp != container) - container = nullptr; - else { - if (lastChild && res.size()) { - res.pop_back(); - if (sublist) - sublist->pop_back(); - } - lastChild = true; - } - } - if (linked->getExtensionByType(true)) { - container = linked; - lastChild = false; - } - else if (linked != sobj || sobj->hasChildElement()) { - // Check for Link or LinkGroup - container = nullptr; - } - else if (auto ext = sobj->getExtensionByType(true)) { - // check for Link array - if (ext->getElementCountValue()) - container = nullptr; - } + res = getSubObjectListFlatten(res, subsizes, sobj, &container, lastChild); } res.push_back(sobj); - if (sublist) - sublist->push_back(pos+1); - sub[pos+1] = c; + if (subsizes) { + subsizes->push_back((int)pos + 1); + } + sub[pos + 1] = subTail; } return res; } diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index b9dbe5307c..03e8182722 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -386,8 +386,8 @@ public: * * @return Return a list of object along the path. */ - std::vector getSubObjectList(const char *subname, - std::vector *subsizes = nullptr, + std::vector getSubObjectList(const char* subname, + std::vector* subsizes = nullptr, bool flatten = false) const; /// reason of calling getSubObjects() diff --git a/src/App/DocumentObserver.cpp b/src/App/DocumentObserver.cpp index f81ff01425..461c80fa4b 100644 --- a/src/App/DocumentObserver.cpp +++ b/src/App/DocumentObserver.cpp @@ -342,6 +342,22 @@ bool SubObjectT::operator==(const SubObjectT &other) const { && subname == other.subname; } +namespace +{ +bool normalizeConvertIndex(const std::vector& objs, const unsigned int idx) +{ + if (auto ext = objs[idx - 1]->getExtensionByType(true)) { + if ((ext->getElementCountValue() != 0) && !ext->getShowElementValue()) { + // if the parent is a collapsed link array element, then we + // have to keep the index no matter what, because there is + // no sub-object corresponding to an array element. + return true; + } + } + return false; +} +} // namespace + bool SubObjectT::normalize(NormalizeOptions options) { bool noElement = options.testFlag(NormalizeOption::NoElement); @@ -352,17 +368,19 @@ bool SubObjectT::normalize(NormalizeOptions options) std::ostringstream ss; std::vector subs; auto obj = getObject(); - if(!obj) + if (!obj) { return false; + } auto objs = obj->getSubObjectList(subname.c_str(), &subs, flatten); - if (objs.empty()) + if (objs.empty()) { return false; - for (unsigned i=1; igetExtensionByType(true)) { - if (ext->getElementCountValue() && !ext->getShowElementValue()) { - // if the parent is a collapsed link array element, then we - // have to keep the index no matter what, because there is - // no sub-object corresponding to an array element. - _keepSub = true; - } - } } - if (_keepSub) + else if (!convertIndex) { + _keepSub = true; + } + else { + _keepSub = normalizeConvertIndex(objs, i); + } + if (_keepSub) { ss << std::string(sub, end); - else + } + else { ss << objs[i]->getNameInDocument() << "."; + } } if (objs.size() > 1 && objs.front()->getSubObject(ss.str().c_str()) != objs.back()) { // something went wrong return false; } - if (!noElement) + if (!noElement) { ss << getOldElementName(); + } std::string sub = ss.str(); if (objs.front() != obj || subname != sub) { *this = objs.front(); @@ -431,13 +446,15 @@ const char *SubObjectT::getElementName() const { return Data::findElementName(subname.c_str()); } -bool SubObjectT::hasSubObject() const { +bool SubObjectT::hasSubObject() const +{ return Data::findElementName(subname.c_str()) != subname.c_str(); } -bool SubObjectT::hasSubElement() const { +bool SubObjectT::hasSubElement() const +{ auto element = getElementName(); - return element && element[0]; + return (element != nullptr) && (element[0] != 0); } std::string SubObjectT::getNewElementName() const { diff --git a/src/App/DocumentObserver.h b/src/App/DocumentObserver.h index f457b61696..33b6ccbb17 100644 --- a/src/App/DocumentObserver.h +++ b/src/App/DocumentObserver.h @@ -252,22 +252,23 @@ public: std::string getSubObjectPython(bool force=true) const; /// Options used by normalize() - enum class NormalizeOption { + enum class NormalizeOption : uint8_t + { /// Do not include sub-element reference in the output path - NoElement = 0x01, + NoElement = 0x01, /** Do not flatten the output path. If not specified, the output path * will be flatten to exclude intermediate objects that belong to the * same geo feature group before resolving. For example, * Part.Fusion.Box. -> Part.Box. */ - NoFlatten = 0x02, + NoFlatten = 0x02, /** Do not change the sub-object component inside the path. Each * component of the subname object path can be either the object * internal name, the label of the object if starts with '$', or an * integer index. If this option is not specified, each component will * be converted to object internal name, except for integer index. */ - KeepSubName = 0x04, + KeepSubName = 0x04, /** Convert integer index in the path to sub-object internal name */ ConvertIndex = 0x08, }; diff --git a/tests/src/App/DocumentObserver.cpp b/tests/src/App/DocumentObserver.cpp index d3841abeae..6fdb18b970 100644 --- a/tests/src/App/DocumentObserver.cpp +++ b/tests/src/App/DocumentObserver.cpp @@ -52,8 +52,9 @@ TEST_F(DocumentObserverTest, hasSubObject) // A subname that doesn't contain a sub object name auto subObjTNameWithoutSubObj {"Line"}; // A subname that contains a sub object name - auto subObjTNameWithSubObj { - std::string(std::string(subObjTNameWithoutSubObj) + ".Edge1").c_str()}; + auto subObjTNameWithSubObj {std::string()}; + subObjTNameWithSubObj += subObjTNameWithoutSubObj; + subObjTNameWithSubObj += ".Edge1"; // A variable used to store the result of the call to the method SubObjectT::hasSubObject() by // the object subObjTWithoutSubObj @@ -64,7 +65,7 @@ TEST_F(DocumentObserverTest, hasSubObject) // Setting the subnames of the App::SubObjectT() objects defined previously subObjTWithoutSubObj.setSubName(subObjTNameWithoutSubObj); - subObjTWithSubObj.setSubName(subObjTNameWithSubObj); + subObjTWithSubObj.setSubName(subObjTNameWithSubObj.c_str()); // Act @@ -94,9 +95,10 @@ TEST_F(DocumentObserverTest, hasSubElement) // A subname that doesn't contain a sub element name auto subObjTNameWithoutSubEl {"Sketch."}; // A subname that contains a sub element name - auto subObjTNameWithSubEl { - std::string(std::string(subObjTNameWithoutSubEl) + ELEMENT_MAP_PREFIX + "e1.ExternalEdge1") - .c_str()}; + auto subObjTNameWithSubEl {std::string()}; + subObjTNameWithSubEl += subObjTNameWithoutSubEl; + subObjTNameWithSubEl += ELEMENT_MAP_PREFIX; + subObjTNameWithSubEl += "e1.ExternalEdge1"; // A variable used to store the result of the call to the method SubObjectT::hasSubElement() by // the object subObjTWithoutSubEl @@ -107,7 +109,7 @@ TEST_F(DocumentObserverTest, hasSubElement) // Setting the subnames of the App::SubObjectT() objects defined previously subObjTWithoutSubEl.setSubName(subObjTNameWithoutSubEl); - subObjTWithSubEl.setSubName(subObjTNameWithSubEl); + subObjTWithSubEl.setSubName(subObjTNameWithSubEl.c_str()); // Act @@ -208,7 +210,7 @@ TEST_F(DocumentObserverTest, normalize) auto subObjTNoFlatten {SubObjectT(lGrp, subName.c_str())}; // An App::SubObjectT object used to test SubObjectT::normalize() with the option argument set // to SubObjectT::NormalizeOption::KeepSubName - auto subObjTKeepSubName {SubObjectT(lGrp, subName.replace(0, 9, "0").c_str())}; + auto subObjTKeepSubName {SubObjectT(lGrp, subName.replace(0, strlen(partName), "0").c_str())}; // An App::SubObjectT object used to test SubObjectT::normalize() with the option argument set // to SubObjectT::NormalizeOption::ConvertIndex auto subObjTConvertIndex {SubObjectT(lGrp, subName.c_str())}; @@ -354,7 +356,7 @@ TEST_F(DocumentObserverTest, normalized) auto subObjTNoFlatten {SubObjectT(lGrp, subName.c_str())}; // An App::SubObjectT object used to test SubObjectT::normalized() with the option argument set // to SubObjectT::NormalizeOption::KeepSubName - auto subObjTKeepSubName {SubObjectT(lGrp, subName.replace(0, 9, "0").c_str())}; + auto subObjTKeepSubName {SubObjectT(lGrp, subName.replace(0, strlen(partName), "0").c_str())}; // An App::SubObjectT object used to test SubObjectT::normalized() with the option argument set // to SubObjectT::NormalizeOption::ConvertIndex auto subObjTConvertIndex {SubObjectT(lGrp, subName.c_str())}; @@ -421,4 +423,4 @@ TEST_F(DocumentObserverTest, normalized) EXPECT_EQ(subObjTConvertIndexNormalized.getSubName().find("0"), std::string::npos); EXPECT_EQ(subObjTConvertIndexNormalized.getSubName().find(fuseName), std::string::npos); EXPECT_NE(subObjTConvertIndexNormalized.getSubName().find(partName), std::string::npos); -} \ No newline at end of file +}