Akonadi

agentbase.h
1 /*
2  This file is part of akonadiresources.
3 
4  SPDX-FileCopyrightText: 2006 Till Adam <[email protected]>
5  SPDX-FileCopyrightText: 2007 Volker Krause <[email protected]>
6  SPDX-FileCopyrightText: 2008 Kevin Krammer <[email protected]>
7 
8  SPDX-License-Identifier: LGPL-2.0-or-later
9 */
10 
11 #pragma once
12 
13 #include "akonadiagentbase_export.h"
14 // AkonadiCore
15 #include <akonadi/item.h>
16 
17 #include <QApplication>
18 
19 #include <KSharedConfig>
20 
21 #include <QDBusConnection>
22 #include <QDBusContext>
23 
24 #include <memory>
25 
26 class Akonadi__ControlAdaptor;
27 class Akonadi__StatusAdaptor;
28 
29 class KAboutData;
30 
31 namespace Akonadi
32 {
33 class AgentBasePrivate;
34 class ChangeRecorder;
35 class Collection;
36 class Item;
37 
38 /**
39  * @short The base class for all Akonadi agents and resources.
40  *
41  * This class is a base class for all Akonadi agents, which covers the real
42  * agent processes and all resources.
43  *
44  * It provides:
45  * - lifetime management
46  * - change monitoring and recording
47  * - configuration interface
48  * - problem reporting
49  *
50  * Akonadi Server supports several ways to launch agents and resources:
51  * - As a separate application (@see AKONADI_AGENT_MAIN)
52  * - As a thread in the AgentServer
53  * - As a separate process, using the akonadi_agent_launcher
54  *
55  * The idea is this, the agent or resource is written as a plugin instead of an
56  * executable (@see AgentFactory). In the AgentServer case, the AgentServer
57  * looks up the plugin and launches the agent in a separate thread. In the
58  * launcher case, a new akonadi_agent_launcher process is started for each
59  * agent or resource instance.
60  *
61  * When making an Agent or Resource suitable for running in the AgentServer some
62  * extra caution is needed. Because multiple instances of several kinds of agents
63  * run in the same process, one cannot blindly use global objects like KGlobal.
64  * For this reasons several methods where added to avoid problems in this context,
65  * most notably AgentBase::config(). Additionally,
66  * one cannot use QDBusConnection::sessionBus() with dbus < 1.4, because of a
67  * multithreading bug in libdbus. Instead one should use
68  * QDBusConnection::sessionBus() which works around this problem.
69  *
70  * @author Till Adam <[email protected]>, Volker Krause <[email protected]>
71  */
72 class AKONADIAGENTBASE_EXPORT AgentBase : public QObject, protected QDBusContext
73 {
74  Q_OBJECT
75 
76 public:
77  /**
78  * @short The interface for reacting on monitored or replayed changes.
79  *
80  * The Observer provides an interface to react on monitored or replayed changes.
81  *
82  * Since the this base class does only tell the change recorder that the change
83  * has been processed, an AgentBase subclass which wants to actually process
84  * the change needs to subclass Observer and reimplement the methods it is
85  * interested in.
86  *
87  * Such an agent specific Observer implementation can either be done
88  * stand-alone, i.e. as a separate object, or by inheriting both AgentBase
89  * and AgentBase::Observer.
90  *
91  * The observer implementation then has registered with the agent, so it
92  * can forward the incoming changes to the observer.
93  *
94  * @note In the multiple inheritance approach the init() method automatically
95  * registers itself as the observer.
96  *
97  * @note Do not call the base implementation of reimplemented virtual methods!
98  * The default implementation disconnected themselves from the Akonadi::ChangeRecorder
99  * to enable internal optimizations for unused notifications.
100  *
101  * Example for stand-alone observer:
102  * @code
103  * class ExampleAgent : public AgentBase
104  * {
105  * public:
106  * ExampleAgent( const QString &id );
107  *
108  * ~ExampleAgent();
109  *
110  * private:
111  * AgentBase::Observer *mObserver;
112  * };
113  *
114  * class ExampleObserver : public AgentBase::Observer
115  * {
116  * protected:
117  * void itemChanged( const Item &item );
118  * };
119  *
120  * ExampleAgent::ExampleAgent( const QString &id )
121  : AgentBase( id )
122  , mObserver( 0 )
123  * {
124  * mObserver = new ExampleObserver();
125  * registerObserver( mObserver );
126  * }
127  *
128  * ExampleAgent::~ExampleAgent()
129  * {
130  * delete mObserver;
131  * }
132  *
133  * void ExampleObserver::itemChanged( const Item &item )
134  * {
135  * // do something with item
136  * qCDebug(AKONADIAGENTBASE_LOG) << "Item id=" << item.id();
137  *
138  * // let base implementation tell the change recorder that we
139  * // have processed the change
140  * AgentBase::Observer::itemChanged( item );
141  * }
142  * @endcode
143  *
144  * Example for observer through multiple inheritance:
145  * @code
146  * class ExampleAgent : public AgentBase, public AgentBase::Observer
147  * {
148  * public:
149  * ExampleAgent( const QString &id );
150  *
151  * protected:
152  * void itemChanged( const Item &item );
153  * };
154  *
155  * ExampleAgent::ExampleAgent( const QString &id )
156  : AgentBase( id )
157  * {
158  * // no need to create or register observer since
159  * // we are the observer and registration happens automatically
160  * // in init()
161  * }
162  *
163  * void ExampleAgent::itemChanged( const Item &item )
164  * {
165  * // do something with item
166  * qCDebug(AKONADIAGENTBASE_LOG) << "Item id=" << item.id();
167  *
168  * // let base implementation tell the change recorder that we
169  * // have processed the change
170  * AgentBase::Observer::itemChanged( item );
171  * }
172  * @endcode
173  *
174  * @author Kevin Krammer <[email protected]>
175  *
176  * @deprecated Use ObserverV2 instead
177  */
178  class AKONADIAGENTBASE_DEPRECATED AKONADIAGENTBASE_EXPORT Observer // krazy:exclude=dpointer
179  {
180  public:
181  /**
182  * Creates an observer instance.
183  */
184  Observer();
185 
186  /**
187  * Destroys the observer instance.
188  */
189  virtual ~Observer();
190 
191  /**
192  * Reimplement to handle adding of new items.
193  * @param item The newly added item.
194  * @param collection The collection @p item got added to.
195  */
196  virtual void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection);
197 
198  /**
199  * Reimplement to handle changes to existing items.
200  * @param item The changed item.
201  * @param partIdentifiers The identifiers of the item parts that has been changed.
202  */
203  virtual void itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers);
204 
205  /**
206  * Reimplement to handle deletion of items.
207  * @param item The deleted item.
208  */
209  virtual void itemRemoved(const Akonadi::Item &item);
210 
211  /**
212  * Reimplement to handle adding of new collections.
213  * @param collection The newly added collection.
214  * @param parent The parent collection.
215  */
216  virtual void collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent);
217 
218  /**
219  * Reimplement to handle changes to existing collections.
220  * @param collection The changed collection.
221  */
222  virtual void collectionChanged(const Akonadi::Collection &collection);
223 
224  /**
225  * Reimplement to handle deletion of collections.
226  * @param collection The deleted collection.
227  */
228  virtual void collectionRemoved(const Akonadi::Collection &collection);
229  };
230 
231  /**
232  * BC extension of Observer with support for monitoring item and collection moves.
233  * Use this one instead of Observer.
234  *
235  * @since 4.4
236  */
237  class AKONADIAGENTBASE_EXPORT ObserverV2 : public Observer // krazy:exclude=dpointer
238  {
239  public:
240  using Observer::collectionChanged;
241 
242  /**
243  * Reimplement to handle item moves.
244  * When using this class in combination with Akonadi::ResourceBase, inter-resource
245  * moves are handled internally already and the corresponding add or delete method
246  * is called instead.
247  *
248  * @param item The moved item.
249  * @param collectionSource The collection the item has been moved from.
250  * @param collectionDestination The collection the item has been moved to.
251  */
252  virtual void itemMoved(const Akonadi::Item &item, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination);
253 
254  /**
255  * Reimplement to handle item linking.
256  * This is only relevant for virtual resources.
257  * @param item The linked item.
258  * @param collection The collection the item is linked to.
259  */
260  virtual void itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection);
261 
262  /**
263  * Reimplement to handle item unlinking.
264  * This is only relevant for virtual resources.
265  * @param item The unlinked item.
266  * @param collection The collection the item is unlinked from.
267  */
268  virtual void itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection);
269 
270  /**
271  * Reimplement to handle collection moves.
272  * When using this class in combination with Akonadi::ResourceBase, inter-resource
273  * moves are handled internally already and the corresponding add or delete method
274  * is called instead.
275  *
276  * @param collection The moved collection.
277  * @param collectionSource The previous parent collection.
278  * @param collectionDestination The new parent collection.
279  */
280  virtual void
281  collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination);
282 
283  /**
284  * Reimplement to handle changes to existing collections.
285  * @param collection The changed collection.
286  * @param changedAttributes The identifiers of the collection parts/attributes that has been changed.
287  */
288  virtual void collectionChanged(const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes);
289  };
290 
291  /**
292  * BC extension of ObserverV2 with support for batch operations
293  *
294  * @warning When using ObserverV3, you will never get single-item notifications
295  * from AgentBase::Observer, even when you don't reimplement corresponding batch
296  * method from ObserverV3. For instance, when you don't reimplement itemsRemoved()
297  * here, you will not get any notifications about item removal whatsoever!
298  *
299  * @since 4.11
300  */
301  class AKONADIAGENTBASE_EXPORT ObserverV3 : public ObserverV2 // krazy:exclude=dpointer
302  {
303  public:
304  /**
305  * Reimplement to handle changes in flags of existing items
306  *
307  * @warning When using ObserverV3, you will never get notifications about
308  * flag changes via Observer::itemChanged(), even when you don't reimplement
309  * itemsFlagsChanged()!
310  *
311  * @param items The changed items
312  * @param addedFlags Flags that have been added to the item
313  * @param removedFlags Flags that have been removed from the item
314  */
315  virtual void itemsFlagsChanged(const Akonadi::Item::List &items, const QSet<QByteArray> &addedFlags, const QSet<QByteArray> &removedFlags);
316 
317  /**
318  * Reimplement to handle batch notification about items deletion.
319  *
320  * @param items List of deleted items
321  */
322  virtual void itemsRemoved(const Akonadi::Item::List &items);
323 
324  /**
325  * Reimplement to handle batch notification about items move
326  *
327  * @param items List of moved items
328  * @param sourceCollection Collection from where the items were moved
329  * @param destinationCollection Collection to which the items were moved
330  */
331  virtual void
332  itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &sourceCollection, const Akonadi::Collection &destinationCollection);
333 
334  /**
335  * Reimplement to handle batch notifications about items linking.
336  *
337  * @param items Linked items
338  * @param collection Collection to which the items have been linked
339  */
340  virtual void itemsLinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection);
341 
342  /**
343  * Reimplement to handle batch notifications about items unlinking.
344  *
345  * @param items Unlinked items
346  * @param collection Collection from which the items have been unlinked
347  */
348  virtual void itemsUnlinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection);
349  };
350 
351  /**
352  * Observer that adds support for item tagging
353  *
354  * @warning ObserverV4 subclasses ObserverV3 which changes behavior of some of the
355  * virtual methods from Observer and ObserverV2. Please make sure you read
356  * documentation of ObserverV3 and adapt your agent accordingly.
357  *
358  * @since 4.13
359  */
360  class AKONADIAGENTBASE_EXPORT ObserverV4 : public ObserverV3 // krazy:exclude=dpointer
361  {
362  public:
363  /**
364  * Reimplement to handle tags additions
365  *
366  * @param tag Newly added tag
367  */
368  virtual void tagAdded(const Akonadi::Tag &tag);
369 
370  /**
371  * Reimplement to handle tags changes
372  *
373  * @param tag Tag that has been changed
374  */
375  virtual void tagChanged(const Akonadi::Tag &tag);
376 
377  /**
378  * Reimplement to handle tags removal.
379  *
380  * @note All items that were tagged by @p tag will get a separate notification
381  * about untagging via itemsTagsChanged(). It is guaranteed that the itemsTagsChanged()
382  * notification will be delivered before this one.
383  *
384  * @param tag Tag that has been removed.
385  */
386  virtual void tagRemoved(const Akonadi::Tag &tag);
387 
388  /**
389  * Reimplement to handle items tagging
390  *
391  * @param items Items that were tagged or untagged
392  * @param addedTags Set of tags that were added to all @p items
393  * @param removedTags Set of tags that were removed from all @p items
394  */
395  virtual void itemsTagsChanged(const Akonadi::Item::List &items, const QSet<Akonadi::Tag> &addedTags, const QSet<Akonadi::Tag> &removedTags);
396 
397  /**
398  * Reimplement to handle relations being added
399  */
400  virtual void relationAdded(const Akonadi::Relation &relation);
401 
402  /**
403  * Reimplement to handle relations being removed
404  */
405  virtual void relationRemoved(const Akonadi::Relation &relation);
406 
407  /**
408  * Reimplement to handled relations changing on items
409  * @param items Items that had relations added/removed from them
410  * @param addedRelations the list of relations that were added to all @p items
411  * @param removedRelations the list of relations that were removed from all @p items
412  */
413  virtual void
414  itemsRelationsChanged(const Akonadi::Item::List &items, const Akonadi::Relation::List &addedRelations, const Akonadi::Relation::List &removedRelations);
415  };
416 
417  /**
418  * This enum describes the different states the
419  * agent can be in.
420  */
421  enum Status {
422  Idle = 0, ///< The agent does currently nothing.
423  Running, ///< The agent is working on something.
424  Broken, ///< The agent encountered an error state.
425  NotConfigured ///< The agent is lacking required configuration
426  };
427 
428  /**
429  * Use this method in the main function of your agent
430  * application to initialize your agent subclass.
431  * This method also takes care of creating a KApplication
432  * object and parsing command line arguments.
433  *
434  * @note In case the given class is also derived from AgentBase::Observer
435  * it gets registered as its own observer (see AgentBase::Observer), e.g.
436  * <tt>agentInstance->registerObserver( agentInstance );</tt>
437  *
438  * @code
439  *
440  * class MyAgent : public AgentBase
441  * {
442  * ...
443  * };
444  *
445  * AKONADI_AGENT_MAIN( MyAgent )
446  *
447  * @endcode
448  *
449  * @param argc number of arguments
450  * @param argv arguments for the function
451  */
452  template<typename T>
453  static int init(int argc, char **argv)
454  {
455  // Disable session management
456  qunsetenv("SESSION_MANAGER");
457 
458  QApplication app(argc, argv);
459  debugAgent(argc, argv);
460  const QString id = parseArguments(argc, argv);
461  T r(id);
462 
463  // check if T also inherits AgentBase::Observer and
464  // if it does, automatically register it on itself
465  auto observer = dynamic_cast<Observer *>(&r);
466  if (observer != nullptr) {
467  r.registerObserver(observer);
468  }
469  return init(r);
470  }
471 
472  /**
473  * This method returns the current status code of the agent.
474  *
475  * The following return values are possible:
476  *
477  * - 0 - Idle
478  * - 1 - Running
479  * - 2 - Broken
480  * - 3 - NotConfigured
481  */
482  [[nodiscard]] virtual int status() const;
483 
484  /**
485  * This method returns an i18n'ed description of the current status code.
486  */
487  [[nodiscard]] virtual QString statusMessage() const;
488 
489  /**
490  * This method returns the current progress of the agent in percentage.
491  */
492  [[nodiscard]] virtual int progress() const;
493 
494  /**
495  * This method returns an i18n'ed description of the current progress.
496  */
497  [[nodiscard]] virtual QString progressMessage() const;
498 
499 public Q_SLOTS:
500  /**
501  * This method is called whenever the agent shall show its configuration dialog
502  * to the user. It will be automatically called when the agent is started for
503  * the first time.
504  *
505  * @param windowId The parent window id.
506  *
507  * @note If the method is reimplemented it has to emit the configurationDialogAccepted()
508  * or configurationDialogRejected() signals depending on the users choice.
509  */
510  virtual void configure(WId windowId);
511 
512 public:
513  /**
514  * This method returns the windows id, which should be used for dialogs.
515  */
516  [[nodiscard]] WId winIdForDialogs() const;
517 
518 #ifdef Q_OS_WIN
519  /**
520  * Overload of @ref configure needed because WId cannot be automatically casted
521  * to qlonglong on Windows.
522  */
523  void configure(qlonglong windowId);
524 #endif
525 
526  /**
527  * Returns the instance identifier of this agent.
528  */
529  [[nodiscard]] QString identifier() const;
530 
531  /**
532  * This method is called when the agent is removed from
533  * the system, so it can do some cleanup stuff.
534  *
535  * @note If you reimplement this in a subclass make sure
536  * to call this base implementation at the end.
537  */
538  virtual void cleanup();
539 
540  /**
541  * Registers the given observer for reacting on monitored or recorded changes.
542  *
543  * @param observer The change handler to register. No ownership transfer, i.e.
544  * the caller stays owner of the pointer and can reset
545  * the registration by calling this method with @c 0
546  */
547  void registerObserver(Observer *observer);
548 
549  /**
550  * This method is used to set the name of the agent.
551  *
552  * @since 4.3
553  * @param name name of the agent
554  */
555  // FIXME_API: make sure location is renamed to this by agentbase
556  void setAgentName(const QString &name);
557 
558  /**
559  * Returns the name of the agent.
560  *
561  * @since 4.3
562  */
563  [[nodiscard]] QString agentName() const;
564 
565 Q_SIGNALS:
566  /**
567  * This signal is emitted whenever the name of the agent has changed.
568  *
569  * @param name The new name of the agent.
570  *
571  * @since 4.3
572  */
573  void agentNameChanged(const QString &name);
574 
575  /**
576  * This signal should be emitted whenever the status of the agent has been changed.
577  * @param status The new Status code.
578  * @param message A i18n'ed description of the new status.
579  */
580  void status(int status, const QString &message = QString());
581 
582  /**
583  * This signal should be emitted whenever the progress of an action in the agent
584  * (e.g. data transfer, connection establishment to remote server etc.) has changed.
585  *
586  * @param progress The progress of the action in percent.
587  */
588  void percent(int progress);
589 
590  /**
591  * This signal shall be used to report warnings.
592  *
593  * @param message The i18n'ed warning message.
594  */
595  void warning(const QString &message);
596 
597  /**
598  * This signal shall be used to report errors.
599  *
600  * @param message The i18n'ed error message.
601  */
602  void error(const QString &message);
603 
604  /**
605  * This signal should be emitted whenever the status of the agent has been changed.
606  * @param status The object that describes the status change.
607  *
608  * @since 4.6
609  */
610  void advancedStatus(const QVariantMap &status);
611 
612  /**
613  * Emitted when another application has remotely asked the agent to abort
614  * its current operation.
615  * Connect to this signal if your agent supports abortion. After aborting
616  * and cleaning up, agents should return to Idle status.
617  *
618  * @since 4.4
619  */
620  void abortRequested();
621 
622  /**
623  * Emitted if another application has changed the agent's configuration remotely
624  * and called AgentInstance::reconfigure().
625  *
626  * @since 4.2
627  */
628  void reloadConfiguration();
629 
630  /**
631  * Emitted when the online state changed.
632  * @param online The online state.
633  * @since 4.2
634  */
635  void onlineChanged(bool online);
636 
637  /**
638  * This signal is emitted whenever the user has accepted the configuration dialog.
639  *
640  * @note Implementors of agents/resources are responsible to emit this signal if
641  * the agent/resource reimplements configure().
642  *
643  * @since 4.4
644  */
645  void configurationDialogAccepted();
646 
647  /**
648  * This signal is emitted whenever the user has rejected the configuration dialog.
649  *
650  * @note Implementors of agents/resources are responsible to emit this signal if
651  * the agent/resource reimplements configure().
652  *
653  * @since 4.4
654  */
655  void configurationDialogRejected();
656 
657 protected:
658  /**
659  * Creates an agent base.
660  *
661  * @param id The instance id of the agent.
662  */
663  AgentBase(const QString &id);
664 
665  /**
666  * Destroys the agent base.
667  */
668  ~AgentBase() override;
669 
670  /**
671  * This method is called whenever the agent application is about to
672  * quit.
673  *
674  * Reimplement this method to do session cleanup (e.g. disconnecting
675  * from groupware server).
676  */
677  virtual void aboutToQuit();
678 
679  /**
680  * Returns the Akonadi::ChangeRecorder object used for monitoring.
681  * Use this to configure which parts you want to monitor.
682  */
683  ChangeRecorder *changeRecorder() const;
684 
685  /**
686  * Returns the config object for this Agent.
687  */
688  KSharedConfigPtr config();
689 
690  /**
691  * Marks the current change as processes and replays the next change if change
692  * recording is enabled (noop otherwise). This method is called
693  * from the default implementation of the change notification slots. While not
694  * required when not using change recording, it is nevertheless recommended
695  * to call this method when done with processing a change notification.
696  */
697  void changeProcessed();
698 
699  /**
700  * Returns whether the agent is currently online.
701  */
702  bool isOnline() const;
703 
704  /**
705  * Sets whether the agent needs network or not.
706  *
707  * @since 4.2
708  * @todo use this in combination with QNetworkConfiguration to change
709  * the onLine status of the agent.
710  * @param needsNetwork @c true if the agents needs network. Defaults to @c false
711  */
712  void setNeedsNetwork(bool needsNetwork);
713 
714  /**
715  * Sets whether the agent shall be online or not.
716  */
717  void setOnline(bool state);
718 
719 protected:
720  /**
721  * Sets the agent offline but will make it online again after a given time
722  *
723  * Use this method when the agent detects some problem with its backend but it wants
724  * to retry all pending operations after some time - e.g. a server can not be reached currently
725  *
726  * Example usage:
727  * @code
728  * void ExampleResource::onItemRemovedFinished(KJob *job)
729  * {
730  * if (job->error()) {
731  * Q_EMIT status(Broken, job->errorString());
732  * deferTask();
733  * setTemporaryOffline(300);
734  * return;
735  * }
736  * ...
737  * }
738  * @endcode
739  *
740  * @since 4.13
741  * @param makeOnlineInSeconds timeout in seconds after which the agent changes to online
742  */
743  void setTemporaryOffline(int makeOnlineInSeconds = 300);
744 
745  /// @cond PRIVATE
746  static void debugAgent(int argc, char **argv);
747 
748  std::unique_ptr<AgentBasePrivate> const d_ptr;
749  explicit AgentBase(AgentBasePrivate *d, const QString &id);
750  friend class ObserverV2;
751  /// @endcond
752 
753  /**
754  * This method is called whenever the @p online status has changed.
755  * Reimplement this method to react on online status changes.
756  * @param online online status
757  */
758  virtual void doSetOnline(bool online);
759 
760  virtual KAboutData aboutData() const;
761 
762 private:
763  /// @cond PRIVATE
764  static QString parseArguments(int argc, char **argv);
765  static int init(AgentBase &r);
766  void setOnlineInternal(bool state);
767 
768  // D-Bus interface stuff
769  void abort();
770  void reconfigure();
771  void quit();
772 
773  // dbus agent interface
774  friend class ::Akonadi__StatusAdaptor;
775  friend class ::Akonadi__ControlAdaptor;
776 
777  Q_DECLARE_PRIVATE(AgentBase)
778  Q_PRIVATE_SLOT(d_func(), void delayedInit())
779  Q_PRIVATE_SLOT(d_func(), void slotStatus(int, const QString &))
780  Q_PRIVATE_SLOT(d_func(), void slotPercent(int))
781  Q_PRIVATE_SLOT(d_func(), void slotWarning(const QString &))
782  Q_PRIVATE_SLOT(d_func(), void slotError(const QString &))
783  Q_PRIVATE_SLOT(d_func(), void slotNetworkStatusChange(bool))
784  Q_PRIVATE_SLOT(d_func(), void slotResumedFromSuspend())
785  Q_PRIVATE_SLOT(d_func(), void slotTemporaryOfflineTimeout())
786 
787  /// @endcond
788 };
789 
790 }
791 
792 #ifndef AKONADI_AGENT_MAIN
793 /**
794  * Convenience Macro for the most common main() function for Akonadi agents.
795  */
796 #define AKONADI_AGENT_MAIN(agentClass) \
797  int main(int argc, char **argv) \
798  { \
799  return Akonadi::AgentBase::init<agentClass>(argc, argv); \
800  }
801 #endif
An Akonadi Tag.
Definition: tag.h:25
Status
This enum describes the different states the agent can be in.
Definition: agentbase.h:421
Represents a collection of PIM items.
Definition: collection.h:61
An Akonadi Relation.
Definition: relation.h:39
Records and replays change notification.
The interface for reacting on monitored or replayed changes.
Definition: agentbase.h:178
static int init(int argc, char **argv)
Use this method in the main function of your agent application to initialize your agent subclass.
Definition: agentbase.h:453
Q_SCRIPTABLE CaptureState status()
BC extension of Observer with support for monitoring item and collection moves.
Definition: agentbase.h:237
The base class for all Akonadi agents and resources.
Definition: agentbase.h:72
KSharedConfigPtr config()
BC extension of ObserverV2 with support for batch operations.
Definition: agentbase.h:301
@ Broken
The agent encountered an error state.
Definition: agentbase.h:424
Q_SCRIPTABLE Q_NOREPLY void abort()
Observer that adds support for item tagging.
Definition: agentbase.h:360
@ Running
The agent is working on something.
Definition: agentbase.h:423
QString message
Represents a PIM item stored in Akonadi storage.
Definition: item.h:100
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Thu Nov 30 2023 04:04:20 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.