File indexing completed on 2025-01-05 04:29:54
0001 /** 0002 * SPDX-FileCopyrightText: 2021 Tobias Fella <tobias.fella@kde.org> 0003 * SPDX-FileCopyrightText: 2021 Bart De Vries <bart@mogwai.be> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0006 */ 0007 0008 #pragma once 0009 0010 #include <QObject> 0011 #include <QQmlEngine> 0012 0013 #include <KFormat> 0014 0015 #include "error.h" 0016 #include "sync/syncutils.h" 0017 0018 namespace QKeychain 0019 { 0020 class WritePasswordJob; 0021 class DeletePasswordJob; 0022 } 0023 0024 class GPodder; 0025 0026 class Sync : public QObject 0027 { 0028 Q_OBJECT 0029 QML_ELEMENT 0030 QML_SINGLETON 0031 0032 Q_PROPERTY(bool syncEnabled READ syncEnabled WRITE setSyncEnabled NOTIFY syncEnabledChanged) 0033 Q_PROPERTY(QString username READ username NOTIFY credentialsChanged) 0034 Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY credentialsChanged) 0035 Q_PROPERTY(QString device READ device WRITE setDevice NOTIFY deviceChanged) 0036 Q_PROPERTY(QString deviceName READ deviceName WRITE setDeviceName NOTIFY deviceNameChanged) 0037 Q_PROPERTY(QString hostname READ hostname WRITE setHostname NOTIFY hostnameChanged) 0038 Q_PROPERTY(SyncUtils::Provider provider READ provider WRITE setProvider NOTIFY providerChanged) 0039 0040 Q_PROPERTY(QString suggestedDevice READ suggestedDevice CONSTANT) 0041 Q_PROPERTY(QString suggestedDeviceName READ suggestedDeviceName CONSTANT) 0042 Q_PROPERTY(QVector<SyncUtils::Device> deviceList READ deviceList NOTIFY deviceListReceived) 0043 0044 Q_PROPERTY(SyncUtils::SyncStatus syncStatus MEMBER m_syncStatus NOTIFY syncProgressChanged) 0045 Q_PROPERTY(int syncProgress MEMBER m_syncProgress NOTIFY syncProgressChanged) 0046 Q_PROPERTY(int syncProgressTotal MEMBER m_syncProgressTotal CONSTANT) 0047 Q_PROPERTY(QString syncProgressText MEMBER m_syncProgressText NOTIFY syncProgressChanged) 0048 Q_PROPERTY(QString lastSuccessfulDownloadSync READ lastSuccessfulDownloadSync NOTIFY syncProgressChanged) 0049 Q_PROPERTY(QString lastSuccessfulUploadSync READ lastSuccessfulUploadSync NOTIFY syncProgressChanged) 0050 0051 public: 0052 static Sync &instance() 0053 { 0054 static Sync _instance; 0055 return _instance; 0056 } 0057 static Sync *create(QQmlEngine *engine, QJSEngine *) 0058 { 0059 engine->setObjectOwnership(&instance(), QQmlEngine::CppOwnership); 0060 return &instance(); 0061 } 0062 0063 bool syncEnabled() const; 0064 QString username() const; 0065 QString password() const; 0066 QString device() const; 0067 QString deviceName() const; 0068 QString hostname() const; 0069 SyncUtils::Provider provider() const; 0070 QString lastSuccessfulSync(const QStringList &matchingLabels = {}) const; 0071 QString lastSuccessfulDownloadSync() const; 0072 QString lastSuccessfulUploadSync() const; 0073 0074 QString suggestedDevice() const; 0075 QString suggestedDeviceName() const; 0076 QVector<SyncUtils::Device> deviceList() const; 0077 0078 void setSyncEnabled(bool status); 0079 void setPassword(const QString &password); 0080 void setDevice(const QString &device); 0081 void setDeviceName(const QString &deviceName); 0082 void setHostname(const QString &hostname); 0083 void setProvider(const SyncUtils::Provider provider); 0084 0085 Q_INVOKABLE void login(const QString &username, const QString &password); 0086 Q_INVOKABLE void retrieveCredentialsFromConfig(); 0087 Q_INVOKABLE void logout(); 0088 Q_INVOKABLE void registerNewDevice(const QString &id, const QString &caption, const QString &type = QStringLiteral("other")); 0089 Q_INVOKABLE void linkUpAllDevices(); 0090 0091 void doSync(SyncUtils::SyncStatus status, bool forceFetchAll = false); // base method for syncing 0092 Q_INVOKABLE void doRegularSync(bool forceFetchAll = false); // regular sync; can be forced to update all feeds 0093 Q_INVOKABLE void doForceSync(); // force a full re-sync with the server; discarding local eposide acions 0094 Q_INVOKABLE void doSyncPushAll(); // upload all local episode states to the server; this will likely overwrite all actions stored on the server 0095 Q_INVOKABLE void doQuickSync(); // only upload pending local episode actions; intended to be run directly after an episode action has been created 0096 0097 // Next are some generic methods to store and apply local changes to be synced 0098 void storeAddFeedAction(const QString &url); 0099 void storeRemoveFeedAction(const QString &url); 0100 void storePlayEpisodeAction(const QString &id, const qulonglong started, const qulonglong position); 0101 void storePlayedEpisodeAction(const QString &id); 0102 void applySubscriptionChangesLocally(const QStringList &addList, const QStringList &removeList); 0103 void applyEpisodeActionsLocally(const QHash<QString, QHash<QString, SyncUtils::EpisodeAction>> &episodeActionHash); 0104 0105 Q_SIGNALS: 0106 void syncEnabledChanged(); 0107 void credentialsChanged(); 0108 void deviceChanged(); 0109 void deviceNameChanged(); 0110 void hostnameChanged(); 0111 void providerChanged(); 0112 void deviceCreated(); 0113 0114 void passwordSaveFinished(bool success); 0115 void passwordRetrievalFinished(QString password); 0116 void passwordInputRequired(); 0117 0118 void loginSucceeded(); 0119 void deviceListReceived(); 0120 0121 void error(Error::Type type, const QString &url, const QString &id, const int errorId, const QString &errorString, const QString &title); 0122 void syncProgressChanged(); 0123 void abortSync(); 0124 0125 private: 0126 Sync(); 0127 0128 void clearSettings(); 0129 void savePasswordToKeyChain(const QString &username, const QString &password); 0130 void savePasswordToFile(const QString &username, const QString &password); 0131 void retrievePasswordFromKeyChain(const QString &username); 0132 QString retrievePasswordFromFile(const QString &username); 0133 void deletePasswordFromKeychain(const QString &username); 0134 0135 void retrieveAllLocalEpisodeStates(); 0136 void onWriteDummyJobFinished(QKeychain::WritePasswordJob *writeDummyJob, const QString &username); 0137 void onWritePasswordJobFinished(QKeychain::WritePasswordJob *job, const QString &username, const QString &password); 0138 void onDeleteJobFinished(QKeychain::DeletePasswordJob *deleteJob, const QString &username); 0139 0140 GPodder *m_gpodder = nullptr; 0141 0142 bool m_syncEnabled; 0143 QString m_username; 0144 QString m_password; 0145 QString m_device; 0146 QString m_deviceName; 0147 QString m_hostname; 0148 SyncUtils::Provider m_provider; 0149 0150 QVector<SyncUtils::Device> m_deviceList; 0151 0152 KFormat m_kformat; 0153 0154 // variables needed for linkUpAllDevices() 0155 QStringList m_syncUpAllSubscriptions; 0156 int m_deviceResponses; 0157 0158 // internal variables used while syncing 0159 bool m_allowSyncActionLogging = true; 0160 0161 // internal variables used for UI notifications 0162 SyncUtils::SyncStatus m_syncStatus = SyncUtils::SyncStatus::NoSync; 0163 int m_syncProgress = 0; 0164 int m_syncProgressTotal = 7; 0165 QString m_syncProgressText = QLatin1String(""); 0166 };