// Copyright (C) 2019 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once #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(); } auto begin() const { return rootItem()->begin(); } auto 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; } QModelIndex findIndex(const std::function &pred) const { ChildType *item = findItemByData(pred); return item ? BaseTreeModel::indexForItem(item) : QModelIndex(); } QList allData() const { QList res; BaseModel::rootItem()->forFirstLevelChildren([&res](ChildType *child) { res.append(child->itemData); }); return res; } QList allData(const std::function &pred) const { QList res; BaseModel::rootItem()->forFirstLevelChildren([pred, &res](ChildType *item) { if (pred(item->itemData)) res.append(item->itemData); }); return res; } void setAllData(const QList &items) { BaseModel::rootItem()->removeChildren(); for (const ItemData &data : items) appendItem(data); } void forAllData(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 {}; } using QAbstractItemModel::itemData; 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