diff --git a/src/libs/utils/listmodel.h b/src/libs/utils/listmodel.h new file mode 100644 index 00000000000..5f4de811e67 --- /dev/null +++ b/src/libs/utils/listmodel.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "utils_global.h" +#include "treemodel.h" + +namespace Utils { + +template +class BaseListModel : public TreeModel, ChildType> +{ +public: + using BaseModel = TreeModel, ChildType>; + using BaseModel::rootItem; + + explicit BaseListModel(QObject *parent = nullptr) : BaseModel(parent) {} + + int itemCount() const { return rootItem()->childCount(); } + ChildType *itemAt(int row) const { return rootItem()->childAt(row); } + + void appendItem(ChildType *item) { rootItem()->appendChild(item); } + + template + void forItems(const Predicate &pred) const + { + rootItem()->forFirstLevelChildren(pred); + } + + template + ChildType *findItem(const Predicate &pred) const + { + return rootItem()->findFirstLevelChild(pred); + } + + void sortItems(const std::function &lessThan) + { + return rootItem()->sortChildren([lessThan](const TreeItem *a, const TreeItem *b) { + return lessThan(static_cast(a), static_cast(b)); + }); + } + + int indexOf(const ChildType *item) const { return rootItem()->indexOf(item); } + + void clear() { rootItem()->removeChildren(); } + + using const_iterator = typename QVector::const_iterator; + const_iterator begin() const { return rootItem()->begin(); } + const_iterator end() const { return rootItem()->end(); } + +}; + +template +class ListItem : public TreeItem +{ +public: + ItemData itemData; +}; + +template +class ListModel : public BaseListModel> +{ +public: + using ChildType = ListItem; + using BaseModel = BaseListModel; + + explicit ListModel(QObject *parent = nullptr) : BaseModel(parent) {} + + const ItemData &dataAt(int row) const + { + static const ItemData dummyData = {}; + auto item = BaseModel::itemAt(row); + return item ? item->itemData : dummyData; + } + + ChildType *findItemByData(const std::function &pred) const + { + return BaseModel::rootItem()->findFirstLevelChild([pred](ChildType *child) { + return pred(child->itemData); + }); + } + + void destroyItems(const std::function &pred) + { + QList toDestroy; + BaseModel::rootItem()->forFirstLevelChildren([pred, &toDestroy](ChildType *item) { + if (pred(item->itemData)) + toDestroy.append(item); + }); + for (ChildType *item : toDestroy) + this->destroyItem(item); + } + + ItemData *findData(const std::function &pred) const + { + ChildType *item = findItemByData(pred); + return item ? &item->itemData : nullptr; + } + + void forItems(const std::function &func) const + { + BaseModel::rootItem()->forFirstLevelChildren([func](ChildType *child) { + func(child->itemData); + }); + } + + ChildType *appendItem(const ItemData &data) + { + auto item = new ChildType; + item->itemData = data; + BaseModel::rootItem()->appendChild(item); + return item; + } + + QVariant data(const QModelIndex &idx, int role) const override + { + TreeItem *item = BaseModel::itemForIndex(idx); + if (item && item->parent() == BaseModel::rootItem()) + return itemData(static_cast(item)->itemData, idx.column(), role); + return {}; + } + + Qt::ItemFlags flags(const QModelIndex &idx) const override + { + TreeItem *item = BaseModel::itemForIndex(idx); + if (item && item->parent() == BaseModel::rootItem()) + return itemFlags(static_cast(item)->itemData, idx.column()); + return {}; + } + + virtual QVariant itemData(const ItemData &idata, int column, int role) const + { + if (m_dataAccessor) + return m_dataAccessor(idata, column, role); + return {}; + } + + virtual Qt::ItemFlags itemFlags(const ItemData &idata, int column) const + { + if (m_flagsAccessor) + return m_flagsAccessor(idata, column); + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + } + + void setDataAccessor(const std::function &accessor) + { + m_dataAccessor = accessor; + } + + void setFlagsAccessor(const std::function &accessor) + { + m_flagsAccessor = accessor; + } + +private: + std::function m_dataAccessor; + std::function m_flagsAccessor; +}; + +} // namespace Utils diff --git a/src/libs/utils/utils-lib.pri b/src/libs/utils/utils-lib.pri index a3e06cc337b..a71cfaeb993 100644 --- a/src/libs/utils/utils-lib.pri +++ b/src/libs/utils/utils-lib.pri @@ -268,7 +268,8 @@ HEADERS += \ $$PWD/removefiledialog.h \ $$PWD/differ.h \ $$PWD/cpplanguage_details.h \ - $$PWD/jsontreeitem.h + $$PWD/jsontreeitem.h \ + $$PWD/listmodel.h FORMS += $$PWD/filewizardpage.ui \ $$PWD/newclasswidget.ui \ diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index 2798f3ab165..694045e2900 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -146,6 +146,7 @@ Project { "jsontreeitem.h", "linecolumn.h", "link.h", + "listmodel.h", "listutils.h", "macroexpander.cpp", "macroexpander.h",