1 //**************************************************************************
2 //   Copyright 2006 - 2017 Martin Koller, kollix@aon.at
3 //
4 //   This program is free software; you can redistribute it and/or modify
5 //   it under the terms of the GNU General Public License as published by
6 //   the Free Software Foundation, version 2 of the License
7 //
8 //**************************************************************************
9 
10 #ifndef _ARCHIVER_H_
11 #define _ARCHIVER_H_
12 
13 // the class which does the archiving
14 
15 #include <QObject>
16 #include <QPointer>
17 #include <QSet>
18 #include <QElapsedTimer>
19 #include <QTime>
20 #include <QDateTime>
21 #include <QStringList>
22 #include <QList>
23 #include <QRegExp>
24 
25 #include <QUrl>
26 #include <kio/copyjob.h>
27 #include <kio/udsentry.h>
28 #include <KCompressionDevice>
29 
30 class KTar;
31 class QDir;
32 class QFileInfo;
33 class QFile;
34 
35 
36 class Archiver : public QObject
37 {
38   Q_OBJECT
39 
40   public:
41     explicit Archiver(QWidget *parent);
42 
43     static Archiver *instance;
44 
45     // always call after you have already set maxSliceMBs, as the sliceCapacity
46     // might be limited with it
47     void setTarget(const QUrl &target);
getTarget() const48     const QUrl &getTarget() const { return targetURL; }
49 
50     enum { UNLIMITED = 0 };
51     void setMaxSliceMBs(int mbs);
getMaxSliceMBs() const52     int getMaxSliceMBs() const { return maxSliceMBs; }
53 
54     void setFilePrefix(const QString &prefix);
getFilePrefix() const55     const QString &getFilePrefix() const { return filePrefix; }
56 
setMediaNeedsChange(bool b)57     void setMediaNeedsChange(bool b) { mediaNeedsChange = b; }
getMediaNeedsChange() const58     bool getMediaNeedsChange() const { return mediaNeedsChange; }
59 
60     void setCompressFiles(bool b);
getCompressFiles() const61     bool getCompressFiles() const { return !ext.isEmpty(); }
62 
63     // number of backups to keep before older ones will be deleted (UNLIMITED or 1..n)
64     void setKeptBackups(int num);
getKeptBackups() const65     int getKeptBackups() const { return numKeptBackups; }
66 
67     // define a filename filter in wildcard format each separated with a space
68     // e.g. "*.png *.ogg"
69     void setFilter(const QString &filter);
70     QString getFilter() const;
71 
72     // define a list of path wildcards to filter complete dirs, separated by newline
73     void setDirFilter(const QString &filter);
74     QString getDirFilter() const;
75 
76     // interval for a full backup instead differential backup; when 1 given == full backup
77     void setFullBackupInterval(int days);
getFullBackupInterval() const78     int getFullBackupInterval() const { return fullBackupInterval; }
79 
getLastFullBackup() const80     const QDateTime &getLastFullBackup() const { return lastFullBackup; }
getLastBackup() const81     const QDateTime &getLastBackup() const { return lastBackup; }
82 
83     // print every single file/dir in non-interactive mode
setVerbose(bool b)84     void setVerbose(bool b) { verbose = b; }
85 
86     // loads the profile into the Archiver and returns includes/excludes lists
87     // return true if loaded, false on file open error
88     bool loadProfile(const QString &fileName, QStringList &includes, QStringList &excludes, QString &error);
setLoadedProfile(const QString & fileName)89     void setLoadedProfile(const QString &fileName) { loadedProfile = fileName; }
90 
91     bool saveProfile(const QString &fileName, const QStringList &includes, const QStringList &excludes, QString &error);
92 
93     // return true if the backup completed successfully, else false
94     bool createArchive(const QStringList &includes, const QStringList &excludes);
95 
getTotalBytes() const96     KIO::filesize_t getTotalBytes() const { return totalBytes; }
getTotalFiles() const97     int getTotalFiles() const { return totalFiles; }
98 
isInProgress() const99     bool isInProgress() const { return runs; }
100 
101     static bool getDiskFree(const QString &path, KIO::filesize_t &capacityBytes, KIO::filesize_t &freeBytes);
102 
103     // TODO: put probably in some global settings object
104     static QString sliceScript;
105 
106   public Q_SLOTS:
107     void cancel();  // cancel a running creation
108     void setForceFullBackup(bool force = true);
109 
110   Q_SIGNALS:
111     void inProgress(bool runs);
112     void logging(const QString &);
113     void warning(const QString &);
114     void targetCapacity(KIO::filesize_t bytes);
115     void sliceProgress(int percent);
116     void fileProgress(int percent);
117     void newSlice(int);
118     void totalFilesChanged(int);
119     void totalBytesChanged(KIO::filesize_t);
120     void elapsedChanged(const QTime &);
121     void backupTypeChanged(bool incremental);
122 
123   private Q_SLOTS:
124     void slotResult(KJob *);
125     void slotListResult(KIO::Job *, const KIO::UDSEntryList &);
126     void receivedOutput();
127     void loggingSlot(const QString &message); // for non-interactive output
128     void warningSlot(const QString &message); // for non-interactive output
129     void updateElapsed();
130 
131   private:
132     void calculateCapacity();  // also emits signals
133     void addDirFiles(QDir &dir);
134     void addFile(const QFileInfo &info);
135 
136     enum AddFileStatus { Error, Added, Skipped };
137     AddFileStatus addLocalFile(const QFileInfo &info);
138 
139     bool compressFile(const QString &origName, QFile &comprFile);
140 
141     void finishSlice();
142     bool getNextSlice();
143 
144     void runScript(const QString &mode);
145     void setIncrementalBackup(bool inc);
146 
147     // returns true if the next backup will be an incremental one, false for a full backup
isIncrementalBackup() const148     bool isIncrementalBackup() const { return !forceFullBackup && incrementalBackup; }
149 
150     // return true if given fileName matches any of the defined filters
151     bool fileIsFiltered(const QString &fileName) const;
152 
153     void emitArchiveError();
154 
155     static bool UDSlessThan(const KIO::UDSEntry &left, const KIO::UDSEntry &right);
156 
157   private:
158     QSet<QString> excludeFiles;
159     QSet<QString> excludeDirs;
160 
161     QString archiveName;
162     QString filePrefix;  // default = "backup"
163     QStringList sliceList;
164     QString loadedProfile;
165 
166     KTar *archive;
167     KIO::filesize_t totalBytes;
168     int totalFiles;
169     int filteredFiles;  // filter or time filter (incremental backup)
170     QElapsedTimer elapsed;
171 
172     QList<QRegExp> filters;
173     QList<QRegExp> dirFilters;
174 
175     QUrl targetURL;
176     QString baseName;
177     int sliceNum;
178     int maxSliceMBs;
179     bool mediaNeedsChange;
180     bool compressFiles;
181 
182     int numKeptBackups;
183     KIO::UDSEntryList targetDirList;
184 
185     QDateTime lastFullBackup;
186     QDateTime lastBackup;
187     int fullBackupInterval;
188     bool incrementalBackup;
189     bool forceFullBackup;
190 
191     KIO::filesize_t sliceBytes;
192     KIO::filesize_t sliceCapacity;
193 
194     QString ext;
195     KCompressionDevice::CompressionType compressionType;
196 
197     bool interactive;
198     bool cancelled;
199     bool runs;
200     bool skippedFiles;  // did we skip files during backup ?
201     bool verbose;
202 
203     QPointer<KIO::CopyJob> job;
204     int jobResult;
205 };
206 
207 #endif
208