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 | |
34 | namespace Akonadi |
35 | { |
36 | class ItemFetchJob; |
37 | class ChangeRecorder; |
38 | class AgentInstance; |
39 | } |
40 | |
41 | struct 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 | |
54 | namespace Akonadi |
55 | { |
56 | /** |
57 | * @internal |
58 | */ |
59 | class AKONADI_TESTS_EXPORT EntityTreeModelPrivate |
60 | { |
61 | public: |
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 | |