File indexing completed on 2024-11-24 04:44:36

0001 /*
0002     SPDX-FileCopyrightText: 2008 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "akonadi-singlefileresource_export.h"
0010 #include <Akonadi/ResourceBase>
0011 
0012 #include <QStringList>
0013 #include <QUrl>
0014 
0015 namespace KIO
0016 {
0017 class FileCopyJob;
0018 class Job;
0019 }
0020 
0021 namespace Akonadi
0022 {
0023 /**
0024  * Base class for single file based resources.
0025  * @see SingleFileResource
0026  */
0027 class AKONADI_SINGLEFILERESOURCE_EXPORT SingleFileResourceBase : public ResourceBase, public AgentBase::Observer
0028 {
0029     Q_OBJECT
0030 public:
0031     explicit SingleFileResourceBase(const QString &id);
0032 
0033     /**
0034      * Set the mimetypes supported by this resource and an optional icon for the collection.
0035      */
0036     void setSupportedMimetypes(const QStringList &mimeTypes, const QString &icon = QString());
0037 
0038     void collectionChanged(const Akonadi::Collection &collection) override;
0039 
0040 public Q_SLOTS:
0041     void reloadFile();
0042 
0043     /*
0044      * Read the current state from a file. This can happen
0045      * from direct callers, or as part of a scheduled task.
0046      * @p taskContext specifies whether the method is being
0047      * called from within a task or not.
0048      */
0049     virtual void readFile(bool taskContext = false) = 0;
0050     /*
0051      * Writes the current state out to a file. This can happen
0052      * from direct callers, or as part of a scheduled task.
0053      * @p taskContext specifies whether the method is being
0054      * called from within a task or not.
0055      */
0056     virtual void writeFile(bool taskContext = false) = 0;
0057 
0058     /*
0059      * Same method as above, but uses a QVariant so it can
0060      * be called from Akonadi::ResourceScheduler.
0061      */
0062     virtual void writeFile(const QVariant &taskContext) = 0;
0063 
0064 protected:
0065     /**
0066      * Implement in derived classes to do things when the configuration changes
0067      * before reload file is called.
0068      */
0069     virtual void applyConfigurationChanges();
0070 
0071     /**
0072      * Returns a pointer to the KConfig object which is used to store runtime
0073      * information of the resource.
0074      */
0075     KSharedConfig::Ptr runtimeConfig() const;
0076 
0077     /**
0078      * Handles everything needed when the hash of a file has changed between the
0079      * last write and the first read. This stores the new hash in a config file
0080      * and notifies implementing resources to handle a hash change if the
0081      * previous known hash was not empty. Finally this method clears the cache
0082      * and calls synchronize.
0083      * Returns true on success, false otherwise.
0084      */
0085     bool readLocalFile(const QString &fileName);
0086 
0087     /**
0088      * Reimplement to read your data from the given file.
0089      * The file is always local, loading from the network is done
0090      * automatically if needed.
0091      */
0092     virtual bool readFromFile(const QString &fileName) = 0;
0093 
0094     /**
0095      * Reimplement to write your data to the given file.
0096      * The file is always local, storing back to the network url is done
0097      * automatically when needed.
0098      */
0099     virtual bool writeToFile(const QString &fileName) = 0;
0100 
0101     /**
0102      * It is not always needed to parse the file when a resources is started.
0103      * (e.g. When the hash of the file is the same as the last time the resource
0104      * has written changes to the file). In this case setActualFileName is
0105      * called so that the implementing resource does know which file to read
0106      * when it actually needs to read the file.
0107      *
0108      * The default implementation will just call readFromFile( fileName ), so
0109      * implementing resources will have to explicitly reimplement this method to
0110      * actually get any profit of this.
0111      *
0112      * @p fileName This will always be a path to a local file.
0113      */
0114     virtual void setLocalFileName(const QString &fileName);
0115 
0116     /**
0117      * Generates the full path for the cache file in the case that a remote file
0118      * is used.
0119      */
0120     QString cacheFile() const;
0121 
0122     /**
0123      * Calculates an MD5 hash for given file. If the file does not exists
0124      * or the path is empty, this will return an empty QByteArray.
0125      */
0126     QByteArray calculateHash(const QString &fileName) const;
0127 
0128     /**
0129      * This method is called when the hash of the file has changed between the
0130      * last writeFile() and a readFile() call. This means that the file was
0131      * changed by another program.
0132      *
0133      * Note: This method is <em>not</em> called when the last known hash is
0134      *       empty. In that case it is assumed that the file is loaded for the
0135      *       first time.
0136      */
0137     virtual void handleHashChange();
0138 
0139     /**
0140      * Returns the hash that was stored to a cache file.
0141      */
0142     QByteArray loadHash() const;
0143 
0144     /**
0145      * Stores the given hash into a cache file.
0146      */
0147     void saveHash(const QByteArray &hash) const;
0148 
0149     /**
0150      * Returns whether the resource can be written to.
0151      */
0152     virtual bool readOnly() const = 0;
0153 
0154     /**
0155      * Returns the collection of this resource.
0156      */
0157     virtual Collection rootCollection() const = 0;
0158 
0159 protected:
0160     QUrl mCurrentUrl;
0161     QStringList mSupportedMimetypes;
0162     QString mCollectionIcon;
0163     KIO::FileCopyJob *mDownloadJob = nullptr;
0164     KIO::FileCopyJob *mUploadJob = nullptr;
0165     QByteArray mCurrentHash;
0166 
0167 protected Q_SLOTS:
0168     void scheduleWrite(); /// Called when changes are added to the ChangeRecorder.
0169     void handleProgress(KJob *, unsigned long);
0170     void fileChanged(const QString &fileName);
0171     void slotDownloadJobResult(KJob *);
0172     void slotUploadJobResult(KJob *);
0173 };
0174 }