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 <vincenzo.calligaro@gmail.com>
This commit is contained in:
CalligaroV
2024-04-11 18:09:40 +02:00
committed by Chris Hennes
parent ceb5478a37
commit 243e20248d
5 changed files with 127 additions and 84 deletions

View File

@@ -888,70 +888,93 @@ DocumentObject *DocumentObject::getSubObject(const char *subname,
return ret;
}
namespace
{
std::vector<DocumentObject*>
DocumentObject::getSubObjectList(const char *subname,
std::vector<int> *sublist,
bool flatten) const
getSubObjectListFlatten(const std::vector<App::DocumentObject*>& resNotFlatten,
std::vector<int>* 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<App::GeoFeatureGroupExtension>(true)) {
*container = linked;
lastChild = false;
}
else if (linked != sobj || sobj->hasChildElement()) {
// Check for Link or LinkGroup
container = nullptr;
}
else if (auto ext = sobj->getExtensionByType<LinkBaseExtension>(true)) {
// check for Link array
if (ext->getElementCountValue() != 0) {
container = nullptr;
}
}
return res;
}
} // namespace
std::vector<DocumentObject*> DocumentObject::getSubObjectList(const char* subname,
std::vector<int>* const subsizes,
bool flatten) const
{
std::vector<DocumentObject*> res;
res.push_back(const_cast<DocumentObject*>(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<App::GeoFeatureGroupExtension>(true))
if (linked->getExtensionByType<App::GeoFeatureGroupExtension>(true)) {
container = const_cast<DocumentObject*>(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<App::GeoFeatureGroupExtension>(true)) {
container = linked;
lastChild = false;
}
else if (linked != sobj || sobj->hasChildElement()) {
// Check for Link or LinkGroup
container = nullptr;
}
else if (auto ext = sobj->getExtensionByType<LinkBaseExtension>(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;
}

View File

@@ -386,8 +386,8 @@ public:
*
* @return Return a list of object along the path.
*/
std::vector<DocumentObject*> getSubObjectList(const char *subname,
std::vector<int> *subsizes = nullptr,
std::vector<DocumentObject*> getSubObjectList(const char* subname,
std::vector<int>* subsizes = nullptr,
bool flatten = false) const;
/// reason of calling getSubObjects()

View File

@@ -342,6 +342,22 @@ bool SubObjectT::operator==(const SubObjectT &other) const {
&& subname == other.subname;
}
namespace
{
bool normalizeConvertIndex(const std::vector<App::DocumentObject*>& objs, const unsigned int idx)
{
if (auto ext = objs[idx - 1]->getExtensionByType<App::LinkBaseExtension>(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<int> 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; i<objs.size(); ++i) {
}
for (unsigned i = 1; i < objs.size(); ++i) {
// Keep digit only subname, as it maybe an index to an array, which does
// not expand its elements as objects.
const char *end = subname.c_str() + subs[i];
const char *sub = end - 2;
for(;;--sub) {
const char* end = subname.c_str() + subs[i];
const char* sub = end - 2;
for (;; --sub) {
if (sub < subname.c_str()) {
sub = subname.c_str();
break;
@@ -372,33 +390,30 @@ bool SubObjectT::normalize(NormalizeOptions options)
break;
}
}
bool _keepSub;
if (!std::isdigit(sub[0]))
bool _keepSub {};
if (std::isdigit(sub[0]) == 0) {
_keepSub = keepSub;
else if (!convertIndex)
_keepSub = true;
else {
_keepSub = false;
if (auto ext = objs[i-1]->getExtensionByType<LinkBaseExtension>(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 {

View File

@@ -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,
};

View File

@@ -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);
}
}