From def8ca8ba1fce10a0514215e333598f831ab6e45 Mon Sep 17 00:00:00 2001 From: hjk <hjk@theqtcompany.com> Date: Mon, 25 Jul 2016 16:48:15 +0200 Subject: [PATCH] TreeModel: Move some base TreeItem code out-of-line Avoid code explosion. Change-Id: I7d239a4560e90b68cc4991341adf940a98776254 Reviewed-by: Christian Stenger <christian.stenger@qt.io> --- src/libs/utils/treemodel.cpp | 55 ++++++++++++ src/libs/utils/treemodel.h | 89 +++++-------------- src/plugins/projectexplorer/projectwindow.cpp | 2 +- .../projectexplorer/toolchainoptionspage.cpp | 4 +- tests/auto/debugger/tst_dumpers.cpp | 6 +- tests/auto/utils/treemodel/tst_treemodel.cpp | 2 +- 6 files changed, 85 insertions(+), 73 deletions(-) diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp index 48dd4ac1b06..3acc9dbcdfc 100644 --- a/src/libs/utils/treemodel.cpp +++ b/src/libs/utils/treemodel.cpp @@ -777,6 +777,61 @@ QAbstractItemModel *TreeItem::model() const return m_model; } +void TreeItem::forAllChildren(const std::function<void (TreeItem *)> &pred) const +{ + foreach (TreeItem *item, m_children) { + pred(item); + item->forAllChildren(pred); + } +} + +void TreeItem::forSelectedChildren(const std::function<bool (TreeItem *)> &pred) const +{ + foreach (TreeItem *item, m_children) { + if (pred(item)) + item->forSelectedChildren(pred); + } +} + +void TreeItem::forChildrenAtLevel(int level, const std::function<void(TreeItem *)> &pred) const +{ + QTC_ASSERT(level > 0, return); + if (level == 1) { + foreach (TreeItem *item, m_children) + pred(item); + } else { + foreach (TreeItem *item, m_children) + item->forChildrenAtLevel(level - 1, pred); + } +} + +TreeItem *TreeItem::findChildAtLevel(int level, const std::function<bool(TreeItem *)> &pred) const +{ + QTC_ASSERT(level > 0, return 0); + if (level == 1) { + foreach (TreeItem *item, m_children) + if (pred(item)) + return item; + } else { + foreach (TreeItem *item, m_children) { + if (auto found = item->findChildAtLevel(level - 1, pred)) + return found; + } + } + return 0; +} + +TreeItem *TreeItem::findAnyChild(const std::function<bool(TreeItem *)> &pred) const +{ + foreach (TreeItem *item, m_children) { + if (pred(item)) + return item; + if (TreeItem *found = item->findAnyChild(pred)) + return found; + } + return 0; +} + void TreeItem::clear() { while (m_children.size()) { diff --git a/src/libs/utils/treemodel.h b/src/libs/utils/treemodel.h index 0fdff46f921..080263a19fa 100644 --- a/src/libs/utils/treemodel.h +++ b/src/libs/utils/treemodel.h @@ -70,62 +70,13 @@ public: QModelIndex index() const; QAbstractItemModel *model() const; - template <class T, class Predicate> - void forSelectedChildren(const Predicate &pred) const { - foreach (TreeItem *item, m_children) { - if (pred(static_cast<T>(item))) - item->forSelectedChildren<T, Predicate>(pred); - } - } - - template <class T, typename Predicate> - void forAllChildren(const Predicate &pred) const { - foreach (TreeItem *item, m_children) { - pred(static_cast<T>(item)); - item->forAllChildren<T, Predicate>(pred); - } - } + void forSelectedChildren(const std::function<bool(TreeItem *)> &pred) const; + void forAllChildren(const std::function<void(TreeItem *)> &pred) const; + TreeItem *findAnyChild(const std::function<bool(TreeItem *)> &pred) const; // Levels are 1-based: Child at Level 1 is an immediate child. - - template <class T, typename Predicate> - void forChildrenAtLevel(int level, Predicate pred) const - { - if (level == 1) { - foreach (TreeItem *item, m_children) - pred(static_cast<T>(item)); - } else { - foreach (TreeItem *item, m_children) - item->forChildrenAtLevel<T, Predicate>(level - 1, pred); - } - } - - template <class T, typename Predicate> - T findChildAtLevel(int level, Predicate pred) const - { - if (level == 1) { - foreach (TreeItem *item, m_children) - if (pred(static_cast<T>(item))) - return static_cast<T>(item); - } else { - foreach (TreeItem *item, m_children) { - if (auto found = item->findChildAtLevel<T, Predicate>(level - 1, pred)) - return found; - } - } - return 0; - } - - template <class T, typename Predicate> - T findAnyChild(Predicate pred) const { - foreach (TreeItem *item, m_children) { - if (pred(static_cast<T>(item))) - return static_cast<T>(item); - if (T found = item->findAnyChild<T>(pred)) - return found; - } - return 0; - } + void forChildrenAtLevel(int level, const std::function<void(TreeItem *)> &pred) const; + TreeItem *findChildAtLevel(int level, const std::function<bool(TreeItem *)> &pred) const; private: TreeItem(const TreeItem &) = delete; @@ -156,17 +107,20 @@ public: template <typename Predicate> void forAllChildren(const Predicate &pred) const { - return TreeItem::forAllChildren<ChildType *, Predicate>(pred); + const auto pred0 = [pred](TreeItem *treeItem) { pred(static_cast<ChildType *>(treeItem)); }; + TreeItem::forAllChildren(pred0); } template <typename Predicate> void forFirstLevelChildren(Predicate pred) const { - return TreeItem::forChildrenAtLevel<ChildType *, Predicate>(1, pred); + const auto pred0 = [pred](TreeItem *treeItem) { pred(static_cast<ChildType *>(treeItem)); }; + TreeItem::forChildrenAtLevel(1, pred0); } template <typename Predicate> ChildType *findFirstLevelChild(Predicate pred) const { - return TreeItem::findChildAtLevel<ChildType *, Predicate>(1, pred); + const auto pred0 = [pred](TreeItem *treeItem) { return pred(static_cast<ChildType *>(treeItem)); }; + return static_cast<ChildType *>(TreeItem::findChildAtLevel(1, pred0)); } ParentType *parent() const { @@ -257,7 +211,6 @@ template<int N> struct SelectType<N> using Type = TreeItem; }; - // BestItem<T0, T1, T2, ... > selects T0 if all types are equal and 'TreeItem' otherwise template<typename ...All> struct BestItemType; @@ -310,12 +263,16 @@ public: template <int Level, class Predicate> void forItemsAtLevel(const Predicate &pred) const { - m_root->forChildrenAtLevel<typename Internal::SelectType<Level, LevelItemTypes...>::Type *>(Level, pred); + using ItemType = typename Internal::SelectType<Level, LevelItemTypes...>::Type; + const auto pred0 = [pred](TreeItem *treeItem) { pred(static_cast<ItemType *>(treeItem)); }; + m_root->forChildrenAtLevel(Level, pred0); } template <int Level, class Predicate> typename Internal::SelectType<Level, LevelItemTypes...>::Type *findItemAtLevel(const Predicate &pred) const { - return m_root->findChildAtLevel<typename Internal::SelectType<Level, LevelItemTypes...>::Type *>(Level, pred); + using ItemType = typename Internal::SelectType<Level, LevelItemTypes...>::Type; + const auto pred0 = [pred](TreeItem *treeItem) { return pred(static_cast<ItemType *>(treeItem)); }; + return static_cast<ItemType *>(m_root->findChildAtLevel(Level, pred0)); } RootItem *rootItem() const { @@ -335,20 +292,20 @@ public: template <class Predicate> BestItem *findNonRooItem(const Predicate &pred) const { - TreeItem *root = this->rootItem(); - return root->findAnyChild<BestItem *>(pred); + const auto pred0 = [pred](TreeItem *treeItem) -> bool { return pred(static_cast<BestItem *>(treeItem)); }; + return static_cast<BestItem *>(m_root->findAnyChild(pred0)); } template <class Predicate> void forSelectedItems(const Predicate &pred) const { - TreeItem *root = this->rootItem(); - root->forSelectedChildren<BestItem *, Predicate>(pred); + const auto pred0 = [pred](TreeItem *treeItem) -> bool { return pred(static_cast<BestItem *>(treeItem)); }; + m_root->forSelectedChildren(pred0); } template <class Predicate> void forAllItems(const Predicate &pred) const { - TreeItem *root = this->rootItem(); - root->forAllChildren<BestItem *, Predicate>(pred); + const auto pred0 = [pred](TreeItem *treeItem) -> void { pred(static_cast<BestItem *>(treeItem)); }; + m_root->forAllChildren(pred0); } BestItem *itemForIndex(const QModelIndex &idx) const { diff --git a/src/plugins/projectexplorer/projectwindow.cpp b/src/plugins/projectexplorer/projectwindow.cpp index 32c95d3b28b..c9e0b5b2953 100644 --- a/src/plugins/projectexplorer/projectwindow.cpp +++ b/src/plugins/projectexplorer/projectwindow.cpp @@ -81,7 +81,7 @@ public: case Qt::DecorationRole: { QVariant icon; - forChildrenAtLevel<TreeItem *>(2, [this, &icon](TreeItem *item) { + forChildrenAtLevel(2, [this, &icon](TreeItem *item) { QVariant sicon = item->data(0, Qt::DecorationRole); if (sicon.isValid()) icon = sicon; diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 0ae5a7e4854..4482f4221af 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -293,8 +293,8 @@ void ToolChainOptionsWidget::removeToolChain(ToolChain *tc) } StaticTreeItem *parent = parentForToolChain(tc); - auto item = parent->findChildAtLevel<ToolChainTreeItem *>(1, [tc](ToolChainTreeItem *item) { - return item->toolChain == tc; + auto item = parent->findChildAtLevel(1, [tc](TreeItem *item) { + return static_cast<ToolChainTreeItem *>(item)->toolChain == tc; }); m_model.destroyItem(item); diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index cf47e228702..401f246f6a0 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -1415,9 +1415,9 @@ void tst_Dumpers::dumper() //qDebug() << "NUM CHECKS" << data.checks.size(); Check check = data.checks.at(i); QString iname = "local." + check.iname; - WatchItem *item = local.findAnyChild<WatchItem *>([iname](WatchItem *item) { - return item->internalName() == iname; - }); + WatchItem *item = static_cast<WatchItem *>(local.findAnyChild([iname](Utils::TreeItem *item) { + return static_cast<WatchItem *>(item)->internalName() == iname; + })); if (item) { seenINames.insert(iname); //qDebug() << "CHECKS" << i << check.iname; diff --git a/tests/auto/utils/treemodel/tst_treemodel.cpp b/tests/auto/utils/treemodel/tst_treemodel.cpp index e87f30183e0..22eb5a23f28 100644 --- a/tests/auto/utils/treemodel/tst_treemodel.cpp +++ b/tests/auto/utils/treemodel/tst_treemodel.cpp @@ -47,7 +47,7 @@ static int countLevelItems(TreeItem *base, int level) { int n = 0; int bl = base->level(); - base->forAllChildren<TreeItem *>([level, bl, &n](TreeItem *item) { + base->forAllChildren([level, bl, &n](TreeItem *item) { if (item->level() == bl + level) ++n; }); -- GitLab