Akonadi

entitytreemodel.h
1/*
2 SPDX-FileCopyrightText: 2008 Stephen Kelly <steveire@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#pragma once
8
9#include "akonadicore_export.h"
10#include "collection.h"
11#include "collectionfetchscope.h"
12#include "item.h"
13
14#include <QAbstractItemModel>
15#include <QStringList>
16
17#include <memory>
18
19namespace Akonadi
20{
21class CollectionStatistics;
22class Item;
23class ItemFetchScope;
24class Monitor;
25class Session;
26
27class EntityTreeModelPrivate;
28
29/**
30 * @short A model for collections and items together.
31 *
32 * Akonadi models and views provide a high level way to interact with the akonadi server.
33 * Most applications will use these classes.
34 *
35 * Models provide an interface for viewing, updating, deleting and moving Items and Collections.
36 * Additionally, the models are updated automatically if another application changes the
37 * data or inserts of deletes items etc.
38 *
39 * @note The EntityTreeModel should be used with the EntityTreeView or the EntityListView class
40 * either directly or indirectly via proxy models.
41 *
42 * <h3>Retrieving Collections and Items from the model</h3>
43 *
44 * If you want to retrieve and Item or Collection from the model, and already have a valid
45 * QModelIndex for the correct row, the Collection can be retrieved like this:
46 *
47 * @code
48 * Collection col = index.data(EntityTreeModel::CollectionRole).value<Collection>();
49 * @endcode
50 *
51 * And similarly for Items. This works even if there is a proxy model between the calling code
52 * and the EntityTreeModel.
53 *
54 * If you want to retrieve a Collection for a particular Collection::Id and you do not yet
55 * have a valid QModelIndex, use modelIndexForCollection.
56 *
57 * <h3>Using EntityTreeModel in your application</h3>
58 *
59 * The responsibilities which fall to the application developer are
60 * - Configuring the Monitor and EntityTreeModel
61 * - Making use of this class via proxy models
62 * - Subclassing for type specific display information
63 *
64 * <h3>Creating and configuring the EntityTreeModel</h3>
65 *
66 * This class is a wrapper around a Akonadi::Monitor object. The model represents a
67 * part of the collection and item tree configured in the Monitor. The structure of the
68 * model mirrors the structure of Collections and Items on the %Akonadi server.
69 *
70 * The following code creates a model which fetches items and collections relevant to
71 * addressees (contacts), and automatically manages keeping the items up to date.
72 *
73 * @code
74 *
75 * auto monitor = new Monitor(this);
76 * monitor->setCollectionMonitored(Collection::root());
77 * monitor->setMimeTypeMonitored(KContacts::Addressee::mimeType());
78 * monitor->setSession(session);
79 *
80 * auto model = new EntityTreeModel(monitor, this);
81 *
82 * auto view = new EntityTreeView(this);
83 * view->setModel(model);
84 *
85 * @endcode
86 *
87 * The EntityTreeModel will show items of a different type by changing the line
88 *
89 * @code
90 * monitor->setMimeTypeMonitored(KContacts::Addressee::mimeType());
91 * @endcode
92 *
93 * to a different mimetype. KContacts::Addressee::mimeType() is an alias for "text/directory". If changed to KMime::Message::mimeType()
94 * (an alias for "message/rfc822") the model would instead contain emails. The model can be configured to contain items of any mimetype
95 * known to %Akonadi.
96 *
97 * @note The EntityTreeModel does some extra configuration on the Monitor, such as setting itemFetchScope() and collectionFetchScope()
98 * to retrieve all ancestors. This is necessary for proper function of the model.
99 *
100 * @see Akonadi::ItemFetchScope::AncestorRetrieval.
101 *
102 * @see akonadi-mimetypes.
103 *
104 * The EntityTreeModel can be further configured for certain behaviours such as fetching of collections and items.
105 *
106 * The model can be configured to not fetch items into the model (ie, fetch collections only) by setting
107 *
108 * @code
109 * entityTreeModel->setItemPopulationStrategy(EntityTreeModel::NoItemPopulation);
110 * @endcode
111 *
112 * The items may be fetched lazily, i.e. not inserted into the model until request by the user for performance reasons.
113 *
114 * The Collection tree is always built immediately if Collections are to be fetched.
115 *
116 * @code
117 * entityTreeModel->setItemPopulationStrategy(EntityTreeModel::LazyPopulation);
118 * @endcode
119 *
120 * This will typically be used with a EntityMimeTypeFilterModel in a configuration such as KMail or AkonadiConsole.
121 *
122 * The CollectionFetchStrategy determines how the model will be populated with Collections. That is, if FetchNoCollections is set,
123 * no collections beyond the root of the model will be fetched. This can be used in combination with setting a particular Collection to monitor.
124 *
125 * @code
126 * // Get an collection id from a config file.
127 * Collection::Id id;
128 * monitor->setCollectionMonitored(Collection(id));
129 * // ... Other initialization code.
130 * entityTree->setCollectionFetchStrategy(FetchNoCollections);
131 * @endcode
132 *
133 * This has the effect of creating a model of only a list of Items, and not collections. This is similar in behaviour and aims to the ItemModel.
134 * By using FetchFirstLevelCollections instead, a mixed list of entities can be created.
135 *
136 * @note It is important that you set only one Collection to be monitored in the monitor object. This one collection will be the root of the tree.
137 * If you need a model with a more complex structure, consider monitoring a common ancestor and using a SelectionProxyModel.
138 *
139 * @see lazy-model-population
140 *
141 * It is also possible to show the root Collection as part of the selectable model:
142 *
143 * @code
144 * entityTree->setIncludeRootCollection(true);
145 * @endcode
146 *
147 *
148 * By default the displayed name of the root collection is '[*]', because it doesn't require i18n, and is generic. It can be changed too.
149 *
150 * @code
151 * entityTree->setIncludeRootCollection(true);
152 * entityTree->setRootCollectionDisplayName(i18nc("Name of top level for all addressbooks in the application", "[All AddressBooks]"))
153 * @endcode
154 *
155 * This feature is used in KAddressBook.
156 *
157 * If items are to be fetched by the model, it is necessary to specify which parts of the items
158 * are to be fetched, using the ItemFetchScope class. By default, only the basic metadata is
159 * fetched. To fetch all item data, including all attributes:
160 *
161 * @code
162 * monitor->itemFetchScope().fetchFullPayload();
163 * monitor->itemFetchScope().fetchAllAttributes();
164 * @endcode
165 *
166 * <h2>Using EntityTreeModel with Proxy models</h2>
167 *
168 * An Akonadi::SelectionProxyModel can be used to simplify managing selection in one view through multiple proxy models to a representation in another view.
169 * The selectionModel of the initial view is used to create a proxied model which filters out anything not related to the current selection.
170 *
171 * @code
172 * // ... create an EntityTreeModel
173 *
174 * collectionTree = new EntityMimeTypeFilterModel(this);
175 * collectionTree->setSourceModel(entityTreeModel);
176 *
177 * // Include only collections in this proxy model.
178 * collectionTree->addMimeTypeInclusionFilter(Collection::mimeType());
179 * collectionTree->setHeaderGroup(EntityTreeModel::CollectionTreeHeaders);
180 *
181 * treeview->setModel(collectionTree);
182 *
183 * // SelectionProxyModel can handle complex selections:
184 * treeview->setSelectionMode(QAbstractItemView::ExtendedSelection);
185 *
186 * auto selProxy = new SelectionProxyModel(treeview->selectionModel(), this);
187 * selProxy->setSourceModel(entityTreeModel);
188 *
189 * itemList = new EntityMimeTypeFilterModel(this);
190 * itemList->setSourceModel(selProxy);
191 *
192 * // Filter out collections. Show only items.
193 * itemList->addMimeTypeExclusionFilter(Collection::mimeType());
194 * itemList->setHeaderGroup(EntityTreeModel::ItemListHeaders);
195 *
196 * auto itemView = new EntityTreeView(splitter);
197 * itemView->setModel(itemList);
198 * @endcode
199 *
200 * The SelectionProxyModel can handle complex selections.
201 *
202 * See the KSelectionProxyModel documentation for the valid configurations of a Akonadi::SelectionProxyModel.
203 *
204 * Obviously, the SelectionProxyModel may be used in a view, or further processed with other proxy models. Typically, the result
205 * from this model will be further filtered to remove collections from the item list as in the above example.
206 *
207 * There are several advantages of using EntityTreeModel with the SelectionProxyModel, namely the items can be fetched and cached
208 * instead of being fetched many times, and the chain of proxies from the core model to the view is automatically handled. There is
209 * no need to manage all the mapToSource and mapFromSource calls manually.
210 *
211 * A KDescendantsProxyModel can be used to represent all descendants of a model as a flat list.
212 * For example, to show all descendant items in a selected Collection in a list:
213 * @code
214 * auto collectionTree = new EntityMimeTypeFilterModel(this);
215 * collectionTree->setSourceModel(entityTreeModel);
216 *
217 * // Include only collections in this proxy model.
218 * collectionTree->addMimeTypeInclusionFilter(Collection::mimeType());
219 * collectionTree->setHeaderGroup(EntityTreeModel::CollectionTreeHeaders);
220 *
221 * treeview->setModel(collectionTree);
222 *
223 * auto selProxy = new SelectionProxyModel(treeview->selectionModel(), this);
224 * selProxy->setSourceModel(entityTreeModel);
225 *
226 * auto descendedList = new KDescendantsProxyModel(this);
227 * descendedList->setSourceModel(selProxy);
228 *
229 * auto itemList = new EntityMimeTypeFilterModel(this);
230 * itemList->setSourceModel(descendedList);
231 *
232 * // Exclude collections from the list view.
233 * itemList->addMimeTypeExclusionFilter(Collection::mimeType());
234 * itemList->setHeaderGroup(EntityTreeModel::ItemListHeaders);
235 *
236 * listView = new EntityTreeView(this);
237 * listView->setModel(itemList);
238 * @endcode
239 *
240 *
241 * Note that it is important in this case to use the KDescendantsProxyModel before the EntityMimeTypeFilterModel.
242 * Otherwise, by filtering out the collections first, you would also be filtering out their child items.
243 *
244 * This pattern is used in KAddressBook.
245 *
246 * It would not make sense to use a KDescendantsProxyModel with LazyPopulation.
247 *
248 * <h3>Subclassing EntityTreeModel</h3>
249 *
250 * Usually an application will create a subclass of an EntityTreeModel and use that in several views via proxy models.
251 *
252 * The subclassing is necessary in order for the data in the model to have type-specific representation in applications
253 *
254 * For example, the headerData for an EntityTreeModel will be different depending on whether it is in a view showing only Collections
255 * in which case the header data should be "AddressBooks" for example, or only Items, in which case the headerData would be
256 * for example "Family Name", "Given Name" and "Email address" for contacts or "Subject", "Sender", "Date" in the case of emails.
257 *
258 * Additionally, the actual data shown in the rows of the model should be type specific.
259 *
260 * In summary, it must be possible to have different numbers of columns, different data in the rows of those columns, and different
261 * titles for each column depending on the contents of the view.
262 *
263 * The way this is accomplished is by using the EntityMimeTypeFilterModel for splitting the model into a "CollectionTree" and an "Item List"
264 * as in the above example, and using a type-specific EntityTreeModel subclass to return the type-specific data, typically for only one type (for example,
265 * contacts or emails).
266 *
267 * The following protected virtual methods should be implemented in the subclass:
268 * - `int entityColumnCount( HeaderGroup headerGroup ) const;`
269 * -- Implement to return the number of columns for a HeaderGroup. If the HeaderGroup is CollectionTreeHeaders, return the number of columns to display for the
270 * Collection tree, and if it is ItemListHeaders, return the number of columns to display for the item. In the case of addressee, this could be for example,
271 * two (for given name and family name) or for emails it could be three (for subject, sender, date). This is a decision of the subclass implementor.
272 * - `QVariant entityHeaderData( int section, Qt::Orientation orientation, int role, HeaderGroup headerGroup ) const;`
273 * -- Implement to return the data for each section for a HeaderGroup. For example, if the header group is CollectionTreeHeaders in a contacts model,
274 * the string "Address books" might be returned for column 0, whereas if the headerGroup is ItemListHeaders, the strings "Given Name", "Family Name",
275 * "Email Address" might be returned for the columns 0, 1, and 2.
276 * - `QVariant entityData( const Collection &collection, int column, int role = Qt::DisplayRole ) const;`
277 * -- Implement to return data for a particular Collection. Typically this will be the name of the collection or the EntityDisplayAttribute.
278 * - `QVariant entityData(const Item &item, int column, int role = Qt::DisplayRole) const;`
279 * -- Implement to return the data for a particular item and column. In the case of email for example, this would be the actual subject, sender and date of the
280 * email.
281 *
282 * @note The entityData methods are just for convenience. the QAbstractItemModel::data method can be overridden if required.
283 *
284 * The application writer must then properly configure proxy models for the views, so that the correct data is shown in the correct view.
285 * That is the purpose of these lines in the above example
286 *
287 * @code
288 * collectionTree->setHeaderGroup(EntityTreeModel::CollectionTreeHeaders);
289 * itemList->setHeaderGroup(EntityTreeModel::ItemListHeaders);
290 * @endcode
291 *
292 * <h3>Progress reporting</h3>
293 *
294 * The EntityTreeModel uses asynchronous Akonadi::Job instances to fill and update itself.
295 * For example, a job is run to fetch the contents of collections (that is, list the items in it).
296 * Additionally, individual Akonadi::Items can be fetched in different parts at different times.
297 *
298 * To indicate that such a job is underway, the EntityTreeModel makes the FetchState available. The
299 * FetchState returned from a QModelIndex representing a Akonadi::Collection will be FetchingState if a
300 * listing of the items in that collection is underway, otherwise the state is IdleState.
301 *
302 * @author Stephen Kelly <steveire@gmail.com>
303 * @since 4.4
304 */
305class AKONADICORE_EXPORT EntityTreeModel : public QAbstractItemModel
306{
307 Q_OBJECT
308
309public:
310 /**
311 * Describes the roles for items. Roles for collections are defined by the superclass.
312 */
313 enum Roles {
314 // sebsauer, 2009-05-07; to be able here to keep the akonadi_next EntityTreeModel compatible with
315 // the akonadi_old ItemModel and CollectionModel, we need to use the same int-values for
316 // ItemRole, ItemIdRole and MimeTypeRole like the Akonadi::ItemModel is using and the same
317 // CollectionIdRole and CollectionRole like the Akonadi::CollectionModel is using.
318 ItemIdRole = Qt::UserRole + 1, ///< The item id
319 ItemRole = Qt::UserRole + 2, ///< The Item
320 MimeTypeRole = Qt::UserRole + 3, ///< The mimetype of the entity
321
322 CollectionIdRole = Qt::UserRole + 10, ///< The collection id.
323 CollectionRole = Qt::UserRole + 11, ///< The collection.
324
325 RemoteIdRole, ///< The remoteId of the entity
326 CollectionChildOrderRole, ///< Ordered list of child items if available
327 ParentCollectionRole, ///< The parent collection of the entity
328 ColumnCountRole, ///< @internal Used by proxies to determine the number of columns for a header group.
329 LoadedPartsRole, ///< Parts available in the model for the item
330 AvailablePartsRole, ///< Parts available in the Akonadi server for the item
331 SessionRole, ///< @internal The Session used by this model
332 CollectionRefRole, ///< @internal Used to increase the reference count on a Collection
333 CollectionDerefRole, ///< @internal Used to decrease the reference count on a Collection
334 PendingCutRole, ///< Used to indicate items which are to be cut
335 EntityUrlRole, ///< The akonadi:/ Url of the entity as a string. Item urls will contain the mimetype.
336 UnreadCountRole, ///< Returns the number of unread items in a collection. @since 4.5
337 FetchStateRole, ///< Returns the FetchState of a particular item. @since 4.5
338 IsPopulatedRole, ///< Returns whether a Collection has been populated, i.e. whether its items have been fetched. @since 4.10
339 OriginalCollectionNameRole, ///< Returns original name for collection @since 4.14
340 DisplayNameRole, ///< Returns the same as Qt::DisplayRole
341 UserRole = Qt::UserRole + 500, ///< First role for user extensions.
342 TerminalUserRole = 2000, ///< Last role for user extensions. Don't use a role beyond this or headerData will break.
343 EndRole = 65535
344 };
345
346 /**
347 * Describes the state of fetch jobs related to particular collections.
348 *
349 * @code
350 * QModelIndex collectionIndex = getIndex();
351 * if (collectionIndex.data(EntityTreeModel::FetchStateRole).toLongLong() == FetchingState) {
352 * // There is a fetch underway
353 * } else {
354 * // There is no fetch underway.
355 * }
356 * @endcode
357 *
358 * @since 4.5
359 */
361 IdleState, ///< There is no fetch of items in this collection in progress.
362 FetchingState ///< There is a fetch of items in this collection in progress.
363 // TODO: Change states for reporting of fetching payload parts of items.
364 };
365 Q_ENUM(FetchState)
366
367 /**
368 * Describes what header information the model shall return.
369 */
371 EntityTreeHeaders, ///< Header information for a tree with collections and items
372 CollectionTreeHeaders, ///< Header information for a collection-only tree
373 ItemListHeaders, ///< Header information for a list of items
374 UserHeaders = 10, ///< Last header information for submodel extensions
375 EndHeaderGroup = 32 ///< Last headergroup role. Don't use a role beyond this or headerData will break.
376 // Note that we're splitting up available roles for the header data hack and int(EndRole / TerminalUserRole) == 32
377 };
378
379 /**
380 * Creates a new entity tree model.
381 *
382 * @param monitor The Monitor whose entities should be represented in the model.
383 * @param parent The parent object.
384 */
385 explicit EntityTreeModel(Monitor *monitor, QObject *parent = nullptr);
386
387 /**
388 * Destroys the entity tree model.
389 */
390 ~EntityTreeModel() override;
391
392 /**
393 * Describes how the model should populated its items.
394 */
396 NoItemPopulation, ///< Do not include items in the model.
397 ImmediatePopulation, ///< Retrieve items immediately when their parent is in the model. This is the default.
398 LazyPopulation ///< Fetch items only when requested (using canFetchMore/fetchMore)
399 };
400
401 /**
402 * Some Entities are hidden in the model, but exist for internal purposes, for example, custom object
403 * directories in groupware resources.
404 * They are hidden by default, but can be shown by setting @p show to true.
405 * @param show enabled displaying of hidden entities if set as @c true
406 * Most applications will not need to use this feature.
407 */
408 void setShowSystemEntities(bool show);
409
410 /**
411 * Returns @c true if internal system entities are shown, and @c false otherwise.
412 */
413 [[nodiscard]] bool systemEntitiesShown() const;
414
415 /**
416 * Returns the currently used listfilter.
417 *
418 * @since 4.14
419 */
420 [[nodiscard]] Akonadi::CollectionFetchScope::ListFilter listFilter() const;
421
422 /**
423 * Sets the currently used listfilter.
424 *
425 * @since 4.14
426 */
427 void setListFilter(Akonadi::CollectionFetchScope::ListFilter filter);
428
429 /**
430 * Monitors the specified collections and resets the model.
431 *
432 * @since 4.14
433 */
434 void setCollectionsMonitored(const Akonadi::Collection::List &collections);
435
436 /**
437 * Adds or removes a specific collection from the monitored set without resetting the model.
438 * Only call this if you're monitoring specific collections (not mimetype/resources/items).
439 *
440 * @since 4.14
441 * @see setCollectionsMonitored()
442 */
443 void setCollectionMonitored(const Akonadi::Collection &col, bool monitored = true);
444
445 /**
446 * Sets the item population @p strategy of the model.
447 */
448 void setItemPopulationStrategy(ItemPopulationStrategy strategy);
449
450 /**
451 * Returns the item population strategy of the model.
452 */
453 [[nodiscard]] ItemPopulationStrategy itemPopulationStrategy() const;
454
455 /**
456 * Sets whether the root collection shall be provided by the model.
457 * @param include enables root collection if set as @c true
458 * @see setRootCollectionDisplayName()
459 */
460 void setIncludeRootCollection(bool include);
461
462 /**
463 * Returns whether the root collection is provided by the model.
464 */
465 [[nodiscard]] bool includeRootCollection() const;
466
467 /**
468 * Sets the display @p name of the root collection of the model.
469 * The default display name is "[*]".
470 * @param name the name to display for the root collection
471 * @note The display name for the root collection is only used if
472 * the root collection has been included with setIncludeRootCollection().
473 */
474 void setRootCollectionDisplayName(const QString &name);
475
476 /**
477 * Returns the display name of the root collection.
478 */
479 [[nodiscard]] QString rootCollectionDisplayName() const;
480
481 /**
482 * Describes what collections shall be fetched by and represent in the model.
483 */
485 FetchNoCollections, ///< Fetches nothing. This creates an empty model.
486 FetchFirstLevelChildCollections, ///< Fetches first level collections in the root collection.
487 FetchCollectionsRecursive, ///< Fetches collections in the root collection recursively. This is the default.
488 InvisibleCollectionFetch ///< Fetches collections, but does not put them in the model. This can be used to create a list of items in all collections.
489 ///< The ParentCollectionRole can still be used to retrieve the parent collection of an Item. @since 4.5
490 };
491
492 /**
493 * Sets the collection fetch @p strategy of the model.
494 */
495 void setCollectionFetchStrategy(CollectionFetchStrategy strategy);
496
497 /**
498 * Returns the collection fetch strategy of the model.
499 */
500 [[nodiscard]] CollectionFetchStrategy collectionFetchStrategy() const;
501
502 [[nodiscard]] QHash<int, QByteArray> roleNames() const override;
503
504 [[nodiscard]] int columnCount(const QModelIndex &parent = QModelIndex()) const override;
505 [[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override;
506
507 [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
508 [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
509
510 [[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override;
511 [[nodiscard]] QStringList mimeTypes() const override;
512
513 [[nodiscard]] Qt::DropActions supportedDropActions() const override;
514 [[nodiscard]] QMimeData *mimeData(const QModelIndexList &indexes) const override;
515 bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
516 bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
517
518 [[nodiscard]] QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
519 [[nodiscard]] QModelIndex parent(const QModelIndex &index) const override;
520
521 // TODO: Review the implementations of these. I think they could be better.
522 [[nodiscard]] bool canFetchMore(const QModelIndex &parent) const override;
523 void fetchMore(const QModelIndex &parent) override;
524 [[nodiscard]] bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
525
526 /**
527 * Returns whether the collection tree has been fetched at initialisation.
528 *
529 * @see collectionTreeFetched
530 * @since 4.10
531 */
532 [[nodiscard]] bool isCollectionTreeFetched() const;
533
534 /**
535 * Returns whether the collection has been populated.
536 *
537 * @see collectionPopulated
538 * @since 4.12
539 */
540 [[nodiscard]] bool isCollectionPopulated(Akonadi::Collection::Id) const;
541
542 /**
543 * Returns whether the model is fully populated.
544 *
545 * Returns true once the collection tree has been fetched and all collections have been populated.
546 *
547 * @see isCollectionPopulated
548 * @see isCollectionTreeFetched
549 * @since 4.14
550 */
551 [[nodiscard]] bool isFullyPopulated() const;
552
553 /**
554 * Reimplemented to handle the AmazingCompletionRole.
555 */
556 [[nodiscard]] QModelIndexList match(const QModelIndex &start,
557 int role,
558 const QVariant &value,
559 int hits = 1,
561
562 /**
563 * Returns a QModelIndex in @p model which points to @p collection.
564 * This method can be used through proxy models if @p model is a proxy model.
565 * @code
566 * EntityTreeModel *model = getEntityTreeModel();
567 * QSortFilterProxyModel *proxy1 = new QSortFilterProxyModel;
568 * proxy1->setSourceModel(model);
569 * QSortFilterProxyModel *proxy2 = new QSortFilterProxyModel;
570 * proxy2->setSourceModel(proxy1);
571 *
572 * ...
573 *
574 * QModelIndex idx = EntityTreeModel::modelIndexForCollection(proxy2, Collection(colId));
575 * if (!idx.isValid())
576 * // Collection with id colId is not in the proxy2.
577 * // Maybe it is filtered out if proxy 2 is only showing items? Make sure you use the correct proxy.
578 * return;
579 *
580 * Collection collection = idx.data( EntityTreeModel::CollectionRole ).value<Collection>();
581 * // collection has the id colId, and all other attributes already fetched by the model such as name, remoteId, Akonadi::Attributes etc.
582 *
583 * @endcode
584 *
585 * This can be useful for example if an id is stored in a config file and needs to be used in the application.
586 *
587 * Note however, that to restore view state such as scrolling, selection and expansion of items in trees, the ETMViewStateSaver can be used for convenience.
588 *
589 * @see modelIndexesForItem
590 * @since 4.5
591 */
592 static QModelIndex modelIndexForCollection(const QAbstractItemModel *model, const Collection &collection);
593
594 /**
595 * Returns a QModelIndex in @p model which points to @p item.
596 * This method can be used through proxy models if @p model is a proxy model.
597 * @param model the model to query for the item
598 * @param item the item to look for
599 * @see modelIndexForCollection
600 * @since 4.5
601 */
602 static QModelIndexList modelIndexesForItem(const QAbstractItemModel *model, const Item &item);
603
604 /**
605 * Returns an Akonadi::Collection from the @p model based on given @p collectionId.
606 *
607 * This is faster and simpler than retrieving a full Collection from the ETM
608 * by using modelIndexForCollection() and then querying for the index data.
609 */
610 static Collection updatedCollection(const QAbstractItemModel *model, qint64 collectionId);
611 static Collection updatedCollection(const QAbstractItemModel *model, const Collection &col);
612
613Q_SIGNALS:
614 /**
615 * Signal emitted when the collection tree has been fetched for the first time.
616 * @param collections list of collections which have been fetched
617 *
618 * @see isCollectionTreeFetched, collectionPopulated
619 * @since 4.10
620 */
622
623 /**
624 * Signal emitted when a collection has been populated, i.e. its items have been fetched.
625 * @param collectionId id of the collection which has been populated
626 *
627 * @see collectionTreeFetched
628 * @since 4.10
629 */
631 /**
632 * Emitted once a collection has been fetched for the very first time.
633 * This is like a dataChanged(), but specific to the initial loading, in order to update
634 * the GUI (window caption, state of actions).
635 * Usually, the GUI uses Akonadi::Monitor to be notified of further changes to the collections.
636 * @param collectionId the identifier of the fetched collection
637 * @since 4.9.3
638 */
639 void collectionFetched(int collectionId);
640
641protected:
642 /**
643 * Clears and resets the model. Always call this instead of the reset method in the superclass.
644 * Using the reset method will not reliably clear or refill the model.
645 */
646 void clearAndReset();
647
648 /**
649 * Provided for convenience of subclasses.
650 */
651 virtual QVariant entityData(const Item &item, int column, int role = Qt::DisplayRole) const;
652
653 /**
654 * Provided for convenience of subclasses.
655 */
656 virtual QVariant entityData(const Collection &collection, int column, int role = Qt::DisplayRole) const;
657
658 /**
659 * Reimplement this to provide different header data. This is needed when using one model
660 * with multiple proxies and views, and each should show different header data.
661 */
662 virtual QVariant entityHeaderData(int section, Qt::Orientation orientation, int role, HeaderGroup headerGroup) const;
663
664 virtual int entityColumnCount(HeaderGroup headerGroup) const;
665
666protected:
667 /// @cond PRIVATE
668 Q_DECLARE_PRIVATE(EntityTreeModel)
669 std::unique_ptr<EntityTreeModelPrivate> const d_ptr;
670 EntityTreeModel(Monitor *monitor, EntityTreeModelPrivate *d, QObject *parent = nullptr);
671 /// @endcond
672
673private:
674 /// @cond PRIVATE
675 // Make these private, they shouldn't be called by applications
676 bool insertRows(int row, int count, const QModelIndex &index = QModelIndex()) override;
677 bool insertColumns(int column, int count, const QModelIndex &index = QModelIndex()) override;
678 bool removeColumns(int column, int count, const QModelIndex &index = QModelIndex()) override;
679 bool removeRows(int row, int count, const QModelIndex &index = QModelIndex()) override;
680
681 Q_PRIVATE_SLOT(d_func(), void monitoredCollectionStatisticsChanged(Akonadi::Collection::Id, const Akonadi::CollectionStatistics &))
682
683 Q_PRIVATE_SLOT(d_func(), void startFirstListJob())
684 Q_PRIVATE_SLOT(d_func(), void serverStarted())
685
686 Q_PRIVATE_SLOT(d_func(), void collectionFetchJobDone(KJob *job))
687 Q_PRIVATE_SLOT(d_func(), void rootFetchJobDone(KJob *job))
688 Q_PRIVATE_SLOT(d_func(), void pasteJobDone(KJob *job))
689 Q_PRIVATE_SLOT(d_func(), void updateJobDone(KJob *job))
690
691 Q_PRIVATE_SLOT(d_func(), void itemsFetched(const Akonadi::Item::List &))
692 Q_PRIVATE_SLOT(d_func(), void collectionsFetched(Akonadi::Collection::List))
693 Q_PRIVATE_SLOT(d_func(), void topLevelCollectionsFetched(Akonadi::Collection::List))
694 Q_PRIVATE_SLOT(d_func(), void ancestorsFetched(Akonadi::Collection::List))
695
696 Q_PRIVATE_SLOT(d_func(), void monitoredMimeTypeChanged(const QString &, bool))
697 Q_PRIVATE_SLOT(d_func(), void monitoredCollectionsChanged(const Akonadi::Collection &, bool))
698 Q_PRIVATE_SLOT(d_func(), void monitoredItemsChanged(const Akonadi::Item &, bool))
699 Q_PRIVATE_SLOT(d_func(), void monitoredResourcesChanged(const QByteArray &, bool))
700
701 Q_PRIVATE_SLOT(d_func(), void monitoredCollectionAdded(const Akonadi::Collection &, const Akonadi::Collection &))
702 Q_PRIVATE_SLOT(d_func(), void monitoredCollectionRemoved(const Akonadi::Collection &))
703 Q_PRIVATE_SLOT(d_func(), void monitoredCollectionChanged(const Akonadi::Collection &))
704 Q_PRIVATE_SLOT(d_func(), void monitoredCollectionMoved(const Akonadi::Collection &, const Akonadi::Collection &, const Akonadi::Collection &))
705
706 Q_PRIVATE_SLOT(d_func(), void monitoredItemAdded(const Akonadi::Item &, const Akonadi::Collection &))
707 Q_PRIVATE_SLOT(d_func(), void monitoredItemRemoved(const Akonadi::Item &))
708 Q_PRIVATE_SLOT(d_func(), void monitoredItemChanged(const Akonadi::Item &, const QSet<QByteArray> &))
709 Q_PRIVATE_SLOT(d_func(), void monitoredItemMoved(const Akonadi::Item &, const Akonadi::Collection &, const Akonadi::Collection &))
710
711 Q_PRIVATE_SLOT(d_func(), void monitoredItemLinked(const Akonadi::Item &, const Akonadi::Collection &))
712 Q_PRIVATE_SLOT(d_func(), void monitoredItemUnlinked(const Akonadi::Item &, const Akonadi::Collection &))
713 Q_PRIVATE_SLOT(d_func(), void changeFetchState(const Akonadi::Collection &))
714
715 Q_PRIVATE_SLOT(d_func(), void agentInstanceRemoved(Akonadi::AgentInstance))
716 Q_PRIVATE_SLOT(d_func(), void monitoredItemsRetrieved(KJob *job))
717 /// @endcond
718};
719
720} // namespace
A representation of an agent instance.
ListFilter
Describes the list filter.
Provides statistics information of a Collection.
Represents a collection of PIM items.
Definition collection.h:62
qint64 Id
Describes the unique id type.
Definition collection.h:79
A model for collections and items together.
ItemPopulationStrategy
Describes how the model should populated its items.
@ ImmediatePopulation
Retrieve items immediately when their parent is in the model. This is the default.
@ NoItemPopulation
Do not include items in the model.
void collectionTreeFetched(const Akonadi::Collection::List &collections)
Signal emitted when the collection tree has been fetched for the first time.
FetchState
Describes the state of fetch jobs related to particular collections.
@ IdleState
There is no fetch of items in this collection in progress.
HeaderGroup
Describes what header information the model shall return.
@ CollectionTreeHeaders
Header information for a collection-only tree.
@ ItemListHeaders
Header information for a list of items.
@ EntityTreeHeaders
Header information for a tree with collections and items.
void collectionFetched(int collectionId)
Emitted once a collection has been fetched for the very first time.
CollectionFetchStrategy
Describes what collections shall be fetched by and represent in the model.
@ FetchNoCollections
Fetches nothing. This creates an empty model.
@ FetchFirstLevelChildCollections
Fetches first level collections in the root collection.
@ FetchCollectionsRecursive
Fetches collections in the root collection recursively. This is the default.
void collectionPopulated(Akonadi::Collection::Id collectionId)
Signal emitted when a collection has been populated, i.e.
Roles
Describes the roles for items.
@ AvailablePartsRole
Parts available in the Akonadi server for the item.
@ ParentCollectionRole
The parent collection of the entity.
@ LoadedPartsRole
Parts available in the model for the item.
@ RemoteIdRole
The remoteId of the entity.
@ OriginalCollectionNameRole
Returns original name for collection.
@ EntityUrlRole
The akonadi:/ Url of the entity as a string. Item urls will contain the mimetype.
@ PendingCutRole
Used to indicate items which are to be cut.
@ DisplayNameRole
Returns the same as Qt::DisplayRole.
@ UnreadCountRole
Returns the number of unread items in a collection.
@ IsPopulatedRole
Returns whether a Collection has been populated, i.e. whether its items have been fetched.
@ CollectionChildOrderRole
Ordered list of child items if available.
@ FetchStateRole
Returns the FetchState of a particular item.
Represents a PIM item stored in Akonadi storage.
Definition item.h:101
Monitors an item or collection for changes.
Definition monitor.h:72
ASAP CLI session.
Q_SCRIPTABLE Q_NOREPLY void start()
Helper integration between Akonadi and Qt.
typedef DropActions
UserRole
typedef ItemFlags
typedef MatchFlags
Orientation
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 14 2024 11:51:45 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.