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