Akonadi

entitytreemodel.h
1 /*
2  SPDX-FileCopyrightText: 2008 Stephen Kelly <[email protected]>
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 
19 namespace Akonadi
20 {
21 class CollectionStatistics;
22 class Item;
23 class ItemFetchScope;
24 class Monitor;
25 class Session;
26 
27 class 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  * Monitor *monitor = new Monitor( this );
76  * monitor->setCollectionMonitored( Collection::root() );
77  * monitor->setMimeTypeMonitored( KContacts::Addressee::mimeType() );
78  * monitor->setSession( session );
79  *
80  * EntityTreeModel *model = new EntityTreeModel( monitor, this );
81  *
82  * EntityTreeView *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 KMail4.5 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  * SelectionProxyModel *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  * EntityTreeView *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  * 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  * SelectionProxyModel *selProxy = new SelectionProxyModel( treeview->selectionModel(), this );
224  * selProxy->setSourceModel( entityTreeModel );
225  *
226  * descendedList = new KDescendantsProxyModel( this );
227  * descendedList->setSourceModel( selProxy );
228  *
229  * 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 <[email protected]>
303  * @since 4.4
304  */
305 class AKONADICORE_EXPORT EntityTreeModel : public QAbstractItemModel
306 {
307  Q_OBJECT
308 
309 public:
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  UserRole = Qt::UserRole + 500, ///< First role for user extensions.
341  TerminalUserRole = 2000, ///< Last role for user extensions. Don't use a role beyond this or headerData will break.
342  EndRole = 65535
343  };
344 
345  /**
346  * Describes the state of fetch jobs related to particular collections.
347  *
348  * @code
349  * QModelIndex collectionIndex = getIndex();
350  * if (collectionIndex.data(EntityTreeModel::FetchStateRole).toLongLong() == FetchingState) {
351  * // There is a fetch underway
352  * } else {
353  * // There is no fetch underway.
354  * }
355  * @endcode
356  *
357  * @since 4.5
358  */
359  enum FetchState {
360  IdleState, ///< There is no fetch of items in this collection in progress.
361  FetchingState ///< There is a fetch of items in this collection in progress.
362  // TODO: Change states for reporting of fetching payload parts of items.
363  };
364 
365  /**
366  * Describes what header information the model shall return.
367  */
368  enum HeaderGroup {
369  EntityTreeHeaders, ///< Header information for a tree with collections and items
370  CollectionTreeHeaders, ///< Header information for a collection-only tree
371  ItemListHeaders, ///< Header information for a list of items
372  UserHeaders = 10, ///< Last header information for submodel extensions
373  EndHeaderGroup = 32 ///< Last headergroup role. Don't use a role beyond this or headerData will break.
374  // Note that we're splitting up available roles for the header data hack and int(EndRole / TerminalUserRole) == 32
375  };
376 
377  /**
378  * Creates a new entity tree model.
379  *
380  * @param monitor The Monitor whose entities should be represented in the model.
381  * @param parent The parent object.
382  */
383  explicit EntityTreeModel(Monitor *monitor, QObject *parent = nullptr);
384 
385  /**
386  * Destroys the entity tree model.
387  */
388  ~EntityTreeModel() override;
389 
390  /**
391  * Describes how the model should populated its items.
392  */
394  NoItemPopulation, ///< Do not include items in the model.
395  ImmediatePopulation, ///< Retrieve items immediately when their parent is in the model. This is the default.
396  LazyPopulation ///< Fetch items only when requested (using canFetchMore/fetchMore)
397  };
398 
399  /**
400  * Some Entities are hidden in the model, but exist for internal purposes, for example, custom object
401  * directories in groupware resources.
402  * They are hidden by default, but can be shown by setting @p show to true.
403  * @param show enabled displaying of hidden entities if set as @c true
404  * Most applications will not need to use this feature.
405  */
406  void setShowSystemEntities(bool show);
407 
408  /**
409  * Returns @c true if internal system entities are shown, and @c false otherwise.
410  */
411  Q_REQUIRED_RESULT bool systemEntitiesShown() const;
412 
413  /**
414  * Returns the currently used listfilter.
415  *
416  * @since 4.14
417  */
418  Q_REQUIRED_RESULT Akonadi::CollectionFetchScope::ListFilter listFilter() const;
419 
420  /**
421  * Sets the currently used listfilter.
422  *
423  * @since 4.14
424  */
425  void setListFilter(Akonadi::CollectionFetchScope::ListFilter filter);
426 
427  /**
428  * Monitors the specified collections and resets the model.
429  *
430  * @since 4.14
431  */
432  void setCollectionsMonitored(const Akonadi::Collection::List &collections);
433 
434  /**
435  * Adds or removes a specific collection from the monitored set without resetting the model.
436  * Only call this if you're monitoring specific collections (not mimetype/resources/items).
437  *
438  * @since 4.14
439  * @see setCollectionsMonitored()
440  */
441  void setCollectionMonitored(const Akonadi::Collection &col, bool monitored = true);
442 
443  /**
444  * Sets the item population @p strategy of the model.
445  */
446  void setItemPopulationStrategy(ItemPopulationStrategy strategy);
447 
448  /**
449  * Returns the item population strategy of the model.
450  */
451  Q_REQUIRED_RESULT ItemPopulationStrategy itemPopulationStrategy() const;
452 
453  /**
454  * Sets whether the root collection shall be provided by the model.
455  * @param include enables root collection if set as @c true
456  * @see setRootCollectionDisplayName()
457  */
458  void setIncludeRootCollection(bool include);
459 
460  /**
461  * Returns whether the root collection is provided by the model.
462  */
463  Q_REQUIRED_RESULT bool includeRootCollection() const;
464 
465  /**
466  * Sets the display @p name of the root collection of the model.
467  * The default display name is "[*]".
468  * @param name the name to display for the root collection
469  * @note The display name for the root collection is only used if
470  * the root collection has been included with setIncludeRootCollection().
471  */
472  void setRootCollectionDisplayName(const QString &name);
473 
474  /**
475  * Returns the display name of the root collection.
476  */
477  Q_REQUIRED_RESULT QString rootCollectionDisplayName() const;
478 
479  /**
480  * Describes what collections shall be fetched by and represent in the model.
481  */
483  FetchNoCollections, ///< Fetches nothing. This creates an empty model.
484  FetchFirstLevelChildCollections, ///< Fetches first level collections in the root collection.
485  FetchCollectionsRecursive, ///< Fetches collections in the root collection recursively. This is the default.
486  InvisibleCollectionFetch ///< Fetches collections, but does not put them in the model. This can be used to create a list of items in all collections.
487  ///< The ParentCollectionRole can still be used to retrieve the parent collection of an Item. @since 4.5
488  };
489 
490  /**
491  * Sets the collection fetch @p strategy of the model.
492  */
493  void setCollectionFetchStrategy(CollectionFetchStrategy strategy);
494 
495  /**
496  * Returns the collection fetch strategy of the model.
497  */
498  Q_REQUIRED_RESULT CollectionFetchStrategy collectionFetchStrategy() const;
499 
500  Q_REQUIRED_RESULT QHash<int, QByteArray> roleNames() const override;
501 
502  Q_REQUIRED_RESULT int columnCount(const QModelIndex &parent = QModelIndex()) const override;
503  Q_REQUIRED_RESULT int rowCount(const QModelIndex &parent = QModelIndex()) const override;
504 
505  Q_REQUIRED_RESULT QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
506  Q_REQUIRED_RESULT QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
507 
508  Q_REQUIRED_RESULT Qt::ItemFlags flags(const QModelIndex &index) const override;
509  Q_REQUIRED_RESULT QStringList mimeTypes() const override;
510 
511  Q_REQUIRED_RESULT Qt::DropActions supportedDropActions() const override;
512  Q_REQUIRED_RESULT QMimeData *mimeData(const QModelIndexList &indexes) const override;
513  bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
514  bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
515 
516  Q_REQUIRED_RESULT QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
517  Q_REQUIRED_RESULT QModelIndex parent(const QModelIndex &index) const override;
518 
519  // TODO: Review the implementations of these. I think they could be better.
520  Q_REQUIRED_RESULT bool canFetchMore(const QModelIndex &parent) const override;
521  void fetchMore(const QModelIndex &parent) override;
522  Q_REQUIRED_RESULT bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
523 
524  /**
525  * Returns whether the collection tree has been fetched at initialisation.
526  *
527  * @see collectionTreeFetched
528  * @since 4.10
529  */
530  Q_REQUIRED_RESULT bool isCollectionTreeFetched() const;
531 
532  /**
533  * Returns whether the collection has been populated.
534  *
535  * @see collectionPopulated
536  * @since 4.12
537  */
538  Q_REQUIRED_RESULT bool isCollectionPopulated(Akonadi::Collection::Id) const;
539 
540  /**
541  * Returns whether the model is fully populated.
542  *
543  * Returns true once the collection tree has been fetched and all collections have been populated.
544  *
545  * @see isCollectionPopulated
546  * @see isCollectionTreeFetched
547  * @since 4.14
548  */
549  Q_REQUIRED_RESULT bool isFullyPopulated() const;
550 
551  /**
552  * Reimplemented to handle the AmazingCompletionRole.
553  */
554  Q_REQUIRED_RESULT QModelIndexList match(const QModelIndex &start,
555  int role,
556  const QVariant &value,
557  int hits = 1,
559 
560  /**
561  * Returns a QModelIndex in @p model which points to @p collection.
562  * This method can be used through proxy models if @p model is a proxy model.
563  * @code
564  * EntityTreeModel *model = getEntityTreeModel();
565  * QSortFilterProxyModel *proxy1 = new QSortFilterProxyModel;
566  * proxy1->setSourceModel(model);
567  * QSortFilterProxyModel *proxy2 = new QSortFilterProxyModel;
568  * proxy2->setSourceModel(proxy1);
569  *
570  * ...
571  *
572  * QModelIndex idx = EntityTreeModel::modelIndexForCollection(proxy2, Collection(colId));
573  * if (!idx.isValid())
574  * // Collection with id colId is not in the proxy2.
575  * // Maybe it is filtered out if proxy 2 is only showing items? Make sure you use the correct proxy.
576  * return;
577  *
578  * Collection collection = idx.data( EntityTreeModel::CollectionRole ).value<Collection>();
579  * // collection has the id colId, and all other attributes already fetched by the model such as name, remoteId, Akonadi::Attributes etc.
580  *
581  * @endcode
582  *
583  * This can be useful for example if an id is stored in a config file and needs to be used in the application.
584  *
585  * Note however, that to restore view state such as scrolling, selection and expansion of items in trees, the ETMViewStateSaver can be used for convenience.
586  *
587  * @see modelIndexesForItem
588  * @since 4.5
589  */
590  static QModelIndex modelIndexForCollection(const QAbstractItemModel *model, const Collection &collection);
591 
592  /**
593  * Returns a QModelIndex in @p model which points to @p item.
594  * This method can be used through proxy models if @p model is a proxy model.
595  * @param model the model to query for the item
596  * @param item the item to look for
597  * @see modelIndexForCollection
598  * @since 4.5
599  */
600  static QModelIndexList modelIndexesForItem(const QAbstractItemModel *model, const Item &item);
601 
602  /**
603  * Returns an Akonadi::Collection from the @p model based on given @p collectionId.
604  *
605  * This is faster and simpler than retrieving a full Collection from the ETM
606  * by using modelIndexForCollection() and then querying for the index data.
607  */
608  static Collection updatedCollection(const QAbstractItemModel *model, qint64 collectionId);
609  static Collection updatedCollection(const QAbstractItemModel *model, const Collection &col);
610 
611 Q_SIGNALS:
612  /**
613  * Signal emitted when the collection tree has been fetched for the first time.
614  * @param collections list of collections which have been fetched
615  *
616  * @see isCollectionTreeFetched, collectionPopulated
617  * @since 4.10
618  */
619  void collectionTreeFetched(const Akonadi::Collection::List &collections);
620 
621  /**
622  * Signal emitted when a collection has been populated, i.e. its items have been fetched.
623  * @param collectionId id of the collection which has been populated
624  *
625  * @see collectionTreeFetched
626  * @since 4.10
627  */
628  void collectionPopulated(Akonadi::Collection::Id collectionId);
629  /**
630  * Emitted once a collection has been fetched for the very first time.
631  * This is like a dataChanged(), but specific to the initial loading, in order to update
632  * the GUI (window caption, state of actions).
633  * Usually, the GUI uses Akonadi::Monitor to be notified of further changes to the collections.
634  * @param collectionId the identifier of the fetched collection
635  * @since 4.9.3
636  */
637  void collectionFetched(int collectionId);
638 
639 protected:
640  /**
641  * Clears and resets the model. Always call this instead of the reset method in the superclass.
642  * Using the reset method will not reliably clear or refill the model.
643  */
644  void clearAndReset();
645 
646  /**
647  * Provided for convenience of subclasses.
648  */
649  virtual QVariant entityData(const Item &item, int column, int role = Qt::DisplayRole) const;
650 
651  /**
652  * Provided for convenience of subclasses.
653  */
654  virtual QVariant entityData(const Collection &collection, int column, int role = Qt::DisplayRole) const;
655 
656  /**
657  * Reimplement this to provide different header data. This is needed when using one model
658  * with multiple proxies and views, and each should show different header data.
659  */
660  virtual QVariant entityHeaderData(int section, Qt::Orientation orientation, int role, HeaderGroup headerGroup) const;
661 
662  virtual int entityColumnCount(HeaderGroup headerGroup) const;
663 
664 protected:
665  /// @cond PRIVATE
666  Q_DECLARE_PRIVATE(EntityTreeModel)
667  std::unique_ptr<EntityTreeModelPrivate> const d_ptr;
668  EntityTreeModel(Monitor *monitor, EntityTreeModelPrivate *d, QObject *parent = nullptr);
669  /// @endcond
670 
671 private:
672  /// @cond PRIVATE
673  // Make these private, they shouldn't be called by applications
674  bool insertRows(int row, int count, const QModelIndex &index = QModelIndex()) override;
675  bool insertColumns(int column, int count, const QModelIndex &index = QModelIndex()) override;
676  bool removeColumns(int column, int count, const QModelIndex &index = QModelIndex()) override;
677  bool removeRows(int row, int count, const QModelIndex &index = QModelIndex()) override;
678 
679  Q_PRIVATE_SLOT(d_func(), void monitoredCollectionStatisticsChanged(Akonadi::Collection::Id, const Akonadi::CollectionStatistics &))
680 
681  Q_PRIVATE_SLOT(d_func(), void startFirstListJob())
682  Q_PRIVATE_SLOT(d_func(), void serverStarted())
683 
684  Q_PRIVATE_SLOT(d_func(), void collectionFetchJobDone(KJob *job))
685  Q_PRIVATE_SLOT(d_func(), void rootFetchJobDone(KJob *job))
686  Q_PRIVATE_SLOT(d_func(), void pasteJobDone(KJob *job))
687  Q_PRIVATE_SLOT(d_func(), void updateJobDone(KJob *job))
688 
689  Q_PRIVATE_SLOT(d_func(), void itemsFetched(const Akonadi::Item::List &))
690  Q_PRIVATE_SLOT(d_func(), void collectionsFetched(Akonadi::Collection::List))
691  Q_PRIVATE_SLOT(d_func(), void topLevelCollectionsFetched(Akonadi::Collection::List))
692  Q_PRIVATE_SLOT(d_func(), void ancestorsFetched(Akonadi::Collection::List))
693 
694  Q_PRIVATE_SLOT(d_func(), void monitoredMimeTypeChanged(const QString &, bool))
695  Q_PRIVATE_SLOT(d_func(), void monitoredCollectionsChanged(const Akonadi::Collection &, bool))
696  Q_PRIVATE_SLOT(d_func(), void monitoredItemsChanged(const Akonadi::Item &, bool))
697  Q_PRIVATE_SLOT(d_func(), void monitoredResourcesChanged(const QByteArray &, bool))
698 
699  Q_PRIVATE_SLOT(d_func(), void monitoredCollectionAdded(const Akonadi::Collection &, const Akonadi::Collection &))
700  Q_PRIVATE_SLOT(d_func(), void monitoredCollectionRemoved(const Akonadi::Collection &))
701  Q_PRIVATE_SLOT(d_func(), void monitoredCollectionChanged(const Akonadi::Collection &))
702  Q_PRIVATE_SLOT(d_func(), void monitoredCollectionMoved(const Akonadi::Collection &, const Akonadi::Collection &, const Akonadi::Collection &))
703 
704  Q_PRIVATE_SLOT(d_func(), void monitoredItemAdded(const Akonadi::Item &, const Akonadi::Collection &))
705  Q_PRIVATE_SLOT(d_func(), void monitoredItemRemoved(const Akonadi::Item &))
706  Q_PRIVATE_SLOT(d_func(), void monitoredItemChanged(const Akonadi::Item &, const QSet<QByteArray> &))
707  Q_PRIVATE_SLOT(d_func(), void monitoredItemMoved(const Akonadi::Item &, const Akonadi::Collection &, const Akonadi::Collection &))
708 
709  Q_PRIVATE_SLOT(d_func(), void monitoredItemLinked(const Akonadi::Item &, const Akonadi::Collection &))
710  Q_PRIVATE_SLOT(d_func(), void monitoredItemUnlinked(const Akonadi::Item &, const Akonadi::Collection &))
711  Q_PRIVATE_SLOT(d_func(), void changeFetchState(const Akonadi::Collection &))
712 
713  Q_PRIVATE_SLOT(d_func(), void agentInstanceRemoved(Akonadi::AgentInstance))
714  Q_PRIVATE_SLOT(d_func(), void monitoredItemsRetrieved(KJob *job))
715  /// @endcond
716 };
717 
718 } // namespace
719 
@ ItemListHeaders
Header information for a list of items.
@ IdleState
There is no fetch of items in this collection in progress.
Provides statistics information of a Collection.
A model for collections and items together.
UserRole
@ FetchFirstLevelChildCollections
Fetches first level collections in the root collection.
@ NoItemPopulation
Do not include items in the model.
@ LoadedPartsRole
Parts available in the model for the item.
@ EntityUrlRole
The akonadi:/ Url of the entity as a string. Item urls will contain the mimetype.
Q_SCRIPTABLE Q_NOREPLY void start()
FetchState
Describes the state of fetch jobs related to particular collections.
Represents a collection of PIM items.
Definition: collection.h:61
@ RemoteIdRole
The remoteId of the entity.
@ OriginalCollectionNameRole
Returns original name for collection.
Monitors an item or collection for changes.
Definition: monitor.h:71
ASAP CLI session.
@ CollectionTreeHeaders
Header information for a collection-only tree.
typedef ItemFlags
@ UnreadCountRole
Returns the number of unread items in a collection.
@ EntityTreeHeaders
Header information for a tree with collections and items.
@ FetchCollectionsRecursive
Fetches collections in the root collection recursively. This is the default.
ListFilter
Describes the list filter.
Orientation
@ FetchNoCollections
Fetches nothing. This creates an empty model.
@ CollectionChildOrderRole
Ordered list of child items if available.
ItemPopulationStrategy
Describes how the model should populated its items.
@ AvailablePartsRole
Parts available in the Akonadi server for the item.
@ PendingCutRole
Used to indicate items which are to be cut.
typedef DropActions
@ IsPopulatedRole
Returns whether a Collection has been populated, i.e. whether its items have been fetched.
@ ImmediatePopulation
Retrieve items immediately when their parent is in the model. This is the default.
Roles
Describes the roles for items.
@ FetchStateRole
Returns the FetchState of a particular item.
typedef MatchFlags
HeaderGroup
Describes what header information the model shall return.
@ ParentCollectionRole
The parent collection of the entity.
CollectionFetchStrategy
Describes what collections shall be fetched by and represent in the model.
A representation of an agent instance.
qint64 Id
Describes the unique id type.
Definition: collection.h:79
Represents a PIM item stored in Akonadi storage.
Definition: item.h:104
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jun 30 2022 03:51:46 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.