added possibility to pause/abort the operations
[case] / src / fileoperator.h
1 // case - file manager for N900
2 // Copyright (C) 2010 Lukas Hrazky <lukkash@email.cz>
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, either version 3 of the License, or
7 // (at your option) any later version.
8 // 
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 // 
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17
18 #ifndef FILEOPERATOR_H
19 #define FILEOPERATOR_H
20
21 #include <QWidget>
22 #include <QFileInfo>
23 #include <QThread>
24 #include <QMutex>
25 #include <QWaitCondition>
26 #include <QDir>
27 #include <QMap>
28 #include <QSet>
29
30 #include "progressbar.h"
31
32
33 class FileManipulatorThread;
34
35
36 class FileOperator : public QWidget {
37     Q_OBJECT
38
39 public:
40     // DONT_ASK_ONCE is a hackish way to avoid asking twice to overwrite the same directory when moving
41     enum Response{NONE, ABORT, RETRY, IGNORE, KEEP, OVERWRITE, SKIP_DIR, ASK, DONT_ASK_ONCE};
42
43     FileOperator(QWidget *parent = 0);
44
45     static QString shortenPath(const QString &path);
46     static QString unwindPath(const QString &path);
47
48     void deleteFiles(const QFileInfoList &files);
49     void copyFiles(const QFileInfoList &files, QDir &destination);
50     void moveFiles(const QFileInfoList &files, QDir &destination);
51
52 public slots:
53     void showErrorPrompt(FileManipulatorThread* manipulator,
54         const QString &message,
55         const QString &fileName,
56         const int err);
57     void showOverwritePrompt(FileManipulatorThread* manipulator,
58         const QString &fileName,
59         const bool dirOverDir);
60     void showInputFilenamePrompt(FileManipulatorThread* manipulator,
61         const QFileInfo &fileName,
62         const bool dirOverDir);
63
64     void remove(FileManipulatorThread* manipulator);
65     void setBarSize(FileManipulatorThread* manipulator, unsigned int size);
66     void updateProgress(FileManipulatorThread* manipulator, int value);
67     void showPaused(FileManipulatorThread* manipulator);
68
69     void togglePauseOperation(FileManipulatorThread* manipulator);
70     void abortOperation(FileManipulatorThread* manipulator);
71
72 protected:
73     void caterNewThread(FileManipulatorThread *thread);
74
75     QList<FileManipulatorThread*> manipulatorList;
76 };
77
78
79 class FileManipulatorThread : public QThread {
80     Q_OBJECT
81
82 public:
83     explicit FileManipulatorThread(const QFileInfoList files, QDir dest = QDir());
84     ~FileManipulatorThread();
85     void setResponse(const FileOperator::Response response, const bool appyToAll = false, const int err = 0);
86
87     void setText(int value);
88
89     void wake();
90
91     ProgressBar *progressBar;
92
93     QMutex mutex;
94     // the new name entered from the overwrite dialog
95     QString newNameFromDialog;
96     // flags to abort/pause the operation
97     bool abort, pause;
98
99 protected:
100     void processFiles(const QFileInfoList &files);
101     virtual void perform(const QFileInfo &file) = 0;
102
103     bool remove(QString &fileName, const bool doUpdates = false);
104     bool remove(const QFileInfoList &files, const bool doUpdates = false);
105     bool remove(const QFileInfo &file, const bool doUpdates = false);
106
107     void copy(const QFileInfo &file);
108
109     unsigned int calculateFileSize(const QFileInfoList &files,
110         const bool count = false,
111         const bool addSize = false);
112
113     QFileInfoList listDirFiles(const QString &dirPath);
114
115     void setBarSize(unsigned int size);
116     void updateProgress(int value);
117     void updateFile(const QString &name);
118
119     void waitOnCond();
120
121     QWaitCondition waitCond;
122
123     // files to process by the operation
124     const QFileInfoList files;
125     // destination for files - changes as the operation recurses into directories
126     QDir dest;
127
128     // responses from the dialog prompts (error and overwrite)
129     FileOperator::Response response;
130     FileOperator::Response overwriteAll;
131     // an array indicating whether to always ignore the error of index errno
132     bool ignoreAll[256];
133
134     // set of files that won't be deleted by the remove(...) functions
135     // used when move(...) would not overwrite target file to ensure the source file doesn't get deleted
136     QSet<QString> removeExcludeFiles;
137
138     // A map of file paths to their size. Not the actual size, but what is calculated for the
139     // purpose of the progressbar for the given operation. So either fileSize/BLOCK_SIZE or simply
140     // 1 for a file and file count for dirs (or both for copy&delete)
141     QMap<QString, qint64> fileSizeMap;
142
143     // the name of the file thats being processed (for progressBar) and the text of the progressBar (the format)
144     QString fileName, barText;
145     // stamp of the last ETA recalculation - done every second
146     time_t lastTimeUpdate;
147     time_t startTime, waitTime;
148     char timeBuf[10];
149     // progress information of the bar and for the current file
150     unsigned int barSize, barValue, fileSize, fileValue;
151
152 signals:
153     void showErrorPrompt(FileManipulatorThread*, const QString&, const QString&, const int);
154     void showOverwritePrompt(FileManipulatorThread*, const QString&, const bool);
155     void showInputFilenamePrompt(FileManipulatorThread*, const QFileInfo&, const bool);
156     void finished(FileManipulatorThread*);
157     void setBarSize(FileManipulatorThread*, unsigned int);
158     void updateProgress(FileManipulatorThread*, int);
159     void operationPaused(FileManipulatorThread*);
160 };
161
162
163 class DeleteThread : public FileManipulatorThread {
164     Q_OBJECT
165
166 public:
167     explicit DeleteThread(const QFileInfoList &files);
168
169 protected:
170     void run();
171     virtual void perform(const QFileInfo &file);
172 };
173
174
175 class CopyThread : public FileManipulatorThread {
176     Q_OBJECT
177
178 public:
179     explicit CopyThread(const QFileInfoList &files, QDir &dest);
180
181 protected:
182     void run();
183     virtual void perform(const QFileInfo &file);
184 };
185
186
187 class MoveThread : public FileManipulatorThread {
188     Q_OBJECT
189
190 public:
191     explicit MoveThread(const QFileInfoList &files, QDir &dest);
192
193 protected:
194     void run();
195     virtual void perform(const QFileInfo &file);
196     void rename(const QFileInfoList &files, const QDir &dest);
197 };
198
199
200 #endif // FILEOPERATOR_H