1/*
2 Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#ifndef AKONADI_MONITOR_H
21#define AKONADI_MONITOR_H
22
23#include <akonadi/tag.h>
24#include <akonadi/collection.h>
25#include <akonadi/item.h>
26
27#include <QtCore/QObject>
28
29namespace Akonadi {
30
31class CollectionFetchScope;
32class CollectionStatistics;
33class Item;
34class ItemFetchScope;
35class MonitorPrivate;
36class Session;
37class TagFetchScope;
38
39/**
40 * @short Monitors an item or collection for changes.
41 *
42 * The Monitor emits signals if some of these objects are changed or
43 * removed or new ones are added to the Akonadi storage.
44 *
45 * There are various ways to filter these notifications. There are three types of filter
46 * evaluation:
47 * - (-) removal-only filter, ie. if the filter matches the notification is dropped,
48 * if not filter evaluation continues with the next one
49 * - (+) pass-exit filter, ie. if the filter matches the notification is delivered,
50 * if not evaluation is continued
51 * - (f) final filter, ie. evaluation ends here if the corresponding filter criteria is set,
52 * the notification is delievered depending on the result, evaluation is only continued
53 * if no filter criteria is defined
54 *
55 * The following filter are available, listed in evaluation order:
56 * (1) ignored sessions (-)
57 * (2) monitor everything (+)
58 * (3a) resource and mimetype filters (f) (items only)
59 * (3b) resource filters (f) (collections only)
60 * (4) item is monitored (+)
61 * (5) collection is monitored (+)
62 *
63 * Optionally, the changed objects can be fetched automatically from the server.
64 * To enable this, see itemFetchScope() and collectionFetchScope().
65 *
66 * Note that as a consequence of rule 3a, it is not possible to monitor (more than zero resources
67 * OR more than zero mimetypes) AND more than zero collections.
68 *
69 * @todo Distinguish between monitoring collection properties and collection content.
70 * @todo Special case for collection content counts changed
71 *
72 * @author Volker Krause <vkrause@kde.org>
73 */
74class AKONADI_EXPORT Monitor : public QObject
75{
76 Q_OBJECT
77
78public:
79 enum Type {
80 /**
81 * @internal This must be kept in sync with Akonadi::NotificationMessageV2::Type
82 */
83 Collections = 1,
84 Items,
85 Tags
86 };
87
88 /**
89 * Creates a new monitor.
90 *
91 * @param parent The parent object.
92 */
93 explicit Monitor(QObject *parent = 0);
94
95 /**
96 * Destroys the monitor.
97 */
98 virtual ~Monitor();
99
100 /**
101 * Sets whether the specified collection shall be monitored for changes. If
102 * monitoring is turned on for the collection, all notifications for items
103 * in that collection will be emitted, and its child collections will also
104 * be monitored. Note that move notifications will be emitted if either one
105 * of the collections involved is being monitored.
106 *
107 * Note that if a session is being ignored, this takes precedence over
108 * setCollectionMonitored() on that session.
109 *
110 * @param collection The collection to monitor.
111 * If this collection is Collection::root(), all collections
112 * in the Akonadi storage will be monitored.
113 * @param monitored Whether to monitor the collection.
114 */
115 void setCollectionMonitored(const Collection &collection, bool monitored = true);
116
117 /**
118 * Sets whether the specified item shall be monitored for changes.
119 *
120 * Note that if a session is being ignored, this takes precedence over
121 * setItemMonitored() on that session.
122 *
123 * @param item The item to monitor.
124 * @param monitored Whether to monitor the item.
125 */
126 void setItemMonitored(const Item &item, bool monitored = true);
127
128 /**
129 * Sets whether the specified resource shall be monitored for changes. If
130 * monitoring is turned on for the resource, all notifications for
131 * collections and items in that resource will be emitted.
132 *
133 * Note that if a session is being ignored, this takes precedence over
134 * setResourceMonitored() on that session.
135 *
136 * @param resource The resource identifier.
137 * @param monitored Whether to monitor the resource.
138 */
139 void setResourceMonitored(const QByteArray &resource, bool monitored = true);
140
141 /**
142 * Sets whether items of the specified mime type shall be monitored for changes.
143 * If monitoring is turned on for the mime type, all notifications for items
144 * matching that mime type will be emitted, but notifications for collections
145 * matching that mime type will only be emitted if this is otherwise specified,
146 * for example by setCollectionMonitored().
147 *
148 * Note that if a session is being ignored, this takes precedence over
149 * setMimeTypeMonitored() on that session.
150 *
151 * @param mimetype The mime type to monitor.
152 * @param monitored Whether to monitor the mime type.
153 */
154 void setMimeTypeMonitored(const QString &mimetype, bool monitored = true);
155
156 /**
157 * Sets whether the specified tag shall be monitored for changes.
158 *
159 * Same rules as for item monitoring apply.
160 *
161 * @param tag Tag to monitor.
162 * @param monitored Whether to monitor the tag.
163 * @since 4.13
164 */
165 void setTagMonitored(const Tag &tag, bool monitored = true);
166
167 /**
168 * Sets whether given type (Collection, Item, Tag should be monitored).
169 *
170 * By default all types are monitored, but once you change one, you have
171 * to explicitly enable all other types you want to monitor.
172 *
173 * @param type Type to monitor.
174 * @param monitored Whether to monitor the type
175 * @since 4.13
176 */
177 void setTypeMonitored(Type type, bool monitored = true);
178
179 /**
180 * Sets whether all items shall be monitored.
181 * @param monitored sets all items as monitored if set as @c true
182 * Note that if a session is being ignored, this takes precedence over
183 * setAllMonitored() on that session.
184 */
185 void setAllMonitored(bool monitored = true);
186
187 /**
188 * Ignores all change notifications caused by the given session. This
189 * overrides all other settings on this session.
190 *
191 * @param session The session you want to ignore.
192 */
193 void ignoreSession(Session *session);
194
195 /**
196 * Enables automatic fetching of changed collections from the Akonadi storage.
197 *
198 * @param enable @c true enables automatic fetching, @c false disables automatic fetching.
199 */
200 void fetchCollection(bool enable);
201
202 /**
203 * Enables automatic fetching of changed collection statistics information from
204 * the Akonadi storage.
205 *
206 * @param enable @c true to enables automatic fetching, @c false disables automatic fetching.
207 */
208 void fetchCollectionStatistics(bool enable);
209
210 /**
211 * Sets the item fetch scope.
212 *
213 * Controls how much of an item's data is fetched from the server, e.g.
214 * whether to fetch the full item payload or only meta data.
215 *
216 * @param fetchScope The new scope for item fetch operations.
217 *
218 * @see itemFetchScope()
219 */
220 void setItemFetchScope(const ItemFetchScope &fetchScope);
221
222 /**
223 * Instructs the monitor to fetch only those parts that were changed and
224 * were requested in the fetch scope.
225 *
226 * This is taken in account only for item modifications.
227 * Example usage:
228 * @code
229 * monitor->itemFetchScope().fetchFullPayload( true );
230 * monitor->fetchChangedOnly(true);
231 * @endcode
232 *
233 * In the example if an item was changed, but its payload was not, the full
234 * payload will not be retrieved.
235 * If the item's payload was changed, the monitor retrieves the changed
236 * payload as well.
237 *
238 * The default is to fetch everything requested.
239 *
240 * @since 4.8
241 *
242 * @param enable @c true to enable the feature, @c false means everything
243 * that was requested will be fetched.
244 * @return void
245 */
246 void fetchChangedOnly(bool enable);
247
248 /**
249 * Returns the item fetch scope.
250 *
251 * Since this returns a reference it can be used to conveniently modify the
252 * current scope in-place, i.e. by calling a method on the returned reference
253 * without storing it in a local variable. See the ItemFetchScope documentation
254 * for an example.
255 *
256 * @return a reference to the current item fetch scope
257 *
258 * @see setItemFetchScope() for replacing the current item fetch scope
259 */
260 ItemFetchScope &itemFetchScope();
261
262 /**
263 * Sets the collection fetch scope.
264 *
265 * Controls which collections are monitored and how much of a collection's data
266 * is fetched from the server.
267 *
268 * @param fetchScope The new scope for collection fetch operations.
269 *
270 * @see collectionFetchScope()
271 * @since 4.4
272 */
273 void setCollectionFetchScope(const CollectionFetchScope &fetchScope);
274
275 /**
276 * Returns the collection fetch scope.
277 *
278 * Since this returns a reference it can be used to conveniently modify the
279 * current scope in-place, i.e. by calling a method on the returned reference
280 * without storing it in a local variable. See the CollectionFetchScope documentation
281 * for an example.
282 *
283 * @return a reference to the current collection fetch scope
284 *
285 * @see setCollectionFetchScope() for replacing the current collection fetch scope
286 * @since 4.4
287 */
288 CollectionFetchScope &collectionFetchScope();
289
290 /**
291 * Sets the tag fetch scope.
292 *
293 * Controls how much of an tag's data is fetched from the server.
294 *
295 * @param fetchScope The new scope for tag fetch operations.
296 *
297 * @see tagFetchScope()
298 */
299 void setTagFetchScope(const TagFetchScope &fetchScope);
300
301 /**
302 * Returns the tag fetch scope.
303 *
304 * Since this returns a reference it can be used to conveniently modify the
305 * current scope in-place, i.e. by calling a method on the returned reference
306 * without storing it in a local variable.
307 *
308 * @return a reference to the current tag fetch scope
309 *
310 * @see setTagFetchScope() for replacing the current tag fetch scope
311 */
312 TagFetchScope &tagFetchScope();
313
314 /**
315 * Returns the list of collections being monitored.
316 *
317 * @since 4.3
318 */
319 Collection::List collectionsMonitored() const;
320
321 /**
322 * Returns the set of items being monitored.
323 *
324 * @since 4.3
325 *
326 * @deprecated Use itemsMonitoredEx() instead.
327 */
328 AKONADI_DEPRECATED QList<Item::Id> itemsMonitored() const;
329
330 /**
331 * Returns the set of items being monitored.
332 *
333 * Faster version (at least on 32-bit systems) of itemsMonitored().
334 *
335 * @since 4.6
336 */
337 QVector<Item::Id> itemsMonitoredEx() const;
338
339 /**
340 * Returns the set of mimetypes being monitored.
341 *
342 * @since 4.3
343 */
344 QStringList mimeTypesMonitored() const;
345
346 /**
347 * Returns the set of tags being monitored.
348 *
349 * @since 4.13
350 */
351 QVector<Tag::Id> tagsMonitored() const;
352
353 /**
354 * Returns the set of types being monitored.
355 *
356 * @since 4.13
357 */
358 QVector<Type> typesMonitored() const;
359
360 /**
361 * Returns the set of identifiers for resources being monitored.
362 *
363 * @since 4.3
364 */
365 QList<QByteArray> resourcesMonitored() const;
366
367 /**
368 * Returns true if everything is being monitored.
369 *
370 * @since 4.3
371 */
372 bool isAllMonitored() const;
373
374 /**
375 * Sets the session used by the Monitor to communicate with the %Akonadi server.
376 * If not set, the Akonadi::Session::defaultSession is used.
377 * @param session the session to be set
378 * @since 4.4
379 */
380 void setSession(Akonadi::Session *session);
381
382 /**
383 * Returns the Session used by the monitor to communicate with Akonadi.
384 *
385 * @since 4.4
386 */
387 Session *session() const;
388
389 /**
390 * Allows to enable/disable collection move translation. If enabled (the default), move
391 * notifications are automatically translated into add/remove notifications if the source/destination
392 * is outside of the monitored collection hierarchy.
393 * @param enabled enables collection move translation if set as @c true
394 * @since 4.9
395 */
396 void setCollectionMoveTranslationEnabled(bool enabled);
397
398Q_SIGNALS:
399 /**
400 * This signal is emitted if a monitored item has changed, e.g. item parts have been modified.
401 *
402 * @param item The changed item.
403 * @param partIdentifiers The identifiers of the item parts that has been changed.
404 */
405 void itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers);
406
407 /**
408 * This signal is emitted if flags of monitored items have changed.
409 *
410 * @param items Items that were changed
411 * @param addedFlags Flags that have been added to each item in @p items
412 * @param removedFlags Flags that have been removed from each item in @p items
413 * @since 4.11
414 */
415 void itemsFlagsChanged(const Akonadi::Item::List &items, const QSet<QByteArray> &addedFlags,
416 const QSet<QByteArray> &removedFlags);
417
418 /**
419 * This signal is emitted if tags of monitored items have changed.
420 *
421 * @param items Items that were changed
422 * @param addedTags Tags that have been added to each item in @p items.
423 * @param removedTags Tags that have been removed from each item in @p items
424 * @since 4.13
425 */
426 void itemsTagsChanged(const Akonadi::Item::List &items, const QSet<Akonadi::Tag> &addedTags,
427 const QSet<Akonadi::Tag> &removedTags);
428
429 /**
430 * This signal is emitted if a monitored item has been moved between two collections
431 *
432 * @param item The moved item.
433 * @param collectionSource The collection the item has been moved from.
434 * @param collectionDestination The collection the item has been moved to.
435 */
436 void itemMoved(const Akonadi::Item &item, const Akonadi::Collection &collectionSource,
437 const Akonadi::Collection &collectionDestination);
438
439 /**
440 * This is signal is emitted when multiple monitored items have been moved between two collections
441 *
442 * @param items Moved items
443 * @param collectionSource The collection the items have been moved from.
444 * @param collectionDestination The collection the items have been moved to.
445 *
446 * @since 4.11
447 */
448 void itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &collectionSource,
449 const Akonadi::Collection &collectionDestination);
450
451 /**
452 * This signal is emitted if an item has been added to a monitored collection in the Akonadi storage.
453 *
454 * @param item The new item.
455 * @param collection The collection the item has been added to.
456 */
457 void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection);
458
459 /**
460 * This signal is emitted if
461 * - a monitored item has been removed from the Akonadi storage
462 * or
463 * - a item has been removed from a monitored collection.
464 *
465 * @param item The removed item.
466 */
467 void itemRemoved(const Akonadi::Item &item);
468
469 /**
470 * This signal is emitted if monitored items have been removed from Akonadi
471 * storage of items have been removed from a monitored collection.
472 *
473 * @param items Removed items
474 *
475 * @since 4.11
476 */
477 void itemsRemoved(const Akonadi::Item::List &items);
478
479 /**
480 * This signal is emitted if a reference to an item is added to a virtual collection.
481 * @param item The linked item.
482 * @param collection The collection the item is linked to.
483 *
484 * @since 4.2
485 */
486 void itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection);
487
488 /**
489 * This signal is emitted if a reference to multiple items is added to a virtual collection
490 *
491 * @param items The linked items
492 * @param collection The collections the items are linked to
493 *
494 * @since 4.11
495 */
496 void itemsLinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection);
497
498 /**
499 * This signal is emitted if a reference to an item is removed from a virtual collection.
500 * @param item The unlinked item.
501 * @param collection The collection the item is unlinked from.
502 *
503 * @since 4.2
504 */
505 void itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection);
506
507 /**
508 * This signal is emitted if a refernece to items is removed from a virtual collection
509 *
510 * @param items The unlinked items
511 * @param collection The collections the items are unlinked from
512 *
513 * @since 4.11
514 */
515 void itemsUnlinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection);
516
517 /**
518 * This signal is emitted if a new collection has been added to a monitored collection in the Akonadi storage.
519 *
520 * @param collection The new collection.
521 * @param parent The parent collection.
522 */
523 void collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent);
524
525 /**
526 * This signal is emitted if a monitored collection has been changed (properties or content).
527 *
528 * @param collection The changed collection.
529 */
530 void collectionChanged(const Akonadi::Collection &collection);
531
532 /**
533 * This signal is emitted if a monitored collection has been changed (properties or attributes).
534 *
535 * @param collection The changed collection.
536 * @param attributeNames The names of the collection attributes that have been changed.
537 *
538 * @since 4.4
539 */
540 void collectionChanged(const Akonadi::Collection &collection, const QSet<QByteArray> &attributeNames);
541
542 /**
543 * This signals is emitted if a monitored collection has been moved.
544 *
545 * @param collection The moved collection.
546 * @param source The previous parent collection.
547 * @param destination The new parent collection.
548 *
549 * @since 4.4
550 */
551 void collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &source, const Akonadi::Collection &destination);
552
553 /**
554 * This signal is emitted if a monitored collection has been removed from the Akonadi storage.
555 *
556 * @param collection The removed collection.
557 */
558 void collectionRemoved(const Akonadi::Collection &collection);
559
560 /**
561 * This signal is emitted if a collection has been subscribed to by the user.
562 * It will be emitted even for unmonitored collections as the check for whether to
563 * monitor it has not been applied yet.
564 *
565 * @param collection The subscribed collection
566 * @param parent The parent collection of the subscribed collection.
567 *
568 * @since 4.6
569 */
570 void collectionSubscribed(const Akonadi::Collection &collection, const Akonadi::Collection &parent);
571
572 /**
573 * This signal is emitted if a user unsubscribes from a collection.
574 *
575 * @param collection The unsubscribed collection
576 *
577 * @since 4.6
578 */
579 void collectionUnsubscribed(const Akonadi::Collection &collection);
580
581 /**
582 * This signal is emitted if the statistics information of a monitored collection
583 * has changed.
584 *
585 * @param id The collection identifier of the changed collection.
586 * @param statistics The updated collection statistics, invalid if automatic
587 * fetching of statistics changes is disabled.
588 */
589 void collectionStatisticsChanged(Akonadi::Collection::Id id,
590 const Akonadi::CollectionStatistics &statistics);
591
592 /**
593 * This signal is emitted if a tag has been added to Akonadi storage.
594 *
595 * @param tag The added tag
596 * @since 4.13
597 */
598 void tagAdded(const Akonadi::Tag &tag);
599
600 /**
601 * This signal is emitted if a monitored tag is changed on the server.
602 *
603 * @param tag The changed tag.
604 * @since 4.13
605 */
606 void tagChanged(const Akonadi::Tag &tag);
607
608 /**
609 * This signal is emitted if a monitored tag is removed from the server storage.
610 *
611 * The monitor will also emit itemTagsChanged() signal for all monitored items
612 * (if any) that were tagged by @p tag.
613 *
614 * @param tag The removed tag.
615 * @since 4.13
616 */
617 void tagRemoved(const Akonadi::Tag &tag);
618
619 /**
620 * This signal is emitted if the Monitor starts or stops monitoring @p collection explicitly.
621 * @param collection The collection
622 * @param monitored Whether the collection is now being monitored or not.
623 *
624 * @since 4.3
625 */
626 void collectionMonitored(const Akonadi::Collection &collection, bool monitored);
627
628 /**
629 * This signal is emitted if the Monitor starts or stops monitoring @p item explicitly.
630 * @param item The item
631 * @param monitored Whether the item is now being monitored or not.
632 *
633 * @since 4.3
634 */
635 void itemMonitored(const Akonadi::Item &item, bool monitored);
636
637 /**
638 * This signal is emitted if the Monitor starts or stops monitoring the resource with the identifier @p identifier explicitly.
639 * @param identifier The identifier of the resource.
640 * @param monitored Whether the resource is now being monitored or not.
641 *
642 * @since 4.3
643 */
644 void resourceMonitored(const QByteArray &identifier, bool monitored);
645
646 /**
647 * This signal is emitted if the Monitor starts or stops monitoring @p mimeType explicitly.
648 * @param mimeType The mimeType.
649 * @param monitored Whether the mimeType is now being monitored or not.
650 *
651 * @since 4.3
652 */
653 void mimeTypeMonitored(const QString &mimeType, bool monitored);
654
655 /**
656 * This signal is emitted if the Monitor starts or stops monitoring everything.
657 * @param monitored Whether everything is now being monitored or not.
658 *
659 * @since 4.3
660 */
661 void allMonitored(bool monitored);
662
663 /**
664 * This signal is emitted if the Monitor starts or stops monitoring @p tag explicitly.
665 * @param tag The tag.
666 * @param monitored Whether the tag is now being monitored or not.
667 * @since 4.13
668 */
669 void tagMonitored(const Akonadi::Tag &tag, bool monitored);
670
671 /**
672 * This signal is emitted if the Monitor starts or stops monitoring @p type explicitly
673 * @param type The type.
674 * @param monitored Whether the type is now being monitored or not.
675 * @since 4.13
676 */
677 void typeMonitored(const Akonadi::Monitor::Type type, bool monitored);
678
679protected:
680 //@cond PRIVATE
681 friend class EntityTreeModel;
682 friend class EntityTreeModelPrivate;
683 MonitorPrivate *d_ptr;
684 explicit Monitor(MonitorPrivate *d, QObject *parent = 0);
685 //@endcond
686
687private:
688 Q_DECLARE_PRIVATE(Monitor)
689
690 //@cond PRIVATE
691 Q_PRIVATE_SLOT(d_ptr, void slotSessionDestroyed(QObject *))
692 Q_PRIVATE_SLOT(d_ptr, void slotStatisticsChangedFinished(KJob *))
693 Q_PRIVATE_SLOT(d_ptr, void slotFlushRecentlyChangedCollections())
694 Q_PRIVATE_SLOT(d_ptr, void slotNotify(const Akonadi::NotificationMessageV3::List &))
695 Q_PRIVATE_SLOT(d_ptr, void dataAvailable())
696 Q_PRIVATE_SLOT(d_ptr, void serverStateChanged(Akonadi::ServerManager::State))
697 Q_PRIVATE_SLOT(d_ptr, void invalidateCollectionCache(qint64))
698 Q_PRIVATE_SLOT(d_ptr, void invalidateItemCache(qint64))
699 Q_PRIVATE_SLOT(d_ptr, void invalidateTagCache(qint64))
700
701 friend class ResourceBasePrivate;
702 //@endcond
703};
704
705}
706
707#endif
708