From 4f6f600a1f966695d2072d7b3ccd6a8818e2b830 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 21 Oct 2022 02:24:42 +0200 Subject: [PATCH] Gui: [skip ci] refactor PropertyModel::buildUp --- src/Gui/propertyeditor/PropertyModel.cpp | 98 +++++++++++++++++------- src/Gui/propertyeditor/PropertyModel.h | 6 ++ 2 files changed, 76 insertions(+), 28 deletions(-) diff --git a/src/Gui/propertyeditor/PropertyModel.cpp b/src/Gui/propertyeditor/PropertyModel.cpp index 0ff4e78651..933253a88d 100644 --- a/src/Gui/propertyeditor/PropertyModel.cpp +++ b/src/Gui/propertyeditor/PropertyModel.cpp @@ -282,42 +282,67 @@ void PropertyModel::buildUp(const PropertyModel::PropertyList& props) // If props empty, then simply reset all property items, but keep the group // items. if (props.empty()) { - beginResetModel(); - for(auto &v : groupItems) { - auto &groupInfo = v.second; - groupInfo.groupItem->reset(); - groupInfo.children.clear(); - } - itemMap.clear(); - endResetModel(); + resetGroups(); return; } // First step, init group info - for (auto &v : groupItems) { - auto &groupInfo = v.second; - groupInfo.children.clear(); - } + initGroups(); // Second step, either find existing items or create new items for the given // properties. There is no signaling of model change at this stage. The // change information is kept pending in GroupInfo::children + findOrCreateChildren(props); + + // Third step, signal item insertion and movement. + insertOrMoveChildren(); + + + // Final step, signal item removal. This is separated from the above because + // of the possibility of moving items between groups. + removeChildren(); +} + +void PropertyModel::resetGroups() +{ + beginResetModel(); + for(auto &v : groupItems) { + auto &groupInfo = v.second; + groupInfo.groupItem->reset(); + groupInfo.children.clear(); + } + itemMap.clear(); + endResetModel(); +} + +void PropertyModel::initGroups() +{ + for (auto &v : groupItems) { + auto &groupInfo = v.second; + groupInfo.children.clear(); + } +} + +void PropertyModel::findOrCreateChildren(const PropertyModel::PropertyList& props) +{ for (const auto & jt : props) { App::Property* prop = jt.second.front(); PropertyItem *item = nullptr; for (auto prop : jt.second) { auto it = itemMap.find(prop); - if (it == itemMap.end() || !it->second) + if (it == itemMap.end() || !it->second) { continue; + } item = it->second; break; } if (!item) { item = createPropertyItem(prop); - if (!item) + if (!item) { continue; + } } GroupInfo &groupInfo = getGroupInfo(prop); @@ -327,18 +352,23 @@ void PropertyModel::buildUp(const PropertyModel::PropertyList& props) setPropertyItemName(item, prop->getName(), groupInfo.groupItem->propertyName()); if (jt.second != item->getPropertyData()) { - for (auto prop : item->getPropertyData()) + for (auto prop : item->getPropertyData()) { itemMap.erase(prop); - for (auto prop : jt.second) + } + for (auto prop : jt.second) { itemMap[prop] = item; + } // TODO: is it necessary to make sure the item has no pending commit? item->setPropertyData(jt.second); } - else + else { item->updateData(); + } } +} - // Third step, signal item insertion and movement. +void PropertyModel::insertOrMoveChildren() +{ for (auto &v : groupItems) { auto &groupInfo = v.second; int beginChange = -1; @@ -375,10 +405,12 @@ void PropertyModel::buildUp(const PropertyModel::PropertyList& props) if (!item->parent()) { flushChanges(); item->setParent(groupInfo.groupItem); - if (beginInsert < 0) + if (beginInsert < 0) { beginInsert = row; + } endInsert = row; - } else { + } + else { flushInserts(); int oldRow = item->row(); // Dynamic property can rename group, so must check @@ -388,12 +420,14 @@ void PropertyModel::buildUp(const PropertyModel::PropertyList& props) if (beginChange < 0) beginChange = row; endChange = row; - } else { + } + else { flushChanges(); - beginMoveRows(createIndex(groupItem->row(),0,groupItem), - oldRow, oldRow, midx, row); - if (groupItem == groupInfo.groupItem) + beginMoveRows(createIndex(groupItem->row(), 0, groupItem), + oldRow, oldRow, midx, row); + if (groupItem == groupInfo.groupItem) { groupInfo.groupItem->moveChild(oldRow, row); + } else { groupItem->takeChild(oldRow); item->setParent(groupInfo.groupItem); @@ -403,16 +437,18 @@ void PropertyModel::buildUp(const PropertyModel::PropertyList& props) } } } + flushChanges(); flushInserts(); } +} - // Final step, signal item removal. This is separated from the above because - // of the possibility of moving items between groups. +void PropertyModel::removeChildren() +{ for (auto &v : groupItems) { auto &groupInfo = v.second; - int last = groupInfo.groupItem->childCount(); - int first = static_cast(groupInfo.children.size()); + int first, last; + getRange(groupInfo, first, last); if (last > first) { QModelIndex midx = this->index(groupInfo.groupItem->_row, 0, QModelIndex()); // This can trigger a recursive call of PropertyView::onTimer() @@ -426,6 +462,12 @@ void PropertyModel::buildUp(const PropertyModel::PropertyList& props) } } +void PropertyModel::getRange(const PropertyModel::GroupInfo& groupInfo, int& first, int& last) const +{ + first = static_cast(groupInfo.children.size()); + last = groupInfo.groupItem->childCount(); +} + void PropertyModel::updateProperty(const App::Property& prop) { auto it = itemMap.find(const_cast(&prop)); diff --git a/src/Gui/propertyeditor/PropertyModel.h b/src/Gui/propertyeditor/PropertyModel.h index f7f9a8608b..34c4620312 100644 --- a/src/Gui/propertyeditor/PropertyModel.h +++ b/src/Gui/propertyeditor/PropertyModel.h @@ -70,13 +70,19 @@ public: QModelIndex propertyIndexFromPath(const QStringList&) const; private: + void resetGroups(); + void initGroups(); void updateChildren(PropertyItem* item, int column, const QModelIndex& parent); + void findOrCreateChildren(const PropertyList& props); + void insertOrMoveChildren(); + void removeChildren(); struct GroupInfo { PropertySeparatorItem *groupItem = nullptr; std::vector children; }; GroupInfo &getGroupInfo(App::Property *); + void getRange(const GroupInfo&, int& first, int& last) const; private: PropertyItem *rootItem;