1 /* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2015-06-15
7 * Description : IO Jobs thread for file system jobs
8 *
9 * Copyright (C) 2015 by Mohamed_Anwer <m_dot_anwer at gmx dot com>
10 * Copyright (C) 2018 by Maik Qualmann <metzpinguin at gmail dot com>
11 *
12 * This program is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General
14 * Public License as published by the Free Software Foundation;
15 * either version 2, or (at your option)
16 * any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * ============================================================ */
24
25 #include "iojobsthread.h"
26
27 // Qt includes
28
29 #include <QFileInfo>
30 #include <QDir>
31
32 // Local includes
33
34 #include "iojob.h"
35 #include "iojobdata.h"
36 #include "digikam_debug.h"
37 #include "coredb.h"
38 #include "coredbaccess.h"
39
40 namespace Digikam
41 {
42
43 class Q_DECL_HIDDEN IOJobsThread::Private
44 {
45
46 public:
47
Private()48 explicit Private()
49 : jobsCount (0),
50 isCanceled(false),
51 jobData (nullptr)
52 {
53 }
54
55 int jobsCount;
56 bool isCanceled;
57
58 IOJobData* jobData;
59
60 QStringList errorsList;
61 };
62
IOJobsThread(QObject * const parent)63 IOJobsThread::IOJobsThread(QObject* const parent)
64 : ActionThreadBase(parent),
65 d(new Private)
66 {
67 setObjectName(QLatin1String("IOJobsThread"));
68 }
69
~IOJobsThread()70 IOJobsThread::~IOJobsThread()
71 {
72 delete d->jobData;
73 delete d;
74 }
75
copyOrMove(IOJobData * const data)76 void IOJobsThread::copyOrMove(IOJobData* const data)
77 {
78 d->jobData = data;
79
80 ActionJobCollection collection;
81
82 int threads = qMin(maximumNumberOfThreads(),
83 data->sourceUrls().count());
84
85 for (int i = 0 ; i < threads ; ++i)
86 {
87 CopyOrMoveJob* const j = new CopyOrMoveJob(data);
88
89 connectOneJob(j);
90
91 collection.insert(j, 0);
92 d->jobsCount++;
93 }
94
95 appendJobs(collection);
96 }
97
deleteFiles(IOJobData * const data)98 void IOJobsThread::deleteFiles(IOJobData* const data)
99 {
100 d->jobData = data;
101
102 ActionJobCollection collection;
103
104 int threads = qMin(maximumNumberOfThreads(),
105 data->sourceUrls().count());
106
107 for (int i = 0 ; i < threads ; ++i)
108 {
109 DeleteJob* const j = new DeleteJob(data);
110
111 connectOneJob(j);
112
113 collection.insert(j, 0);
114 d->jobsCount++;
115 }
116
117 appendJobs(collection);
118 }
119
renameFile(IOJobData * const data)120 void IOJobsThread::renameFile(IOJobData* const data)
121 {
122 d->jobData = data;
123 ActionJobCollection collection;
124
125 RenameFileJob* const j = new RenameFileJob(data);
126
127 connectOneJob(j);
128
129 connect(j, SIGNAL(signalRenameFailed(QUrl)),
130 this, SIGNAL(signalRenameFailed(QUrl)));
131
132 collection.insert(j, 0);
133 d->jobsCount++;
134
135 appendJobs(collection);
136 }
137
listDTrashItems(const QString & collectionPath)138 void IOJobsThread::listDTrashItems(const QString& collectionPath)
139 {
140 ActionJobCollection collection;
141
142 DTrashItemsListingJob* const j = new DTrashItemsListingJob(collectionPath);
143
144 connect(j, SIGNAL(trashItemInfo(DTrashItemInfo)),
145 this, SIGNAL(collectionTrashItemInfo(DTrashItemInfo)));
146
147 connect(j, SIGNAL(signalDone()),
148 this, SIGNAL(signalFinished()));
149
150 collection.insert(j, 0);
151 d->jobsCount++;
152
153 appendJobs(collection);
154 }
155
restoreDTrashItems(IOJobData * const data)156 void IOJobsThread::restoreDTrashItems(IOJobData* const data)
157 {
158 d->jobData = data;
159 ActionJobCollection collection;
160
161 RestoreDTrashItemsJob* const j = new RestoreDTrashItemsJob(data);
162
163 connectOneJob(j);
164
165 collection.insert(j, 0);
166 d->jobsCount++;
167
168 appendJobs(collection);
169 }
170
emptyDTrashItems(IOJobData * const data)171 void IOJobsThread::emptyDTrashItems(IOJobData* const data)
172 {
173 d->jobData = data;
174 ActionJobCollection collection;
175
176 EmptyDTrashItemsJob* const j = new EmptyDTrashItemsJob(data);
177
178 connectOneJob(j);
179
180 collection.insert(j, 0);
181 d->jobsCount++;
182
183 appendJobs(collection);
184 }
185
isCanceled() const186 bool IOJobsThread::isCanceled() const
187 {
188 return d->isCanceled;
189 }
190
hasErrors() const191 bool IOJobsThread::hasErrors() const
192 {
193 return !d->errorsList.isEmpty();
194 }
195
errorsList() const196 QStringList& IOJobsThread::errorsList() const
197 {
198 return d->errorsList;
199 }
200
jobData() const201 IOJobData* IOJobsThread::jobData() const
202 {
203 return d->jobData;
204 }
205
connectOneJob(IOJob * const j)206 void IOJobsThread::connectOneJob(IOJob* const j)
207 {
208 connect(j, SIGNAL(signalError(QString)),
209 this, SLOT(slotError(QString)));
210
211 connect(j, SIGNAL(signalDone()),
212 this, SLOT(slotOneJobFinished()));
213
214 connect(j, SIGNAL(signalOneProccessed(QUrl)),
215 this, SIGNAL(signalOneProccessed(QUrl)));
216 }
217
slotOneJobFinished()218 void IOJobsThread::slotOneJobFinished()
219 {
220 d->jobsCount--;
221
222 if (d->jobsCount == 0)
223 {
224 emit signalFinished();
225 qCDebug(DIGIKAM_IOJOB_LOG) << "Thread Finished";
226 }
227 }
228
slotError(const QString & errString)229 void IOJobsThread::slotError(const QString& errString)
230 {
231 d->errorsList.append(errString);
232 }
233
slotCancel()234 void IOJobsThread::slotCancel()
235 {
236 d->isCanceled = true;
237 ActionThreadBase::cancel();
238 }
239
240 } // namespace Digikam
241