1/*
2 Copyright (c) 2008 Stephen Kelly <steveire@gmail.com>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#ifndef ENTITYTREEMODELPRIVATE_H
21#define ENTITYTREEMODELPRIVATE_H
22
23#include <akonadi/item.h>
24#include <KJob>
25
26#include <akonadi/collectionfetchjob.h>
27#include <akonadi/itemfetchscope.h>
28#include <akonadi/mimetypechecker.h>
29
30#include "entitytreemodel.h"
31
32#include "akonadiprivate_export.h"
33
34namespace Akonadi
35{
36class ItemFetchJob;
37class ChangeRecorder;
38class AgentInstance;
39}
40
41struct Node
42{
43 Akonadi::Entity::Id id;
44 Akonadi::Entity::Id parent;
45
46 enum Type {
47 Item,
48 Collection
49 };
50
51 int type;
52};
53
54namespace Akonadi
55{
56/**
57 * @internal
58 */
59class AKONADI_TESTS_EXPORT EntityTreeModelPrivate
60{
61public:
62
63 explicit EntityTreeModelPrivate(EntityTreeModel *parent);
64 ~EntityTreeModelPrivate();
65 EntityTreeModel *const q_ptr;
66
67 enum RetrieveDepth {
68 Base,
69 Recursive
70 };
71
72 void init(ChangeRecorder *monitor);
73
74 void fetchCollections(const Collection &collection, CollectionFetchJob::Type type = CollectionFetchJob::FirstLevel);
75 void fetchCollections(const Collection::List &collections, CollectionFetchJob::Type type = CollectionFetchJob::FirstLevel);
76 void fetchCollections(Akonadi::CollectionFetchJob *job);
77 void fetchItems(const Collection &collection);
78 void collectionsFetched(const Akonadi::Collection::List &);
79 void collectionListFetched(const Akonadi::Collection::List &);
80 void itemsFetched(const Akonadi::Item::List &items);
81 void itemsFetched(const Collection::Id collectionId, const Akonadi::Item::List &items);
82
83 void monitoredCollectionAdded(const Akonadi::Collection &, const Akonadi::Collection &);
84 void monitoredCollectionRemoved(const Akonadi::Collection &);
85 void monitoredCollectionChanged(const Akonadi::Collection &);
86 void monitoredCollectionStatisticsChanged(Akonadi::Collection::Id, const Akonadi::CollectionStatistics &);
87 void monitoredCollectionMoved(const Akonadi::Collection &, const Akonadi::Collection &, const Akonadi::Collection &);
88
89 void monitoredItemAdded(const Akonadi::Item &, const Akonadi::Collection &);
90 void monitoredItemRemoved(const Akonadi::Item &);
91 void monitoredItemChanged(const Akonadi::Item &, const QSet<QByteArray> &);
92 void monitoredItemMoved(const Akonadi::Item &, const Akonadi::Collection &, const Akonadi::Collection &);
93
94 void monitoredItemLinked(const Akonadi::Item &, const Akonadi::Collection &);
95 void monitoredItemUnlinked(const Akonadi::Item &, const Akonadi::Collection &);
96
97 void monitoredMimeTypeChanged(const QString &mimeType, bool monitored);
98 void monitoredCollectionsChanged(const Akonadi::Collection &collection, bool monitored);
99 void monitoredItemsChanged(const Akonadi::Item &item, bool monitored);
100 void monitoredResourcesChanged(const QByteArray &resource, bool monitored);
101
102 Collection::List getParentCollections(const Item &item) const;
103 void removeChildEntities(Collection::Id collectionId);
104
105 /**
106 * Returns the list of names of the child collections of @p collection.
107 */
108 QStringList childCollectionNames(const Collection &collection) const;
109
110 /**
111 * Fetch parent collections and insert this @p collection and its parents into the node tree
112 */
113 void retrieveAncestors(const Akonadi::Collection &collection, bool insertBaseCollection = true);
114 void ancestorsFetched(const Akonadi::Collection::List &collectionList);
115 void insertCollection(const Akonadi::Collection &collection, const Akonadi::Collection &parent);
116 void insertPendingCollection(const Akonadi::Collection &collection, const Akonadi::Collection &parent, QMutableListIterator<Collection> &it);
117
118 void beginResetModel();
119 void endResetModel();
120 /**
121 * Start function for filling the Model, finds and fetches the root of the node tree
122 * Next relevant function for filling the model is startFirstListJob()
123 */
124 void fillModel();
125
126 void changeFetchState(const Collection &parent);
127 void agentInstanceAdvancedStatusChanged(const QString &, const QVariantMap &);
128 void agentInstanceRemoved(const Akonadi::AgentInstance &instace);
129
130 QHash<Collection::Id, Collection> m_collections;
131 QHash<Entity::Id, Item> m_items;
132 QHash<Collection::Id, QList<Node *> > m_childEntities;
133 QSet<Collection::Id> m_populatedCols;
134 QSet<Collection::Id> m_collectionsWithoutItems;
135
136 QVector<Entity::Id> m_pendingCutItems;
137 QVector<Entity::Id> m_pendingCutCollections;
138 mutable QSet<Collection::Id> m_pendingCollectionRetrieveJobs;
139
140 ChangeRecorder *m_monitor;
141 Collection m_rootCollection;
142 Node *m_rootNode;
143 QString m_rootCollectionDisplayName;
144 QStringList m_mimeTypeFilter;
145 MimeTypeChecker m_mimeChecker;
146 EntityTreeModel::CollectionFetchStrategy m_collectionFetchStrategy;
147 EntityTreeModel::ItemPopulationStrategy m_itemPopulation;
148 CollectionFetchScope::ListFilter m_listFilter;
149 bool m_includeStatistics;
150 bool m_showRootCollection;
151 bool m_collectionTreeFetched;
152 QHash<Collection::Id, uint> m_collectionSyncProgress;
153
154 /**
155 * Called after the root collection was fetched by fillModel
156 *
157 * Initiates further fetching of collections depending on the monitored collections
158 * (in the monitor) and the m_collectionFetchStrategy.
159 *
160 * Further collections are either fetched directly with fetchCollections and
161 * fetchItems or, in case that collections or resources are monitored explicitly
162 * via fetchTopLevelCollections
163 */
164 void startFirstListJob();
165
166 void serverStarted();
167
168 void monitoredItemsRetrieved(KJob *job);
169 void rootFetchJobDone(KJob *job);
170 void collectionFetchJobDone(KJob *job);
171 void itemFetchJobDone(KJob *job);
172 void finalCollectionFetchJobDone(KJob *job);
173 void updateJobDone(KJob *job);
174 void pasteJobDone(KJob *job);
175
176 /**
177 * Returns the index of the node in @p list with the id @p id. Returns -1 if not found.
178 */
179 template<Node::Type Type>
180 int indexOf(const QList<Node *> &nodes, Entity::Id id) const
181 {
182 int i = 0;
183 foreach (const Node *node, nodes) {
184 if (node->id == id && node->type == Type) {
185 return i;
186 }
187 i++;
188 }
189
190 return -1;
191 }
192
193 /**
194 * The id of the collection which starts an item fetch job. This is part of a hack with QObject::sender
195 * in itemsReceivedFromJob to correctly insert items into the model.
196 */
197 static QByteArray FetchCollectionId() {
198 return "FetchCollectionId";
199 }
200
201 Session *m_session;
202
203 Q_DECLARE_PUBLIC(EntityTreeModel)
204
205 void fetchTopLevelCollections() const;
206 void topLevelCollectionsFetched(const Akonadi::Collection::List &collectionList);
207
208 /**
209 @returns True if @p entity or one of its descemdants is hidden.
210 */
211 bool isHidden(const Entity &entity, Node::Type type) const;
212
213 template<typename T>
214 bool isHidden(const T &entity) const;
215
216 bool m_showSystemEntities;
217
218 void ref(Collection::Id id);
219 void deref(Collection::Id id);
220
221 /**
222 * @returns true if the collection is actively monitored (referenced or buffered with refcounting enabled)
223 *
224 * purely for testing
225 */
226 bool isMonitored(Collection::Id id);
227
228 /**
229 * @returns true if the collection is buffered
230 *
231 * purely for testing
232 */
233 bool isBuffered(Collection::Id id);
234
235 /**
236 @returns true if the Collection with the id of @p id should be purged.
237 */
238 bool shouldPurge(Collection::Id id);
239
240 /**
241 Purges the items in the Collection @p id
242 */
243 void purgeItems(Collection::Id id);
244
245 /**
246 Removes the items starting from @p it and up to a maximum of @p end in Collection @p col. @p pos should be the index of @p it
247 in the m_childEntities before calling, and is updated to the position of the next Collection in m_childEntities afterward.
248 This is required to emit model remove signals properly.
249
250 @returns an iterator pointing to the next Collection after @p it, or at @p end
251 */
252 QList<Node *>::iterator removeItems(QList<Node *>::iterator it, QList<Node *>::iterator end,
253 int *pos, const Collection &col);
254
255 /**
256 Skips over Collections in m_childEntities up to a maximum of @p end. @p it is an iterator pointing to the first Collection
257 in a block of Collections, and @p pos initially describes the index of @p it in m_childEntities and is updated to point to
258 the index of the next Item in the list.
259
260 @returns an iterator pointing to the next Item after @p it, or at @p end
261 */
262 QList<Node *>::iterator skipCollections(QList<Node *>::iterator it, QList<Node *>::iterator end, int *pos);
263
264 /**
265 Emits the data changed signal for the entire row as in the subclass, instead of just for the first column.
266 */
267 void dataChanged(const QModelIndex &top, const QModelIndex &bottom);
268
269 /**
270 * Returns the model index for the given @p collection.
271 */
272 QModelIndex indexForCollection(const Collection &collection) const;
273
274 /**
275 * Returns the model indexes for the given @p item.
276 */
277 QModelIndexList indexesForItem(const Item &item) const;
278
279 bool canFetchMore(const QModelIndex &parent) const;
280
281 /**
282 * Returns true if the collection matches all filters and should be part of the model.
283 * This method checks all properties that could change by modifying the collection.
284 * Currently that includes:
285 * * hidden attribute
286 * * content mime types
287 */
288 bool shouldBePartOfModel(const Collection &collection) const;
289 bool hasChildCollection(const Collection &collection) const;
290 bool isAncestorMonitored(const Collection &collection) const;
291};
292
293}
294
295#endif
296