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