1 /*
2  * SPDX-FileCopyrightText: 2014 Mario Bensi <mbensi@ipsquad.net>
3    SPDX-FileCopyrightText: 2014 Kevin Ottens <ervin@kde.org>
4    * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
5    */
6 
7 
8 
9 #ifndef PRESENTATION_QUERYTREENODE_H
10 #define PRESENTATION_QUERYTREENODE_H
11 
12 #include <functional>
13 
14 #include "domain/task.h"
15 
16 #include "domain/queryresultinterface.h"
17 
18 #include "querytreemodelbase.h"
19 
20 namespace Presentation {
21 
22 template<typename ItemType, typename AdditionalInfo>
23 class QueryTreeNode : public QueryTreeNodeBase
24 {
25 public:
26     typedef Domain::QueryResultInterface<ItemType> ItemQuery;
27     typedef typename ItemQuery::Ptr ItemQueryPtr;
28 
29     typedef std::function<ItemQueryPtr(const ItemType &)> QueryGenerator;
30     typedef std::function<Qt::ItemFlags(const ItemType &)> FlagsFunction;
31     typedef std::function<QVariant(const ItemType &, int, const AdditionalInfo &)> DataFunction;
32     typedef std::function<bool(const ItemType &, const QVariant &, int)> SetDataFunction;
33     typedef std::function<bool(const QMimeData *, Qt::DropAction, const ItemType &)> DropFunction;
34 
QueryTreeNode(const ItemType & item,QueryTreeNodeBase * parentNode,QueryTreeModelBase * model,const QueryGenerator & queryGenerator,const FlagsFunction & flagsFunction,const DataFunction & dataFunction,const SetDataFunction & setDataFunction)35     QueryTreeNode(const ItemType &item, QueryTreeNodeBase *parentNode, QueryTreeModelBase *model,
36                   const QueryGenerator &queryGenerator,
37                   const FlagsFunction &flagsFunction,
38                   const DataFunction &dataFunction,
39                   const SetDataFunction &setDataFunction)
40         : QueryTreeNodeBase(parentNode, model),
41           m_item(item),
42           m_flagsFunction(flagsFunction),
43           m_dataFunction(dataFunction),
44           m_setDataFunction(setDataFunction)
45     {
46         init(model, queryGenerator);
47     }
48 
QueryTreeNode(const ItemType & item,QueryTreeNodeBase * parentNode,QueryTreeModelBase * model,const QueryGenerator & queryGenerator,const FlagsFunction & flagsFunction,const DataFunction & dataFunction,const SetDataFunction & setDataFunction,const DropFunction & dropFunction)49     QueryTreeNode(const ItemType &item, QueryTreeNodeBase *parentNode, QueryTreeModelBase *model,
50                   const QueryGenerator &queryGenerator,
51                   const FlagsFunction &flagsFunction,
52                   const DataFunction &dataFunction,
53                   const SetDataFunction &setDataFunction,
54                   const DropFunction &dropFunction)
55         : QueryTreeNodeBase(parentNode, model),
56           m_item(item),
57           m_flagsFunction(flagsFunction),
58           m_dataFunction(dataFunction),
59           m_setDataFunction(setDataFunction),
60           m_dropFunction(dropFunction)
61     {
62         init(model, queryGenerator);
63     }
64 
item()65     ItemType item() const { return m_item; }
66 
flags()67     Qt::ItemFlags flags() const override { return m_flagsFunction(m_item); }
68 
data(int role)69     QVariant data(int role) const override
70     {
71         if (role == QueryTreeModelBase::ObjectRole)
72             return QVariant::fromValue(m_item);
73 
74         return m_dataFunction(m_item, role, m_additionalInfo);
75     }
76 
setData(const QVariant & value,int role)77     bool setData(const QVariant &value, int role) override { return m_setDataFunction(m_item, value, role); }
78 
dropMimeData(const QMimeData * data,Qt::DropAction action)79     bool dropMimeData(const QMimeData *data, Qt::DropAction action) override
80     {
81         if (m_dropFunction)
82             return m_dropFunction(data, action, m_item);
83         else
84             return false;
85     }
86 
hasAdditionalInfo()87     bool hasAdditionalInfo() const { return m_additionalInfo; }
setAdditionalInfo(const AdditionalInfo & info)88     void setAdditionalInfo(const AdditionalInfo &info) { m_additionalInfo = info; }
89 
90 private:
init(QueryTreeModelBase * model,const QueryGenerator & queryGenerator)91     void init(QueryTreeModelBase *model, const QueryGenerator &queryGenerator)
92     {
93         m_children = queryGenerator(m_item);
94 
95         if (!m_children)
96             return;
97 
98         for (auto child : m_children->data()) {
99             QueryTreeNodeBase *node = new QueryTreeNode<ItemType, AdditionalInfo>(child, this,
100                                                                   model, queryGenerator,
101                                                                   m_flagsFunction,
102                                                                   m_dataFunction, m_setDataFunction,
103                                                                   m_dropFunction);
104             appendChild(node);
105         }
106 
107         m_children->addPreInsertHandler([this](const ItemType &, int index) {
108             QModelIndex parentIndex = parent() ? createIndex(row(), 0, this) : QModelIndex();
109             beginInsertRows(parentIndex, index, index);
110         });
111         m_children->addPostInsertHandler([this, model, queryGenerator](const ItemType &item, int index) {
112             QueryTreeNodeBase *node = new QueryTreeNode<ItemType, AdditionalInfo>(item, this,
113                                                                   model, queryGenerator,
114                                                                   m_flagsFunction,
115                                                                   m_dataFunction, m_setDataFunction,
116                                                                   m_dropFunction);
117             insertChild(index, node);
118             endInsertRows();
119         });
120         m_children->addPreRemoveHandler([this](const ItemType &, int index) {
121             QModelIndex parentIndex = parent() ? createIndex(row(), 0, this) : QModelIndex();
122             beginRemoveRows(parentIndex, index, index);
123         });
124         m_children->addPostRemoveHandler([this](const ItemType &, int index) {
125             removeChildAt(index);
126             endRemoveRows();
127         });
128         m_children->addPostReplaceHandler([this](const ItemType &, int idx) {
129             const QModelIndex parentIndex = parent() ? createIndex(row(), 0, this) : QModelIndex();
130             const QModelIndex dataIndex = index(idx, 0, parentIndex);
131             emitDataChanged(dataIndex, dataIndex);
132         });
133     }
134 
135     ItemType m_item;
136     ItemQueryPtr m_children;
137     mutable AdditionalInfo m_additionalInfo;
138 
139     FlagsFunction m_flagsFunction;
140     DataFunction m_dataFunction;
141     SetDataFunction m_setDataFunction;
142     DropFunction m_dropFunction;
143 };
144 
145 }
146 
147 #endif // PRESENTATION_QUERYTREENODE_H
148