File indexing completed on 2024-03-24 05:52:50
0001 //************************************************************************** 0002 // Copyright 2006 - 2023 Martin Koller, kollix@aon.at 0003 // 0004 // This program is free software; you can redistribute it and/or modify 0005 // it under the terms of the GNU General Public License as published by 0006 // the Free Software Foundation, version 2 of the License 0007 // 0008 //************************************************************************** 0009 0010 #ifndef _ARCHIVER_H_ 0011 #define _ARCHIVER_H_ 0012 0013 // the class which does the archiving 0014 0015 #include <QObject> 0016 #include <QPointer> 0017 #include <QSet> 0018 #include <QElapsedTimer> 0019 #include <QTime> 0020 #include <QDateTime> 0021 #include <QStringList> 0022 #include <QList> 0023 #include <QRegExp> 0024 0025 #include <QUrl> 0026 #include <kio/global.h> 0027 #include <kio/copyjob.h> 0028 #include <kio/udsentry.h> 0029 #include <KCompressionDevice> 0030 0031 class QDir; 0032 class QFileInfo; 0033 class QFile; 0034 0035 0036 class Archiver : public QObject 0037 { 0038 Q_OBJECT 0039 0040 public: 0041 explicit Archiver(QWidget *parent); 0042 0043 static Archiver *instance; 0044 0045 // always call after you have already set maxSliceMBs, as the sliceCapacity 0046 // might be limited with it 0047 void setTarget(const QUrl &target); 0048 const QUrl &getTarget() const { return targetURL; } 0049 0050 enum { UNLIMITED = 0 }; 0051 void setMaxSliceMBs(int mbs); 0052 int getMaxSliceMBs() const { return maxSliceMBs; } 0053 0054 void setFilePrefix(const QString &prefix); 0055 const QString &getFilePrefix() const { return filePrefix; } 0056 0057 void setMediaNeedsChange(bool b) { mediaNeedsChange = b; } 0058 bool getMediaNeedsChange() const { return mediaNeedsChange; } 0059 0060 void setCompressFiles(bool b); 0061 bool getCompressFiles() const { return !ext.isEmpty(); } 0062 0063 // number of backups to keep before older ones will be deleted (UNLIMITED or 1..n) 0064 void setKeptBackups(int num); 0065 int getKeptBackups() const { return numKeptBackups; } 0066 0067 // define a filename filter in wildcard format each separated with a space 0068 // e.g. "*.png *.ogg" 0069 void setFilter(const QString &filter); 0070 QString getFilter() const; 0071 0072 // define a list of path wildcards to filter complete dirs, separated by newline 0073 void setDirFilter(const QString &filter); 0074 QString getDirFilter() const; 0075 0076 // interval for a full backup instead differential backup; when 1 given == full backup 0077 void setFullBackupInterval(int days); 0078 int getFullBackupInterval() const { return fullBackupInterval; } 0079 0080 const QDateTime &getLastFullBackup() const { return lastFullBackup; } 0081 const QDateTime &getLastBackup() const { return lastBackup; } 0082 0083 // when manually saving a profile, we need to restart the backup (incremental) cycle 0084 void resetBackupCycle(); 0085 0086 // print every single file/dir in non-interactive mode 0087 void setVerbose(bool b) { verbose = b; } 0088 0089 // loads the profile into the Archiver and returns includes/excludes lists 0090 // return true if loaded, false on file open error 0091 bool loadProfile(const QString &fileName, QStringList &includes, QStringList &excludes, QString &error); 0092 void setLoadedProfile(const QString &fileName) { loadedProfile = fileName; } 0093 0094 bool saveProfile(const QString &fileName, const QStringList &includes, const QStringList &excludes, QString &error); 0095 0096 // return true if the backup completed successfully, else false 0097 bool createArchive(const QStringList &includes, const QStringList &excludes); 0098 0099 KIO::filesize_t getTotalBytes() const { return totalBytes; } 0100 int getTotalFiles() const { return totalFiles; } 0101 0102 bool isInProgress() const { return runs; } 0103 0104 static bool getDiskFree(const QString &path, KIO::filesize_t &capacityBytes, KIO::filesize_t &freeBytes); 0105 0106 // TODO: put probably in some global settings object 0107 static QString sliceScript; 0108 0109 public Q_SLOTS: 0110 void cancel(); // cancel a running creation 0111 void setForceFullBackup(bool force = true); 0112 0113 Q_SIGNALS: 0114 void inProgress(bool runs); 0115 void logging(const QString &); 0116 void warning(const QString &); 0117 void targetCapacity(KIO::filesize_t bytes); 0118 void sliceProgress(int percent); 0119 void fileProgress(int percent); 0120 void newSlice(int); 0121 void totalFilesChanged(int); 0122 void totalBytesChanged(KIO::filesize_t); 0123 void elapsedChanged(const QTime &); 0124 void backupTypeChanged(bool incremental); 0125 0126 private Q_SLOTS: 0127 void slotResult(KJob *); 0128 void slotListResult(KIO::Job *, const KIO::UDSEntryList &); 0129 void receivedOutput(); 0130 void loggingSlot(const QString &message); // for non-interactive output 0131 void warningSlot(const QString &message); // for non-interactive output 0132 void updateElapsed(); 0133 0134 private: 0135 void calculateCapacity(); // also emits signals 0136 void addDirFiles(QDir &dir); 0137 void addFile(const QFileInfo &info); 0138 0139 enum AddFileStatus { Error, Added, Skipped }; 0140 AddFileStatus addLocalFile(const QFileInfo &info, struct archive_entry *entry); 0141 0142 bool compressFile(const QString &origName, QFile &comprFile); 0143 0144 void finishSlice(); 0145 bool getNextSlice(); 0146 0147 void runScript(const QString &mode); 0148 void setIncrementalBackup(bool inc); 0149 0150 // returns true if the next backup will be an incremental one, false for a full backup 0151 bool isIncrementalBackup() const { return !forceFullBackup && incrementalBackup; } 0152 0153 // return true if given fileName matches any of the defined filters 0154 bool fileIsFiltered(const QString &fileName) const; 0155 0156 void emitArchiveError(); 0157 0158 static bool UDSlessThan(const KIO::UDSEntry &left, const KIO::UDSEntry &right); 0159 0160 private: 0161 QSet<QString> excludeFiles; 0162 QSet<QString> excludeDirs; 0163 0164 QString archiveName; 0165 QString filePrefix; // default = "backup" 0166 QStringList sliceList; 0167 QString loadedProfile; 0168 0169 struct archive *archive = nullptr; 0170 KIO::filesize_t totalBytes = 0; 0171 int totalFiles = 0; 0172 int filteredFiles = 0; // filter or time filter (incremental backup) 0173 QElapsedTimer elapsed; 0174 0175 QList<QRegExp> filters; 0176 QList<QRegExp> dirFilters; 0177 0178 QUrl targetURL; 0179 QString baseName; 0180 int sliceNum = 0; 0181 int maxSliceMBs = Archiver::UNLIMITED; 0182 bool mediaNeedsChange = false; 0183 0184 int numKeptBackups = Archiver::UNLIMITED; 0185 KIO::UDSEntryList targetDirList; 0186 0187 QDateTime lastFullBackup; 0188 QDateTime lastBackup; 0189 int fullBackupInterval = 1; 0190 bool incrementalBackup = false; 0191 bool forceFullBackup = false; 0192 0193 KIO::filesize_t sliceBytes = 0; 0194 KIO::filesize_t sliceCapacity = 0; 0195 0196 QString ext; 0197 KCompressionDevice::CompressionType compressionType = KCompressionDevice::None; 0198 0199 bool interactive; 0200 bool cancelled = false; 0201 bool runs = false; 0202 bool skippedFiles = false; // did we skip files during backup ? 0203 bool verbose = false; 0204 0205 QPointer<KIO::CopyJob> job; 0206 int jobResult = 0; 0207 }; 0208 0209 #endif