summaryrefslogtreecommitdiffstats
path: root/common/modelresult.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'common/modelresult.cpp')
-rw-r--r--common/modelresult.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/common/modelresult.cpp b/common/modelresult.cpp
new file mode 100644
index 0000000..1abcc62
--- /dev/null
+++ b/common/modelresult.cpp
@@ -0,0 +1,203 @@
1/*
2 * Copyright (C) 2014 Christian Mollekopf <chrigi_1@fastmail.fm>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) version 3, or any
8 * later version accepted by the membership of KDE e.V. (or its
9 * successor approved by the membership of KDE e.V.), which shall
10 * act as a proxy defined in Section 6 of version 3 of the license.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20#include "modelresult.h"
21
22#include <QDebug>
23
24#include "domain/folder.h"
25#include "log.h"
26
27template<class T, class Ptr>
28ModelResult<T, Ptr>::ModelResult(const Akonadi2::Query &query, const QList<QByteArray> &propertyColumns)
29 :QAbstractItemModel(),
30 mPropertyColumns(propertyColumns)
31{
32}
33
34static qint64 getIdentifier(const QModelIndex &idx)
35{
36 if (!idx.isValid()) {
37 return 0;
38 }
39 return idx.internalId();
40}
41
42template<class T, class Ptr>
43qint64 ModelResult<T, Ptr>::parentId(const Ptr &value)
44{
45 return qHash(value->getProperty("parent").toByteArray());
46}
47
48template<class T, class Ptr>
49int ModelResult<T, Ptr>::rowCount(const QModelIndex &parent) const
50{
51 return mTree[getIdentifier(parent)].size();
52}
53
54template<class T, class Ptr>
55int ModelResult<T, Ptr>::columnCount(const QModelIndex &parent) const
56{
57 return mPropertyColumns.size();
58}
59
60template<class T, class Ptr>
61QVariant ModelResult<T, Ptr>::data(const QModelIndex &index, int role) const
62{
63 if (role == DomainObjectRole) {
64 Q_ASSERT(mEntities.contains(index.internalId()));
65 return QVariant::fromValue(mEntities.value(index.internalId()));
66 }
67 if (role == Qt::DisplayRole) {
68 if (index.column() < mPropertyColumns.size()) {
69 Q_ASSERT(mEntities.contains(index.internalId()));
70 auto entity = mEntities.value(index.internalId());
71 return entity->getProperty(mPropertyColumns.at(index.column())).toString();
72 } else {
73 return "No data available";
74 }
75 }
76 return QVariant();
77}
78
79template<class T, class Ptr>
80QModelIndex ModelResult<T, Ptr>::index(int row, int column, const QModelIndex &parent) const
81{
82 auto id = getIdentifier(parent);
83 auto childId = mTree.value(id).at(row);
84 return createIndex(row, column, childId);
85}
86
87template<class T, class Ptr>
88QModelIndex ModelResult<T, Ptr>::createIndexFromId(const qint64 &id) const
89{
90 auto grandParentId = mParents.value(id, 0);
91 auto row = mTree.value(grandParentId).indexOf(id);
92 return createIndex(row, 0, id);
93}
94
95template<class T, class Ptr>
96QModelIndex ModelResult<T, Ptr>::parent(const QModelIndex &index) const
97{
98 auto id = getIdentifier(index);
99 auto parentId = mParents.value(id);
100 return createIndexFromId(parentId);
101}
102
103template<class T, class Ptr>
104bool ModelResult<T, Ptr>::canFetchMore(const QModelIndex &parent) const
105{
106 qDebug() << "Can fetch more: " << parent << mEntityChildrenFetched.value(parent.internalId());
107 return mEntityChildrenFetched.value(parent.internalId());
108}
109
110template<class T, class Ptr>
111void ModelResult<T, Ptr>::fetchMore(const QModelIndex &parent)
112{
113 qDebug() << "Fetch more: " << parent;
114 fetchEntities(parent);
115}
116
117template<class T, class Ptr>
118void ModelResult<T, Ptr>::add(const Ptr &value)
119{
120 auto childId = qHash(value->identifier());
121 auto id = parentId(value);
122 //Ignore updates we get before the initial fetch is done
123 if (!mEntityChildrenFetched[id]) {
124 return;
125 }
126 auto parent = createIndexFromId(id);
127 qDebug() << "Added entity " << childId << value->identifier() << id;
128 const auto keys = mTree[id];
129 int index = 0;
130 for (; index < keys.size(); index++) {
131 if (childId < keys.at(index)) {
132 break;
133 }
134 }
135 if (mEntities.contains(childId)) {
136 qWarning() << "Entity already in model " << value->identifier();
137 return;
138 }
139 qDebug() << "Inserting rows " << index << parent;
140 beginInsertRows(QModelIndex(), index, index);
141 mEntities.insert(childId, value);
142 mTree[id].insert(index, childId);
143 mParents.insert(childId, id);
144 endInsertRows();
145 qDebug() << "Inserted rows " << mTree[id].size();
146}
147
148
149template<class T, class Ptr>
150void ModelResult<T, Ptr>::remove(const Ptr &value)
151{
152 auto childId = qHash(value->identifier());
153 auto id = parentId(value);
154 auto parent = createIndexFromId(id);
155 qDebug() << "Removed entity" << childId;
156 auto index = mTree[id].indexOf(qHash(value->identifier()));
157 beginRemoveRows(parent, index, index);
158 mEntities.remove(childId);
159 mTree[id].removeAll(childId);
160 mParents.remove(childId);
161 //TODO remove children
162 endRemoveRows();
163}
164
165template<class T, class Ptr>
166void ModelResult<T, Ptr>::fetchEntities(const QModelIndex &parent)
167{
168 const auto id = getIdentifier(parent);
169 mEntityChildrenFetched[id] = true;
170 Trace() << "Loading child entities";
171 loadEntities(parent.data(DomainObjectRole).template value<Ptr>());
172}
173
174template<class T, class Ptr>
175void ModelResult<T, Ptr>::setFetcher(const std::function<void(const Ptr &parent)> &fetcher)
176{
177 Trace() << "Setting fetcher";
178 loadEntities = fetcher;
179}
180
181template<class T, class Ptr>
182void ModelResult<T, Ptr>::modify(const Ptr &value)
183{
184 auto childId = qHash(value->identifier());
185 auto id = parentId(value);
186 //Ignore updates we get before the initial fetch is done
187 if (!mEntityChildrenFetched[id]) {
188 return;
189 }
190 auto parent = createIndexFromId(id);
191 qDebug() << "Modified entity" << childId;
192 auto i = mTree[id].indexOf(childId);
193 mEntities.remove(childId);
194 mEntities.insert(childId, value);
195 //TODO check for change of parents
196 auto idx = index(i, 0, parent);
197 emit dataChanged(idx, idx);
198}
199
200template class ModelResult<Akonadi2::ApplicationDomain::Folder, Akonadi2::ApplicationDomain::Folder::Ptr>;
201template class ModelResult<Akonadi2::ApplicationDomain::Mail, Akonadi2::ApplicationDomain::Mail::Ptr>;
202template class ModelResult<Akonadi2::ApplicationDomain::Event, Akonadi2::ApplicationDomain::Event::Ptr>;
203template class ModelResult<Akonadi2::ApplicationDomain::AkonadiResource, Akonadi2::ApplicationDomain::AkonadiResource::Ptr>;