Integrated file selection dialogue with the main code. Improved the
[openvpnui.git] / src / filebrowse / fileworker.cpp
1 #include "fileworker.h"
2 #include <QDateTime>
3 #include "globals.h"
4
5 FileWorker::FileWorker(QObject *parent) :
6 QThread(parent),
7 m_mode(DeleteMode),
8 m_cancelled(KeepRunning),
9 m_progress(0)
10 {
11 }
12
13 FileWorker::~FileWorker()
14 {
15 }
16
17 void FileWorker::startDeleteFiles(QStringList filenames)
18 {
19 if (isRunning()) {
20 emit errorOccurred(tr("File operation already in progress"), "");
21 return;
22 }
23
24 // basic validity check
25 foreach (QString filename, filenames) {
26 if (filename.isEmpty()) {
27 emit errorOccurred(tr("Empty filename"), "");
28 return;
29 }
30 }
31
32 m_mode = DeleteMode;
33 m_filenames = filenames;
34 m_cancelled.storeRelease(KeepRunning);
35 start();
36 }
37
38 void FileWorker::startCopyFiles(QStringList filenames, QString destDirectory)
39 {
40 if (isRunning()) {
41 emit errorOccurred(tr("File operation already in progress"), "");
42 return;
43 }
44
45 // basic validity check
46 foreach (QString filename, filenames) {
47 if (filename.isEmpty()) {
48 emit errorOccurred(tr("Empty filename"), "");
49 return;
50 }
51 }
52
53 m_mode = CopyMode;
54 m_filenames = filenames;
55 m_destDirectory = destDirectory;
56 m_cancelled.storeRelease(KeepRunning);
57 start();
58 }
59
60 void FileWorker::startMoveFiles(QStringList filenames, QString destDirectory)
61 {
62 if (isRunning()) {
63 emit errorOccurred(tr("File operation already in progress"), "");
64 return;
65 }
66
67 // basic validity check
68 foreach (QString filename, filenames) {
69 if (filename.isEmpty()) {
70 emit errorOccurred(tr("Empty filename"), "");
71 return;
72 }
73 }
74
75 m_mode = MoveMode;
76 m_filenames = filenames;
77 m_destDirectory = destDirectory;
78 m_cancelled.storeRelease(KeepRunning);
79 start();
80 }
81
82 void FileWorker::cancel()
83 {
84 m_cancelled.storeRelease(Cancelled);
85 }
86
87 void FileWorker::run() Q_DECL_OVERRIDE
88 {
89 switch (m_mode) {
90 case DeleteMode:
91 deleteFiles();
92 break;
93
94 case MoveMode:
95 case CopyMode:
96 copyOrMoveFiles();
97 break;
98 }
99 }
100
101 QString FileWorker::deleteFile(QString filename)
102 {
103 QFileInfo info(filename);
104 if (!info.exists())
105 return tr("File not found");
106
107 if (info.isDir()) {
108 // this should be custom function to get better error reporting
109 bool ok = QDir(info.absoluteFilePath()).removeRecursively();
110 if (!ok)
111 return tr("Folder delete failed");
112
113 } else {
114 QFile file(info.absoluteFilePath());
115 bool ok = file.remove();
116 if (!ok)
117 return file.errorString();
118 }
119 return QString();
120 }
121
122 void FileWorker::deleteFiles()
123 {
124 int fileIndex = 0;
125 int fileCount = m_filenames.count();
126
127 foreach (QString filename, m_filenames) {
128 m_progress = 100 * fileIndex / fileCount;
129 emit progressChanged(m_progress, filename);
130
131 // stop if cancelled
132 if (m_cancelled.loadAcquire() == Cancelled) {
133 emit errorOccurred(tr("Cancelled"), filename);
134 return;
135 }
136
137 // delete file and stop if errors
138 QString errMsg = deleteFile(filename);
139 if (!errMsg.isEmpty()) {
140 emit errorOccurred(errMsg, filename);
141 return;
142 }
143 emit fileDeleted(filename);
144
145 fileIndex++;
146 }
147
148 m_progress = 100;
149 emit progressChanged(m_progress, "");
150 emit done();
151 }
152
153 void FileWorker::copyOrMoveFiles()
154 {
155 int fileIndex = 0;
156 int fileCount = m_filenames.count();
157
158 QDir dest(m_destDirectory);
159 foreach (QString filename, m_filenames) {
160 m_progress = 100 * fileIndex / fileCount;
161 emit progressChanged(m_progress, filename);
162
163 // stop if cancelled
164 if (m_cancelled.loadAcquire() == Cancelled) {
165 emit errorOccurred(tr("Cancelled"), filename);
166 return;
167 }
168
169 // check destination does not exists, otherwise copy/move fails
170 QFileInfo fileInfo(filename);
171 QString newname = dest.absoluteFilePath(fileInfo.fileName());
172
173 // move or copy and stop if errors
174 QFile file(filename);
175 if (m_mode == MoveMode) {
176 if (!file.rename(newname)) {
177 emit errorOccurred(file.errorString(), filename);
178 return;
179 }
180 } else {
181 if (fileInfo.isDir()) {
182 QString errmsg = copyDirRecursively(filename, newname);
183 if (!errmsg.isEmpty()) {
184 emit errorOccurred(errmsg, filename);
185 return;
186 }
187 } else {
188 QString errmsg = copyOverwrite(filename, newname);
189 if (!errmsg.isEmpty()) {
190 emit errorOccurred(errmsg, filename);
191 return;
192 }
193 }
194 }
195
196 fileIndex++;
197 }
198
199 m_progress = 100;
200 emit progressChanged(m_progress, "");
201 emit done();
202 }
203
204 QString FileWorker::copyDirRecursively(QString srcDirectory, QString destDirectory)
205 {
206 QDir srcDir(srcDirectory);
207 if (!srcDir.exists())
208 return tr("Source folder doesn't exist");
209
210 QDir destDir(destDirectory);
211 if (!destDir.exists()) {
212 QDir d(destDir);
213 d.cdUp();
214 if (!d.mkdir(destDir.dirName()))
215 return tr("Can't create target folder %1").arg(destDirectory);
216 }
217
218 // copy files
219 QStringList names = srcDir.entryList(QDir::Files);
220 for (int i = 0 ; i < names.count() ; ++i) {
221 // stop if cancelled
222 if (m_cancelled.loadAcquire() == Cancelled)
223 return tr("Cancelled");
224
225 QString filename = names.at(i);
226 emit progressChanged(m_progress, filename);
227 QString spath = srcDir.absoluteFilePath(filename);
228 QString dpath = destDir.absoluteFilePath(filename);
229 QString errmsg = copyOverwrite(spath, dpath);
230 if (!errmsg.isEmpty())
231 return errmsg;
232 }
233
234 // copy dirs
235 names = srcDir.entryList(QDir::NoDotAndDotDot | QDir::AllDirs);
236 for (int i = 0 ; i < names.count() ; ++i) {
237 // stop if cancelled
238 if (m_cancelled.loadAcquire() == Cancelled)
239 return tr("Cancelled");
240
241 QString filename = names.at(i);
242 emit progressChanged(m_progress, filename);
243 QString spath = srcDir.absoluteFilePath(filename);
244 QString dpath = destDir.absoluteFilePath(filename);
245 QString errmsg = copyDirRecursively(spath, dpath);
246 if (!errmsg.isEmpty())
247 return errmsg;
248 }
249
250 return QString();
251 }
252
253 QString FileWorker::copyOverwrite(QString src, QString dest)
254 {
255 QFile dfile(dest);
256 if (dfile.exists()) {
257 if (!dfile.remove())
258 return dfile.errorString();
259 }
260
261 QFile sfile(src);
262 if (!sfile.copy(dest))
263 return sfile.errorString();
264
265 return QString();
266 }