File indexing completed on 2024-05-19 05:16:11
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Christian Mollekopf <mollekopf@kolabsys.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 * 0006 */ 0007 0008 #pragma once 0009 0010 #include <KConfig> 0011 #include <KConfigGroup> 0012 #include <QFile> 0013 #include <QObject> 0014 0015 class NullableConfigGroup 0016 { 0017 public: 0018 NullableConfigGroup() = default; 0019 0020 explicit NullableConfigGroup(const KConfigGroup &grp) 0021 : mConfigGroup(grp) 0022 { 0023 } 0024 0025 KConfigGroup &configGroup() 0026 { 0027 return mConfigGroup; 0028 } 0029 0030 template<typename T> 0031 inline T readEntry(const QString &key, const T &aDefault) const 0032 { 0033 if (mConfigGroup.isValid()) { 0034 return mConfigGroup.readEntry<T>(key, aDefault); 0035 } 0036 return aDefault; 0037 } 0038 0039 template<typename T> 0040 inline void writeEntry(const QString &key, const T &value) 0041 { 0042 if (mConfigGroup.isValid()) { 0043 mConfigGroup.writeEntry<T>(key, value); 0044 } 0045 } 0046 0047 private: 0048 KConfigGroup mConfigGroup; 0049 }; 0050 0051 /** 0052 * Base class for generic migration jobs in akonadi. 0053 * 0054 * MigrationJobs can be run standalone from commandline using a small wrapper application or using the 0055 * Akonadi Migration Agent. 0056 * 0057 * Each migrator should assign a unique identifier for it's state (this identifier must never change). 0058 * 0059 * The work done by the migrator may be paused, and the migrator may persist it's state to resume migrations after a reboot. 0060 * 0061 * TODO: The migrator base ensures that no migrator can be run multiple times by locking it over dbus. 0062 * 0063 * The status is stored in the akonadi instance config directory, meaning the status is stored per akonadi instance. 0064 * This is the only reason why this MigratorBase is currently specific to akonadi migration jobs. 0065 */ 0066 class MigratorBase : public QObject 0067 { 0068 Q_OBJECT 0069 public: 0070 /** 0071 * Default constructor with default config and logfile 0072 */ 0073 explicit MigratorBase(const QString &identifier, QObject *parent = nullptr); 0074 0075 /** 0076 * Constructor that allows to inject a configfile and logfile. 0077 * 0078 * Pass and empty string to disable config and log. 0079 */ 0080 explicit MigratorBase(const QString &identifier, const QString &configFile, const QString &logFile, QObject *parent = nullptr); 0081 0082 ~MigratorBase() override; 0083 0084 QString identifier() const; 0085 0086 /** 0087 * Translated, human readable display name of migrator. 0088 */ 0089 virtual QString displayName() const; 0090 0091 /** 0092 * Translated, human readable description of migrator. 0093 */ 0094 virtual QString description() const; 0095 0096 /** 0097 * Returns the filename of the logfile used by this migrator. 0098 * 0099 * Returns QString() if there is no logfile set. 0100 */ 0101 QString logfile() const; 0102 0103 enum MigrationState { 0104 None, 0105 InProgress, 0106 Paused, 0107 Complete, 0108 NeedsUpdate, 0109 Aborted, 0110 Failed, 0111 }; 0112 0113 enum MessageType { 0114 Success, 0115 Skip, 0116 Info, 0117 Warning, 0118 Error, 0119 }; 0120 0121 /** 0122 * Read migration state. 0123 * 0124 * @return MigrationState. 0125 */ 0126 MigrationState migrationState() const; 0127 0128 /** 0129 * Return false if this job cannot start (i.e. due to missing dependencies). 0130 */ 0131 virtual bool canStart(); 0132 0133 /** 0134 * Mandatory updates that the Migration Agent should autostart should return true 0135 */ 0136 virtual bool shouldAutostart() const; 0137 0138 /** 0139 * Start migration. 0140 * 0141 * Implement startWork instead. 0142 * 0143 * Note that this will directly (blocking) call startWork(). 0144 */ 0145 void start(); 0146 0147 /** 0148 * Pause migration. 0149 */ 0150 virtual void pause(); 0151 0152 /** 0153 * Resume migration. 0154 */ 0155 virtual void resume(); 0156 0157 /** 0158 * Abort migration. 0159 */ 0160 virtual void abort(); 0161 0162 /** 0163 * progress in percent 0164 */ 0165 int progress() const; 0166 0167 /** 0168 * Status 0169 */ 0170 QString status() const; 0171 0172 Q_SIGNALS: 0173 // Signal for state changes 0174 void stateChanged(MigratorBase::MigrationState); 0175 0176 // Signal for log window 0177 void message(MigratorBase::MessageType type, const QString &msg); 0178 0179 // Signal for progress bar 0180 void progress(int progress); 0181 0182 // Signal for scheduling. The migrator has finished for some reason (success, failure, ...) and we can forget about it and move on. 0183 void stoppedProcessing(); 0184 0185 protected: 0186 /** 0187 * Reimplement to start work. 0188 */ 0189 virtual void startWork() = 0; 0190 0191 void setMigrationState(MigratorBase::MigrationState state); 0192 0193 void setProgress(int); 0194 0195 private Q_SLOTS: 0196 /** 0197 * Logs a message, that appears in the logfile and potentially in a log window. 0198 * Do not call this directly. Emit the message signal instead, which is connected to this slot. 0199 */ 0200 void logMessage(MigratorBase::MessageType type, const QString &msg); 0201 0202 private: 0203 NullableConfigGroup config(); 0204 void saveState(); 0205 void loadState(); 0206 0207 void setLogfile(const QString &); 0208 0209 const QString mIdentifier; 0210 MigrationState mMigrationState = None; 0211 QScopedPointer<QFile> mLogFile; 0212 QScopedPointer<KConfig> mConfig; 0213 int mProgress; 0214 }; 0215 0216 Q_DECLARE_METATYPE(MigratorBase::MigrationState)