File indexing completed on 2024-06-23 05:06:30

0001 /*
0002     This file is part of akonadiresources.
0003 
0004     SPDX-FileCopyrightText: 2006 Till Adam <adam@kde.org>
0005     SPDX-FileCopyrightText: 2007 Volker Krause <vkrause@kde.org>
0006     SPDX-FileCopyrightText: 2008 Kevin Krammer <kevin.krammer@gmx.at>
0007 
0008     SPDX-License-Identifier: LGPL-2.0-or-later
0009 */
0010 
0011 #pragma once
0012 
0013 #include "akonadiagentbase_export.h"
0014 // AkonadiCore
0015 #include "akonadi/item.h"
0016 
0017 #include <QApplication>
0018 
0019 #include <KSharedConfig>
0020 
0021 #include <QDBusConnection>
0022 #include <QDBusContext>
0023 
0024 #include <memory>
0025 
0026 class Akonadi__ControlAdaptor;
0027 class Akonadi__StatusAdaptor;
0028 
0029 class KAboutData;
0030 
0031 namespace Akonadi
0032 {
0033 class AgentBasePrivate;
0034 class ChangeRecorder;
0035 class Collection;
0036 class Item;
0037 
0038 /**
0039  * @short The base class for all Akonadi agents and resources.
0040  *
0041  * This class is a base class for all Akonadi agents, which covers the real
0042  * agent processes and all resources.
0043  *
0044  * It provides:
0045  * - lifetime management
0046  * - change monitoring and recording
0047  * - configuration interface
0048  * - problem reporting
0049  *
0050  * Akonadi Server supports several ways to launch agents and resources:
0051  * - As a separate application (@see AKONADI_AGENT_MAIN)
0052  * - As a thread in the AgentServer
0053  * - As a separate process, using the akonadi_agent_launcher
0054  *
0055  * The idea is this, the agent or resource is written as a plugin instead of an
0056  * executable (@see AgentFactory). In the AgentServer case, the AgentServer
0057  * looks up the plugin and launches the agent in a separate thread. In the
0058  * launcher case, a new akonadi_agent_launcher process is started for each
0059  * agent or resource instance.
0060  *
0061  * When making an Agent or Resource suitable for running in the AgentServer some
0062  * extra caution is needed. Because multiple instances of several kinds of agents
0063  * run in the same process, one cannot blindly use global objects like KGlobal.
0064  * For this reasons several methods where added to avoid problems in this context,
0065  * most notably AgentBase::config(). Additionally,
0066  * one cannot use QDBusConnection::sessionBus() with dbus < 1.4, because of a
0067  * multithreading bug in libdbus. Instead one should use
0068  * QDBusConnection::sessionBus() which works around this problem.
0069  *
0070  * @author Till Adam <adam@kde.org>, Volker Krause <vkrause@kde.org>
0071  */
0072 class AKONADIAGENTBASE_EXPORT AgentBase : public QObject, protected QDBusContext
0073 {
0074     Q_OBJECT
0075 
0076 public:
0077     /**
0078      * @short The interface for reacting on monitored or replayed changes.
0079      *
0080      * The Observer provides an interface to react on monitored or replayed changes.
0081      *
0082      * Since the this base class does only tell the change recorder that the change
0083      * has been processed, an AgentBase subclass which wants to actually process
0084      * the change needs to subclass Observer and reimplement the methods it is
0085      * interested in.
0086      *
0087      * Such an agent specific Observer implementation can either be done
0088      * stand-alone, i.e. as a separate object, or by inheriting both AgentBase
0089      * and AgentBase::Observer.
0090      *
0091      * The observer implementation then has registered with the agent, so it
0092      * can forward the incoming changes to the observer.
0093      *
0094      * @note In the multiple inheritance approach the init() method automatically
0095      *       registers itself as the observer.
0096      *
0097      * @note Do not call the base implementation of reimplemented virtual methods!
0098      *       The default implementation disconnected themselves from the Akonadi::ChangeRecorder
0099      *       to enable internal optimizations for unused notifications.
0100      *
0101      * Example for stand-alone observer:
0102      * @code
0103      * class ExampleAgent : public AgentBase
0104      * {
0105      *   public:
0106      *     ExampleAgent( const QString &id );
0107      *
0108      *     ~ExampleAgent();
0109      *
0110      *   private:
0111      *     AgentBase::Observer *mObserver;
0112      * };
0113      *
0114      * class ExampleObserver : public AgentBase::Observer
0115      * {
0116      *   protected:
0117      *     void itemChanged( const Item &item );
0118      * };
0119      *
0120      * ExampleAgent::ExampleAgent( const QString &id )
0121          : AgentBase( id )
0122          , mObserver( 0 )
0123      * {
0124      *   mObserver = new ExampleObserver();
0125      *   registerObserver( mObserver );
0126      * }
0127      *
0128      * ExampleAgent::~ExampleAgent()
0129      * {
0130      *   delete mObserver;
0131      * }
0132      *
0133      * void ExampleObserver::itemChanged( const Item &item )
0134      * {
0135      *   // do something with item
0136      *   qCDebug(AKONADIAGENTBASE_LOG) << "Item id=" << item.id();
0137      *
0138      *   // let base implementation tell the change recorder that we
0139      *   // have processed the change
0140      *   AgentBase::Observer::itemChanged( item );
0141      * }
0142      * @endcode
0143      *
0144      * Example for observer through multiple inheritance:
0145      * @code
0146      * class ExampleAgent : public AgentBase, public AgentBase::Observer
0147      * {
0148      *   public:
0149      *     ExampleAgent( const QString &id );
0150      *
0151      *   protected:
0152      *     void itemChanged( const Item &item );
0153      * };
0154      *
0155      * ExampleAgent::ExampleAgent( const QString &id )
0156          : AgentBase( id )
0157      * {
0158      *   // no need to create or register observer since
0159      *   // we are the observer and registration happens automatically
0160      *   // in init()
0161      * }
0162      *
0163      * void ExampleAgent::itemChanged( const Item &item )
0164      * {
0165      *   // do something with item
0166      *   qCDebug(AKONADIAGENTBASE_LOG) << "Item id=" << item.id();
0167      *
0168      *   // let base implementation tell the change recorder that we
0169      *   // have processed the change
0170      *   AgentBase::Observer::itemChanged( item );
0171      * }
0172      * @endcode
0173      *
0174      * @author Kevin Krammer <kevin.krammer@gmx.at>
0175      *
0176      * @deprecated Use ObserverV2 instead
0177      */
0178     class AKONADIAGENTBASE_DEPRECATED AKONADIAGENTBASE_EXPORT Observer // krazy:exclude=dpointer
0179     {
0180     public:
0181         /**
0182          * Creates an observer instance.
0183          */
0184         Observer();
0185 
0186         /**
0187          * Destroys the observer instance.
0188          */
0189         virtual ~Observer();
0190 
0191         /**
0192          * Reimplement to handle adding of new items.
0193          * @param item The newly added item.
0194          * @param collection The collection @p item got added to.
0195          */
0196         virtual void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection);
0197 
0198         /**
0199          * Reimplement to handle changes to existing items.
0200          * @param item The changed item.
0201          * @param partIdentifiers The identifiers of the item parts that has been changed.
0202          */
0203         virtual void itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers);
0204 
0205         /**
0206          * Reimplement to handle deletion of items.
0207          * @param item The deleted item.
0208          */
0209         virtual void itemRemoved(const Akonadi::Item &item);
0210 
0211         /**
0212          * Reimplement to handle adding of new collections.
0213          * @param collection The newly added collection.
0214          * @param parent The parent collection.
0215          */
0216         virtual void collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent);
0217 
0218         /**
0219          * Reimplement to handle changes to existing collections.
0220          * @param collection The changed collection.
0221          */
0222         virtual void collectionChanged(const Akonadi::Collection &collection);
0223 
0224         /**
0225          * Reimplement to handle deletion of collections.
0226          * @param collection The deleted collection.
0227          */
0228         virtual void collectionRemoved(const Akonadi::Collection &collection);
0229     };
0230 
0231     /**
0232      * BC extension of Observer with support for monitoring item and collection moves.
0233      * Use this one instead of Observer.
0234      *
0235      * @since 4.4
0236      */
0237     class AKONADIAGENTBASE_EXPORT ObserverV2 : public Observer // krazy:exclude=dpointer
0238     {
0239     public:
0240         using Observer::collectionChanged;
0241 
0242         /**
0243          * Reimplement to handle item moves.
0244          * When using this class in combination with Akonadi::ResourceBase, inter-resource
0245          * moves are handled internally already and the corresponding  add or delete method
0246          * is called instead.
0247          *
0248          * @param item The moved item.
0249          * @param collectionSource The collection the item has been moved from.
0250          * @param collectionDestination The collection the item has been moved to.
0251          */
0252         virtual void itemMoved(const Akonadi::Item &item, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination);
0253 
0254         /**
0255          * Reimplement to handle item linking.
0256          * This is only relevant for virtual resources.
0257          * @param item The linked item.
0258          * @param collection The collection the item is linked to.
0259          */
0260         virtual void itemLinked(const Akonadi::Item &item, const Akonadi::Collection &collection);
0261 
0262         /**
0263          * Reimplement to handle item unlinking.
0264          * This is only relevant for virtual resources.
0265          * @param item The unlinked item.
0266          * @param collection The collection the item is unlinked from.
0267          */
0268         virtual void itemUnlinked(const Akonadi::Item &item, const Akonadi::Collection &collection);
0269 
0270         /**
0271          * Reimplement to handle collection moves.
0272          * When using this class in combination with Akonadi::ResourceBase, inter-resource
0273          * moves are handled internally already and the corresponding  add or delete method
0274          * is called instead.
0275          *
0276          * @param collection The moved collection.
0277          * @param collectionSource The previous parent collection.
0278          * @param collectionDestination The new parent collection.
0279          */
0280         virtual void
0281         collectionMoved(const Akonadi::Collection &collection, const Akonadi::Collection &collectionSource, const Akonadi::Collection &collectionDestination);
0282 
0283         /**
0284          * Reimplement to handle changes to existing collections.
0285          * @param collection The changed collection.
0286          * @param changedAttributes The identifiers of the collection parts/attributes that has been changed.
0287          */
0288         virtual void collectionChanged(const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes);
0289     };
0290 
0291     /**
0292      * BC extension of ObserverV2 with support for batch operations
0293      *
0294      * @warning When using ObserverV3, you will never get single-item notifications
0295      * from AgentBase::Observer, even when you don't reimplement corresponding batch
0296      * method from ObserverV3. For instance, when you don't reimplement itemsRemoved()
0297      * here, you will not get any notifications about item removal whatsoever!
0298      *
0299      * @since 4.11
0300      */
0301     class AKONADIAGENTBASE_EXPORT ObserverV3 : public ObserverV2 // krazy:exclude=dpointer
0302     {
0303     public:
0304         /**
0305          * Reimplement to handle changes in flags of existing items
0306          *
0307          * @warning When using ObserverV3, you will never get notifications about
0308          * flag changes via Observer::itemChanged(), even when you don't reimplement
0309          * itemsFlagsChanged()!
0310          *
0311          * @param items The changed items
0312          * @param addedFlags Flags that have been added to the item
0313          * @param removedFlags Flags that have been removed from the item
0314          */
0315         virtual void itemsFlagsChanged(const Akonadi::Item::List &items, const QSet<QByteArray> &addedFlags, const QSet<QByteArray> &removedFlags);
0316 
0317         /**
0318          * Reimplement to handle batch notification about items deletion.
0319          *
0320          * @param items List of deleted items
0321          */
0322         virtual void itemsRemoved(const Akonadi::Item::List &items);
0323 
0324         /**
0325          * Reimplement to handle batch notification about items move
0326          *
0327          * @param items List of moved items
0328          * @param sourceCollection Collection from where the items were moved
0329          * @param destinationCollection Collection to which the items were moved
0330          */
0331         virtual void
0332         itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &sourceCollection, const Akonadi::Collection &destinationCollection);
0333 
0334         /**
0335          * Reimplement to handle batch notifications about items linking.
0336          *
0337          * @param items Linked items
0338          * @param collection Collection to which the items have been linked
0339          */
0340         virtual void itemsLinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection);
0341 
0342         /**
0343          * Reimplement to handle batch notifications about items unlinking.
0344          *
0345          * @param items Unlinked items
0346          * @param collection Collection from which the items have been unlinked
0347          */
0348         virtual void itemsUnlinked(const Akonadi::Item::List &items, const Akonadi::Collection &collection);
0349     };
0350 
0351     /**
0352      * Observer that adds support for item tagging
0353      *
0354      * @warning ObserverV4 subclasses ObserverV3 which changes behavior of some of the
0355      * virtual methods from Observer and ObserverV2. Please make sure you read
0356      * documentation of ObserverV3 and adapt your agent accordingly.
0357      *
0358      * @since 4.13
0359      */
0360     class AKONADIAGENTBASE_EXPORT ObserverV4 : public ObserverV3 // krazy:exclude=dpointer
0361     {
0362     public:
0363         /**
0364          * Reimplement to handle tags additions
0365          *
0366          * @param tag Newly added tag
0367          */
0368         virtual void tagAdded(const Akonadi::Tag &tag);
0369 
0370         /**
0371          * Reimplement to handle tags changes
0372          *
0373          * @param tag Tag that has been changed
0374          */
0375         virtual void tagChanged(const Akonadi::Tag &tag);
0376 
0377         /**
0378          * Reimplement to handle tags removal.
0379          *
0380          * @note All items that were tagged by @p tag will get a separate notification
0381          * about untagging via itemsTagsChanged(). It is guaranteed that the itemsTagsChanged()
0382          * notification will be delivered before this one.
0383          *
0384          * @param tag Tag that has been removed.
0385          */
0386         virtual void tagRemoved(const Akonadi::Tag &tag);
0387 
0388         /**
0389          * Reimplement to handle items tagging
0390          *
0391          * @param items Items that were tagged or untagged
0392          * @param addedTags Set of tags that were added to all @p items
0393          * @param removedTags Set of tags that were removed from all @p items
0394          */
0395         virtual void itemsTagsChanged(const Akonadi::Item::List &items, const QSet<Akonadi::Tag> &addedTags, const QSet<Akonadi::Tag> &removedTags);
0396 
0397         /**
0398          * Reimplement to handle relations being added
0399          */
0400         virtual void relationAdded(const Akonadi::Relation &relation);
0401 
0402         /**
0403          * Reimplement to handle relations being removed
0404          */
0405         virtual void relationRemoved(const Akonadi::Relation &relation);
0406 
0407         /**
0408          * Reimplement to handled relations changing on items
0409          * @param items Items that had relations added/removed from them
0410          * @param addedRelations the list of relations that were added to all @p items
0411          * @param removedRelations the list of relations that were removed from all @p items
0412          */
0413         virtual void
0414         itemsRelationsChanged(const Akonadi::Item::List &items, const Akonadi::Relation::List &addedRelations, const Akonadi::Relation::List &removedRelations);
0415     };
0416 
0417     /**
0418      * This enum describes the different states the
0419      * agent can be in.
0420      */
0421     enum Status {
0422         Idle = 0, ///< The agent does currently nothing.
0423         Running, ///< The agent is working on something.
0424         Broken, ///< The agent encountered an error state.
0425         NotConfigured ///< The agent is lacking required configuration
0426     };
0427 
0428     /**
0429      * Use this method in the main function of your agent
0430      * application to initialize your agent subclass.
0431      * This method also takes care of creating a KApplication
0432      * object and parsing command line arguments.
0433      *
0434      * @note In case the given class is also derived from AgentBase::Observer
0435      *       it gets registered as its own observer (see AgentBase::Observer), e.g.
0436      *       <tt>agentInstance->registerObserver( agentInstance );</tt>
0437      *
0438      * @code
0439      *
0440      *   class MyAgent : public AgentBase
0441      *   {
0442      *     ...
0443      *   };
0444      *
0445      *   AKONADI_AGENT_MAIN( MyAgent )
0446      *
0447      * @endcode
0448      *
0449      * @param argc number of arguments
0450      * @param argv arguments for the function
0451      */
0452     template<typename T>
0453     static int init(int argc, char **argv)
0454     {
0455         // Disable session management
0456         qunsetenv("SESSION_MANAGER");
0457 
0458         QApplication app(argc, argv);
0459         debugAgent(argc, argv);
0460         const QString id = parseArguments(argc, argv);
0461         T r(id);
0462 
0463         // check if T also inherits AgentBase::Observer and
0464         // if it does, automatically register it on itself
0465         auto observer = dynamic_cast<Observer *>(&r);
0466         if (observer != nullptr) {
0467             r.registerObserver(observer);
0468         }
0469         return init(r);
0470     }
0471 
0472     /**
0473      * This method returns the current status code of the agent.
0474      *
0475      * The following return values are possible:
0476      *
0477      *  - 0 - Idle
0478      *  - 1 - Running
0479      *  - 2 - Broken
0480      *  - 3 - NotConfigured
0481      */
0482     [[nodiscard]] virtual int status() const;
0483 
0484     /**
0485      * This method returns an i18n'ed description of the current status code.
0486      */
0487     [[nodiscard]] virtual QString statusMessage() const;
0488 
0489     /**
0490      * This method returns the current progress of the agent in percentage.
0491      */
0492     [[nodiscard]] virtual int progress() const;
0493 
0494     /**
0495      * This method returns an i18n'ed description of the current progress.
0496      */
0497     [[nodiscard]] virtual QString progressMessage() const;
0498 
0499 public Q_SLOTS:
0500     /**
0501      * This method is called whenever the agent shall show its configuration dialog
0502      * to the user. It will be automatically called when the agent is started for
0503      * the first time.
0504      *
0505      * @param windowId The parent window id.
0506      *
0507      * @note If the method is reimplemented it has to emit the configurationDialogAccepted()
0508      *       or configurationDialogRejected() signals depending on the users choice.
0509      */
0510     virtual void configure(WId windowId);
0511 
0512 public:
0513     /**
0514      * This method returns the windows id, which should be used for dialogs.
0515      */
0516     [[nodiscard]] WId winIdForDialogs() const;
0517 
0518 #ifdef Q_OS_WIN
0519     /**
0520      * Overload of @ref configure needed because WId cannot be automatically casted
0521      * to qlonglong on Windows.
0522      */
0523     void configure(qlonglong windowId);
0524 #endif
0525 
0526     /**
0527      * Returns the instance identifier of this agent.
0528      */
0529     [[nodiscard]] QString identifier() const;
0530 
0531     /**
0532      * This method is called when the agent is removed from
0533      * the system, so it can do some cleanup stuff.
0534      *
0535      * @note If you reimplement this in a subclass make sure
0536      *       to call this base implementation at the end.
0537      */
0538     virtual void cleanup();
0539 
0540     /**
0541      * Registers the given observer for reacting on monitored or recorded changes.
0542      *
0543      * @param observer The change handler to register. No ownership transfer, i.e.
0544      *                 the caller stays owner of the pointer and can reset
0545      *                 the registration by calling this method with @c 0
0546      */
0547     void registerObserver(Observer *observer);
0548 
0549     /**
0550      * This method is used to set the name of the agent.
0551      *
0552      * @since 4.3
0553      * @param name name of the agent
0554      */
0555     // FIXME_API: make sure location is renamed to this by agentbase
0556     void setAgentName(const QString &name);
0557 
0558     /**
0559      * Returns the name of the agent.
0560      *
0561      * @since 4.3
0562      */
0563     [[nodiscard]] QString agentName() const;
0564 
0565 Q_SIGNALS:
0566     /**
0567      * This signal is emitted whenever the name of the agent has changed.
0568      *
0569      * @param name The new name of the agent.
0570      *
0571      * @since 4.3
0572      */
0573     void agentNameChanged(const QString &name);
0574 
0575     /**
0576      * This signal should be emitted whenever the status of the agent has been changed.
0577      * @param status The new Status code.
0578      * @param message A i18n'ed description of the new status.
0579      */
0580     void status(int status, const QString &message = QString());
0581 
0582     /**
0583      * This signal should be emitted whenever the progress of an action in the agent
0584      * (e.g. data transfer, connection establishment to remote server etc.) has changed.
0585      *
0586      * @param progress The progress of the action in percent.
0587      */
0588     void percent(int progress);
0589 
0590     /**
0591      * This signal shall be used to report warnings.
0592      *
0593      * @param message The i18n'ed warning message.
0594      */
0595     void warning(const QString &message);
0596 
0597     /**
0598      * This signal shall be used to report errors.
0599      *
0600      * @param message The i18n'ed error message.
0601      */
0602     void error(const QString &message);
0603 
0604     /**
0605      * This signal should be emitted whenever the status of the agent has been changed.
0606      * @param status The object that describes the status change.
0607      *
0608      * @since 4.6
0609      */
0610     void advancedStatus(const QVariantMap &status);
0611 
0612     /**
0613      * Emitted when another application has remotely asked the agent to abort
0614      * its current operation.
0615      * Connect to this signal if your agent supports abortion. After aborting
0616      * and cleaning up, agents should return to Idle status.
0617      *
0618      * @since 4.4
0619      */
0620     void abortRequested();
0621 
0622     /**
0623      * Emitted if another application has changed the agent's configuration remotely
0624      * and called AgentInstance::reconfigure().
0625      *
0626      * @since 4.2
0627      */
0628     void reloadConfiguration();
0629 
0630     /**
0631      * Emitted when the online state changed.
0632      * @param online The online state.
0633      * @since 4.2
0634      */
0635     void onlineChanged(bool online);
0636 
0637     /**
0638      * This signal is emitted whenever the user has accepted the configuration dialog.
0639      *
0640      * @note Implementors of agents/resources are responsible to emit this signal if
0641      *       the agent/resource reimplements configure().
0642      *
0643      * @since 4.4
0644      */
0645     void configurationDialogAccepted();
0646 
0647     /**
0648      * This signal is emitted whenever the user has rejected the configuration dialog.
0649      *
0650      * @note Implementors of agents/resources are responsible to emit this signal if
0651      *       the agent/resource reimplements configure().
0652      *
0653      * @since 4.4
0654      */
0655     void configurationDialogRejected();
0656 
0657 protected:
0658     /**
0659      * Creates an agent base.
0660      *
0661      * @param id The instance id of the agent.
0662      */
0663     AgentBase(const QString &id);
0664 
0665     /**
0666      * Destroys the agent base.
0667      */
0668     ~AgentBase() override;
0669 
0670     /**
0671      * This method is called whenever the agent application is about to
0672      * quit.
0673      *
0674      * Reimplement this method to do session cleanup (e.g. disconnecting
0675      * from groupware server).
0676      */
0677     virtual void aboutToQuit();
0678 
0679     /**
0680      * Returns the Akonadi::ChangeRecorder object used for monitoring.
0681      * Use this to configure which parts you want to monitor.
0682      */
0683     ChangeRecorder *changeRecorder() const;
0684 
0685     /**
0686      * Returns the config object for this Agent.
0687      */
0688     KSharedConfigPtr config();
0689 
0690     /**
0691      * Marks the current change as processes and replays the next change if change
0692      * recording is enabled (noop otherwise). This method is called
0693      * from the default implementation of the change notification slots. While not
0694      * required when not using change recording, it is nevertheless recommended
0695      * to call this method when done with processing a change notification.
0696      */
0697     void changeProcessed();
0698 
0699     /**
0700      * Returns whether the agent is currently online.
0701      */
0702     bool isOnline() const;
0703 
0704     /**
0705      * Sets whether the agent needs network or not.
0706      *
0707      * @since 4.2
0708      * @todo use this in combination with QNetworkConfiguration to change
0709      *       the onLine status of the agent.
0710      * @param needsNetwork @c true if the agents needs network. Defaults to @c false
0711      */
0712     void setNeedsNetwork(bool needsNetwork);
0713 
0714     /**
0715      * Sets whether the agent shall be online or not.
0716      */
0717     void setOnline(bool state);
0718 
0719 protected:
0720     /**
0721      * Sets the agent offline but will make it online again after a given time
0722      *
0723      * Use this method when the agent detects some problem with its backend but it wants
0724      * to retry all pending operations after some time - e.g. a server can not be reached currently
0725      *
0726      * Example usage:
0727      * @code
0728      * void ExampleResource::onItemRemovedFinished(KJob *job)
0729      * {
0730      *     if (job->error()) {
0731      *         Q_EMIT status(Broken, job->errorString());
0732      *         deferTask();
0733      *         setTemporaryOffline(300);
0734      *         return;
0735      *     }
0736      *     ...
0737      * }
0738      * @endcode
0739      *
0740      * @since 4.13
0741      * @param makeOnlineInSeconds timeout in seconds after which the agent changes to online
0742      */
0743     void setTemporaryOffline(int makeOnlineInSeconds = 300);
0744 
0745     /// @cond PRIVATE
0746     static void debugAgent(int argc, char **argv);
0747 
0748     std::unique_ptr<AgentBasePrivate> const d_ptr;
0749     explicit AgentBase(AgentBasePrivate *d, const QString &id);
0750     friend class ObserverV2;
0751     /// @endcond
0752 
0753     /**
0754      * This method is called whenever the @p online status has changed.
0755      * Reimplement this method to react on online status changes.
0756      * @param online online status
0757      */
0758     virtual void doSetOnline(bool online);
0759 
0760     virtual KAboutData aboutData() const;
0761 
0762 private:
0763     /// @cond PRIVATE
0764     static QString parseArguments(int argc, char **argv);
0765     static int init(AgentBase &r);
0766     void setOnlineInternal(bool state);
0767 
0768     // D-Bus interface stuff
0769     void abort();
0770     void reconfigure();
0771     void quit();
0772 
0773     // dbus agent interface
0774     friend class ::Akonadi__StatusAdaptor;
0775     friend class ::Akonadi__ControlAdaptor;
0776 
0777     Q_DECLARE_PRIVATE(AgentBase)
0778     Q_PRIVATE_SLOT(d_func(), void delayedInit())
0779     Q_PRIVATE_SLOT(d_func(), void slotStatus(int, const QString &))
0780     Q_PRIVATE_SLOT(d_func(), void slotPercent(int))
0781     Q_PRIVATE_SLOT(d_func(), void slotWarning(const QString &))
0782     Q_PRIVATE_SLOT(d_func(), void slotError(const QString &))
0783     Q_PRIVATE_SLOT(d_func(), void slotNetworkStatusChange(bool))
0784     Q_PRIVATE_SLOT(d_func(), void slotResumedFromSuspend())
0785     Q_PRIVATE_SLOT(d_func(), void slotTemporaryOfflineTimeout())
0786 
0787     /// @endcond
0788 };
0789 
0790 }
0791 
0792 #ifndef AKONADI_AGENT_MAIN
0793 /**
0794  * Convenience Macro for the most common main() function for Akonadi agents.
0795  */
0796 #define AKONADI_AGENT_MAIN(agentClass)                                                                                                                         \
0797     int main(int argc, char **argv)                                                                                                                            \
0798     {                                                                                                                                                          \
0799         return Akonadi::AgentBase::init<agentClass>(argc, argv);                                                                                               \
0800     }
0801 #endif