1 /* This file is part of Clementine.
2 Copyright 2010-2011, David Sansome <me@davidsansome.com>
3 Copyright 2014, Krzysztof Sobiecki <sobkas@gmail.com>
4 Copyright 2014, John Maguire <john.maguire@gmail.com>
5
6 Clementine is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 Clementine is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with Clementine. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "deletefiles.h"
21
22 #include <QStringList>
23 #include <QTimer>
24 #include <QThread>
25 #include <QUrl>
26
27 #include "musicstorage.h"
28 #include "taskmanager.h"
29
30 const int DeleteFiles::kBatchSize = 50;
31
DeleteFiles(TaskManager * task_manager,std::shared_ptr<MusicStorage> storage)32 DeleteFiles::DeleteFiles(TaskManager* task_manager,
33 std::shared_ptr<MusicStorage> storage)
34 : thread_(nullptr),
35 task_manager_(task_manager),
36 storage_(storage),
37 started_(false),
38 task_id_(0),
39 progress_(0) {
40 original_thread_ = thread();
41 }
42
~DeleteFiles()43 DeleteFiles::~DeleteFiles() {}
44
Start(const SongList & songs)45 void DeleteFiles::Start(const SongList& songs) {
46 if (thread_) return;
47
48 songs_ = songs;
49
50 task_id_ = task_manager_->StartTask(tr("Deleting files"));
51 task_manager_->SetTaskBlocksLibraryScans(true);
52
53 thread_ = new QThread;
54 connect(thread_, SIGNAL(started()), SLOT(ProcessSomeFiles()));
55
56 moveToThread(thread_);
57 thread_->start();
58 }
59
Start(const QUrl & url)60 void DeleteFiles::Start(const QUrl& url) {
61 SongList songs;
62 Song song;
63 song.set_url(url);
64 songs << song;
65
66 Start(songs);
67 }
68
Start(const QStringList & filenames)69 void DeleteFiles::Start(const QStringList& filenames) {
70 SongList songs;
71 for (const QString& filename : filenames) {
72 Song song;
73 song.set_url(QUrl::fromLocalFile(filename));
74 songs << song;
75 }
76
77 Start(songs);
78 }
79
ProcessSomeFiles()80 void DeleteFiles::ProcessSomeFiles() {
81 if (!started_) {
82 storage_->StartDelete();
83 started_ = true;
84 }
85
86 // None left?
87 if (progress_ >= songs_.count()) {
88 task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
89
90 storage_->FinishCopy(songs_with_errors_.isEmpty());
91
92 task_manager_->SetTaskFinished(task_id_);
93
94 emit Finished(songs_with_errors_);
95
96 // Move back to the original thread so deleteLater() can get called in
97 // the main thread's event loop
98 moveToThread(original_thread_);
99 deleteLater();
100
101 // Stop this thread
102 thread_->quit();
103 return;
104 }
105
106 // We process files in batches so we can be cancelled part-way through.
107
108 const int n = qMin(songs_.count(), progress_ + kBatchSize);
109 for (; progress_ < n; ++progress_) {
110 task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
111
112 const Song& song = songs_[progress_];
113
114 MusicStorage::DeleteJob job;
115 job.metadata_ = song;
116
117 if (!storage_->DeleteFromStorage(job)) {
118 songs_with_errors_ << song;
119 }
120 }
121
122 QTimer::singleShot(0, this, SLOT(ProcessSomeFiles()));
123 }
124