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

KDE's Doxygen guidelines are available online.