File indexing completed on 2024-11-17 04:44:59

0001 /*
0002     SPDX-FileCopyrightText: 2015-2020 Krzysztof Nowicki <krissn@op.pl>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QQueue>
0010 #include <QScopedPointer>
0011 
0012 #include <Akonadi/ResourceBase>
0013 #include <Akonadi/TransportResourceBase>
0014 
0015 #include "ewsclient.h"
0016 #include "ewsfetchitemsjob.h"
0017 #include "ewsid.h"
0018 
0019 #include <ewsconfig.h>
0020 
0021 class FetchItemState;
0022 class EwsAbstractAuth;
0023 class EwsSubscriptionManager;
0024 class EwsTagStore;
0025 class EwsSettings;
0026 class KNotification;
0027 
0028 class EwsResource : public Akonadi::ResourceBase, public Akonadi::AgentBase::ObserverV4, public Akonadi::TransportResourceBase
0029 {
0030     Q_OBJECT
0031     Q_CLASSINFO("D-Bus Interface", "org.kde.Akonadi.Ews.Resource")
0032 public:
0033     static const QString akonadiEwsPropsetUuid;
0034     static const EwsPropertyField globalTagsProperty;
0035     static const EwsPropertyField globalTagsVersionProperty;
0036     static const EwsPropertyField tagsProperty;
0037     static const EwsPropertyField flagsProperty;
0038 
0039     explicit EwsResource(const QString &id);
0040     ~EwsResource() override;
0041 
0042     void itemsTagsChanged(const Akonadi::Item::List &items, const QSet<Akonadi::Tag> &addedTags, const QSet<Akonadi::Tag> &removedTags) override;
0043     void tagAdded(const Akonadi::Tag &tag) override;
0044     void tagChanged(const Akonadi::Tag &tag) override;
0045     void tagRemoved(const Akonadi::Tag &tag) override;
0046 
0047     void collectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &parent) override;
0048     void collectionMoved(const Akonadi::Collection &collection,
0049                          const Akonadi::Collection &collectionSource,
0050                          const Akonadi::Collection &collectionDestination) override;
0051     void collectionChanged(const Akonadi::Collection &collection, const QSet<QByteArray> &changedAttributes) override;
0052     void collectionChanged(const Akonadi::Collection &collection) override;
0053     void collectionRemoved(const Akonadi::Collection &collection) override;
0054     void itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection) override;
0055     void itemChanged(const Akonadi::Item &item, const QSet<QByteArray> &partIdentifiers) override;
0056     void itemsFlagsChanged(const Akonadi::Item::List &items, const QSet<QByteArray> &addedFlags, const QSet<QByteArray> &removedFlags) override;
0057     void itemsMoved(const Akonadi::Item::List &items, const Akonadi::Collection &sourceCollection, const Akonadi::Collection &destinationCollection) override;
0058     void itemsRemoved(const Akonadi::Item::List &items) override;
0059 
0060     void sendItem(const Akonadi::Item &item) override;
0061 
0062     const Akonadi::Collection &rootCollection() const
0063     {
0064         return mRootCollection;
0065     }
0066 
0067     EwsSettings *settings()
0068     {
0069         return mSettings.data();
0070     }
0071 
0072 protected:
0073     void doSetOnline(bool online) override;
0074 public Q_SLOTS:
0075     void configure(WId windowId) override;
0076     Q_SCRIPTABLE void clearCollectionSyncState(int collectionId);
0077     Q_SCRIPTABLE void clearFolderTreeSyncState();
0078     Q_SCRIPTABLE void setInitialReconnectTimeout(int timeout);
0079 protected Q_SLOTS:
0080     void retrieveCollections() override;
0081     void retrieveItems(const Akonadi::Collection &collection) override;
0082     bool retrieveItems(const Akonadi::Item::List &items, const QSet<QByteArray> &parts) override;
0083     void retrieveTags() override;
0084     QString dumpResourceToString() const override;
0085 private Q_SLOTS:
0086     void fetchFoldersJobFinished(KJob *job);
0087     void fetchFoldersIncrJobFinished(KJob *job);
0088     void itemFetchJobFinished(KJob *job);
0089     void getItemsRequestFinished(KJob *job);
0090     void itemChangeRequestFinished(KJob *job);
0091     void itemModifyFlagsRequestFinished(KJob *job);
0092     void itemMoveRequestFinished(KJob *job);
0093     void itemDeleteRequestFinished(KJob *job);
0094     void itemCreateRequestFinished(KJob *job);
0095     void itemSendRequestFinished(KJob *job);
0096     void folderCreateRequestFinished(KJob *job);
0097     void folderMoveRequestFinished(KJob *job);
0098     void folderUpdateRequestFinished(KJob *job);
0099     void folderDeleteRequestFinished(KJob *job);
0100     void delayedInit();
0101     void foldersModifiedEvent(const EwsId::List &folders);
0102     void foldersModifiedCollectionSyncFinished(KJob *job);
0103     void folderTreeModifiedEvent();
0104     void fullSyncRequestedEvent();
0105     void rootFolderFetchFinished(KJob *job);
0106     void specialFoldersFetchFinished(KJob *job);
0107     void itemsTagChangeFinished(KJob *job);
0108     void globalTagChangeFinished(KJob *job);
0109     void globalTagsRetrievalFinished(KJob *job);
0110     void adjustInboxRemoteIdFetchFinished(KJob *job);
0111     void rootCollectionFetched(KJob *job);
0112     void connectionError();
0113     void reloadConfig();
0114     void authSucceeded();
0115     void authFailed(const QString &error);
0116     void requestAuthFailed();
0117     void emitReadyStatus();
0118     void adjustRootCollectionName(const QString &newName);
0119 public Q_SLOTS:
0120     Q_SCRIPTABLE void sendMessage(const QString &id, const QByteArray &content);
0121 Q_SIGNALS:
0122     Q_SCRIPTABLE void messageSent(const QString &id, const QString &error);
0123 #if HAVE_SEPARATE_MTA_RESOURCE
0124 private Q_SLOTS:
0125     void messageSendRequestFinished(KJob *job);
0126 #endif
0127 
0128 private:
0129     enum AuthStage { AuthIdle, AuthRefreshToken, AuthAccessToken, AuthFailure };
0130 
0131     enum QueuedFetchItemsJobType { RetrieveItems, SubscriptionSync };
0132 
0133     void finishItemsFetch(FetchItemState *state);
0134     void fetchSpecialFolders();
0135     void specialFoldersCollectionsRetrieved(const Akonadi::Collection::List &folders);
0136 
0137     void saveState();
0138     void resetUrl();
0139 
0140     void doRetrieveCollections();
0141 
0142     int reconnectTimeout();
0143     void setUpAuth();
0144     void reauthNotificationDismissed(bool accepted);
0145     void reauthenticate();
0146 
0147     static QString getCollectionSyncState(const Akonadi::Collection &col);
0148     static void saveCollectionSyncState(Akonadi::Collection &col, const QString &state);
0149 
0150     void queueFetchItemsJob(const Akonadi::Collection &col, QueuedFetchItemsJobType type, const std::function<void(EwsFetchItemsJob *)> &startFn);
0151     void startFetchItemsJob(const Akonadi::Collection &col, std::function<void(EwsFetchItemsJob *)> startFn);
0152     void dequeueFetchItemsJob();
0153 
0154     template<class Job>
0155     void connectStatusSignals(Job *job);
0156 
0157     EwsClient mEwsClient;
0158     Akonadi::Collection mRootCollection;
0159     QScopedPointer<EwsSubscriptionManager> mSubManager;
0160     QString mFolderSyncState;
0161     QHash<QString, EwsId::List> mItemsToCheck;
0162     QString mPassword;
0163     QScopedPointer<EwsAbstractAuth> mAuth;
0164     AuthStage mAuthStage;
0165     QPointer<KNotification> mReauthNotification;
0166 
0167     bool mTagsRetrieved = false;
0168     int mReconnectTimeout;
0169     int mInitialReconnectTimeout;
0170     EwsTagStore *mTagStore = nullptr;
0171     QScopedPointer<EwsSettings> mSettings;
0172 
0173     struct QueuedFetchItemsJob {
0174         Akonadi::Collection col;
0175         QueuedFetchItemsJobType type;
0176         std::function<void(EwsFetchItemsJob *)> startFn;
0177     };
0178     QQueue<QueuedFetchItemsJob> mFetchItemsJobQueue;
0179 };