File indexing completed on 2025-01-05 04:59:44

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Mario Bensi <mbensi@ipsquad.net>
0003    SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
0004    * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005    */
0006 
0007 
0008 
0009 #ifndef PRESENTATION_QUERYTREENODE_H
0010 #define PRESENTATION_QUERYTREENODE_H
0011 
0012 #include <functional>
0013 
0014 #include "domain/task.h"
0015 
0016 #include "domain/queryresultinterface.h"
0017 
0018 #include "querytreemodelbase.h"
0019 
0020 namespace Presentation {
0021 
0022 template<typename ItemType, typename AdditionalInfo>
0023 class QueryTreeNode : public QueryTreeNodeBase
0024 {
0025 public:
0026     typedef Domain::QueryResultInterface<ItemType> ItemQuery;
0027     typedef typename ItemQuery::Ptr ItemQueryPtr;
0028 
0029     typedef std::function<ItemQueryPtr(const ItemType &)> QueryGenerator;
0030     typedef std::function<Qt::ItemFlags(const ItemType &)> FlagsFunction;
0031     typedef std::function<QVariant(const ItemType &, int, const AdditionalInfo &)> DataFunction;
0032     typedef std::function<bool(const ItemType &, const QVariant &, int)> SetDataFunction;
0033     typedef std::function<bool(const QMimeData *, Qt::DropAction, const ItemType &)> DropFunction;
0034 
0035     QueryTreeNode(const ItemType &item, QueryTreeNodeBase *parentNode, QueryTreeModelBase *model,
0036                   const QueryGenerator &queryGenerator,
0037                   const FlagsFunction &flagsFunction,
0038                   const DataFunction &dataFunction,
0039                   const SetDataFunction &setDataFunction)
0040         : QueryTreeNodeBase(parentNode, model),
0041           m_item(item),
0042           m_flagsFunction(flagsFunction),
0043           m_dataFunction(dataFunction),
0044           m_setDataFunction(setDataFunction)
0045     {
0046         init(model, queryGenerator);
0047     }
0048 
0049     QueryTreeNode(const ItemType &item, QueryTreeNodeBase *parentNode, QueryTreeModelBase *model,
0050                   const QueryGenerator &queryGenerator,
0051                   const FlagsFunction &flagsFunction,
0052                   const DataFunction &dataFunction,
0053                   const SetDataFunction &setDataFunction,
0054                   const DropFunction &dropFunction)
0055         : QueryTreeNodeBase(parentNode, model),
0056           m_item(item),
0057           m_flagsFunction(flagsFunction),
0058           m_dataFunction(dataFunction),
0059           m_setDataFunction(setDataFunction),
0060           m_dropFunction(dropFunction)
0061     {
0062         init(model, queryGenerator);
0063     }
0064 
0065     ItemType item() const { return m_item; }
0066 
0067     Qt::ItemFlags flags() const override { return m_flagsFunction(m_item); }
0068 
0069     QVariant data(int role) const override
0070     {
0071         if (role == QueryTreeModelBase::ObjectRole)
0072             return QVariant::fromValue(m_item);
0073 
0074         return m_dataFunction(m_item, role, m_additionalInfo);
0075     }
0076 
0077     bool setData(const QVariant &value, int role) override { return m_setDataFunction(m_item, value, role); }
0078 
0079     bool dropMimeData(const QMimeData *data, Qt::DropAction action) override
0080     {
0081         if (m_dropFunction)
0082             return m_dropFunction(data, action, m_item);
0083         else
0084             return false;
0085     }
0086 
0087     bool hasAdditionalInfo() const { return hasAdditionalInfo(m_additionalInfo); }
0088     void setAdditionalInfo(const AdditionalInfo &info) { m_additionalInfo = info; }
0089 
0090 private:
0091     template <typename T>
0092     inline bool hasAdditionalInfo(const QSharedPointer<T> &p) const {
0093         return !p.isNull();
0094     }
0095     template <typename T>
0096     inline bool hasAdditionalInfo(const T &value) const
0097     {
0098         return value;
0099     }
0100 
0101     void init(QueryTreeModelBase *model, const QueryGenerator &queryGenerator)
0102     {
0103         m_children = queryGenerator(m_item);
0104 
0105         if (!m_children)
0106             return;
0107 
0108         for (auto child : m_children->data()) {
0109             QueryTreeNodeBase *node = new QueryTreeNode<ItemType, AdditionalInfo>(child, this,
0110                                                                   model, queryGenerator,
0111                                                                   m_flagsFunction,
0112                                                                   m_dataFunction, m_setDataFunction,
0113                                                                   m_dropFunction);
0114             appendChild(node);
0115         }
0116 
0117         m_children->addPreInsertHandler([this](const ItemType &, int index) {
0118             QModelIndex parentIndex = parent() ? createIndex(row(), 0, this) : QModelIndex();
0119             beginInsertRows(parentIndex, index, index);
0120         });
0121         m_children->addPostInsertHandler([this, model, queryGenerator](const ItemType &item, int index) {
0122             QueryTreeNodeBase *node = new QueryTreeNode<ItemType, AdditionalInfo>(item, this,
0123                                                                   model, queryGenerator,
0124                                                                   m_flagsFunction,
0125                                                                   m_dataFunction, m_setDataFunction,
0126                                                                   m_dropFunction);
0127             insertChild(index, node);
0128             endInsertRows();
0129         });
0130         m_children->addPreRemoveHandler([this](const ItemType &, int index) {
0131             QModelIndex parentIndex = parent() ? createIndex(row(), 0, this) : QModelIndex();
0132             beginRemoveRows(parentIndex, index, index);
0133         });
0134         m_children->addPostRemoveHandler([this](const ItemType &, int index) {
0135             removeChildAt(index);
0136             endRemoveRows();
0137         });
0138         m_children->addPostReplaceHandler([this](const ItemType &, int idx) {
0139             const QModelIndex parentIndex = parent() ? createIndex(row(), 0, this) : QModelIndex();
0140             const QModelIndex dataIndex = index(idx, 0, parentIndex);
0141             emitDataChanged(dataIndex, dataIndex);
0142         });
0143     }
0144 
0145     ItemType m_item;
0146     ItemQueryPtr m_children;
0147     mutable AdditionalInfo m_additionalInfo;
0148 
0149     FlagsFunction m_flagsFunction;
0150     DataFunction m_dataFunction;
0151     SetDataFunction m_setDataFunction;
0152     DropFunction m_dropFunction;
0153 };
0154 
0155 }
0156 
0157 #endif // PRESENTATION_QUERYTREENODE_H