1 /*
2 SPDX-FileCopyrightText: 2021 Kai Uwe Broulik <kde@broulik.de>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7 #include "kjobcreator.h"
8
9 #include <QApplication>
10 #include <QIcon>
11 #include <QPushButton>
12
13 #include <KUiServerJobTracker>
14 #include <KUiServerV2JobTracker>
15 #include <KWidgetJobTracker>
16
17 #include <limits>
18
TestJob(QObject * parent)19 TestJob::TestJob(QObject *parent)
20 : KJob(parent)
21 {
22 }
23
start()24 void TestJob::start()
25 {
26 m_started = true;
27 }
28
started() const29 bool TestJob::started() const
30 {
31 return m_started;
32 }
33
finish()34 void TestJob::finish()
35 {
36 emitResult();
37 }
38
setPercentage(int percent)39 void TestJob::setPercentage(int percent)
40 {
41 setPercent(percent);
42 }
43
setProcessedMiB(double bytes)44 void TestJob::setProcessedMiB(double bytes)
45 {
46 setProcessedAmount(KJob::Bytes, bytes * 1024 * 1024);
47 }
48
setTotalMiB(double bytes)49 void TestJob::setTotalMiB(double bytes)
50 {
51 setTotalAmount(KJob::Bytes, bytes * 1024 * 1024);
52 }
53
setProcessedFiles(int files)54 void TestJob::setProcessedFiles(int files)
55 {
56 setProcessedAmount(KJob::Files, files);
57 }
58
setTotalFiles(int files)59 void TestJob::setTotalFiles(int files)
60 {
61 setTotalAmount(KJob::Files, files);
62 }
63
setProcessedDirectories(int directories)64 void TestJob::setProcessedDirectories(int directories)
65 {
66 setProcessedAmount(KJob::Directories, directories);
67 }
68
setTotalDirectories(int directories)69 void TestJob::setTotalDirectories(int directories)
70 {
71 setTotalAmount(KJob::Directories, directories);
72 }
73
setProcessedItems(int items)74 void TestJob::setProcessedItems(int items)
75 {
76 setProcessedAmount(KJob::Items, items);
77 }
78
setTotalItems(int items)79 void TestJob::setTotalItems(int items)
80 {
81 setTotalAmount(KJob::Items, items);
82 }
83
setSpeedMiB(double speed)84 void TestJob::setSpeedMiB(double speed)
85 {
86 emitSpeed(speed * 1024 * 1024);
87 }
88
setErrorState(int errorCode,const QString & errorTest)89 void TestJob::setErrorState(int errorCode, const QString &errorTest)
90 {
91 setError(errorCode);
92 setErrorText(errorTest);
93 }
94
setSuspendable(bool suspendable)95 void TestJob::setSuspendable(bool suspendable)
96 {
97 auto caps = capabilities();
98 caps.setFlag(KJob::Suspendable, suspendable);
99 setCapabilities(caps);
100 }
101
setKillable(bool killable)102 void TestJob::setKillable(bool killable)
103 {
104 auto caps = capabilities();
105 caps.setFlag(KJob::Killable, killable);
106 setCapabilities(caps);
107 }
108
doKill()109 bool TestJob::doKill()
110 {
111 // TODO add checkbox for testing what happens when you try to kill a job that refuses?
112 return true;
113 }
114
doSuspend()115 bool TestJob::doSuspend()
116 {
117 return true;
118 }
119
doResume()120 bool TestJob::doResume()
121 {
122 return true;
123 }
124
TestDialog(QWidget * parent)125 TestDialog::TestDialog(QWidget *parent)
126 : QDialog(parent)
127 {
128 m_ui.setupUi(this);
129
130 m_ui.desktopEntry->setText(QGuiApplication::desktopFileName());
131
132 m_ui.processedBytes->setMaximum(std::numeric_limits<double>::max());
133 m_ui.totalBytes->setMaximum(m_ui.processedBytes->maximum());
134 m_ui.processedFiles->setMaximum(std::numeric_limits<int>::max());
135 m_ui.totalFiles->setMaximum(m_ui.processedFiles->maximum());
136 m_ui.processedDirectories->setMaximum(std::numeric_limits<int>::max());
137 m_ui.totalDirectories->setMaximum(m_ui.processedDirectories->maximum());
138 m_ui.processedItems->setMaximum(std::numeric_limits<int>::max());
139 m_ui.totalItems->setMaximum(m_ui.processedItems->maximum());
140
141 m_ui.speed->setMaximum(std::numeric_limits<double>::max());
142
143 m_ui.createButton->setIcon(QIcon::fromTheme(QStringLiteral("document-new")));
144 m_ui.startButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
145 m_ui.suspendButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
146 m_ui.killButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-stop")));
147 m_ui.finishButton->setIcon(QIcon::fromTheme(QStringLiteral("view-task")));
148
149 updateUiState();
150
151 connect(m_ui.desktopEntry, &QLineEdit::editingFinished, this, [this] {
152 QGuiApplication::setDesktopFileName(m_ui.desktopEntry->text());
153 updateUiState();
154 });
155
156 connect(m_ui.destUrl, &QLineEdit::editingFinished, this, &TestDialog::updateJob);
157
158 connect(m_ui.emitDescriptionButton, &QPushButton::clicked, this, [this] {
159 m_job->description(m_job,
160 m_ui.title->text(),
161 qMakePair(m_ui.descriptionLabel1->text(), m_ui.descriptionValue1->text()),
162 qMakePair(m_ui.descriptionLabel2->text(), m_ui.descriptionValue2->text()));
163 });
164
165 connect(m_ui.percent, &QSlider::valueChanged, this, &TestDialog::updateJob);
166 connect(m_ui.processedBytes, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &TestDialog::updateJob);
167 connect(m_ui.totalBytes, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &TestDialog::updateJob);
168 connect(m_ui.processedFiles, qOverload<int>(&QSpinBox::valueChanged), this, &TestDialog::updateJob);
169 connect(m_ui.totalFiles, qOverload<int>(&QSpinBox::valueChanged), this, &TestDialog::updateJob);
170 connect(m_ui.processedDirectories, qOverload<int>(&QSpinBox::valueChanged), this, &TestDialog::updateJob);
171 connect(m_ui.totalDirectories, qOverload<int>(&QSpinBox::valueChanged), this, &TestDialog::updateJob);
172 connect(m_ui.processedItems, qOverload<int>(&QSpinBox::valueChanged), this, &TestDialog::updateJob);
173 connect(m_ui.totalItems, qOverload<int>(&QSpinBox::valueChanged), this, &TestDialog::updateJob);
174 connect(m_ui.speed, qOverload<double>(&QDoubleSpinBox::valueChanged), this, &TestDialog::updateJob);
175
176 connect(m_ui.infoMessage, &QLineEdit::returnPressed, m_ui.emitInfoMessage, &QPushButton::click);
177 connect(m_ui.emitInfoMessage, &QPushButton::clicked, this, [this] {
178 m_job->infoMessage(m_job, m_ui.infoMessage->text(), QString());
179 });
180
181 connect(m_ui.errorCombo, qOverload<int>(&QComboBox::activated), this, &TestDialog::updateJob);
182 connect(m_ui.errorText, &QLineEdit::editingFinished, this, &TestDialog::updateJob);
183
184 connect(m_ui.suspendableCheck, &QCheckBox::toggled, this, &TestDialog::updateJob);
185 connect(m_ui.killableCheck, &QCheckBox::toggled, this, &TestDialog::updateJob);
186
187 connect(m_ui.createButton, &QPushButton::clicked, this, [this] {
188 Q_ASSERT(!m_job);
189 m_job = new TestJob(this);
190 connect(m_job, &KJob::finished, this, [this] {
191 m_job = nullptr;
192 m_registeredWithWidgetTracker = false;
193 m_registeredWithUiServerTracker = false;
194 m_registeredWithUiServerV2Tracker = false;
195 updateUiState();
196 });
197 connect(m_job, &KJob::suspended, this, &TestDialog::updateUiState);
198 connect(m_job, &KJob::resumed, this, &TestDialog::updateUiState);
199
200 // KJob auto-calculates percent based on processed/total amount, so sync that back into the UI
201 connect(m_job, &KJob::percentChanged, this, [this](KJob *job, unsigned long percent) {
202 Q_UNUSED(job);
203 m_ui.percent->setValue(percent);
204 });
205
206 updateJob();
207 updateUiState();
208 });
209 connect(m_ui.startButton, &QPushButton::clicked, this, [this] {
210 m_job->start();
211 updateUiState();
212 });
213 connect(m_ui.suspendButton, &QPushButton::clicked, this, [this] {
214 if (m_job->isSuspended()) {
215 m_job->resume();
216 } else {
217 m_job->suspend();
218 }
219 });
220 connect(m_ui.killButton, &QPushButton::clicked, this, [this] {
221 m_job->kill();
222 });
223 connect(m_ui.finishButton, &QPushButton::clicked, this, [this] {
224 m_job->finish();
225 });
226
227 connect(m_ui.registerKWidgetJobTracker, &QPushButton::clicked, this, [this] {
228 if (!m_widgetTracker) {
229 // not passing "parent" so it spawns a new window
230 m_widgetTracker.reset(new KWidgetJobTracker(nullptr));
231 }
232 m_widgetTracker->registerJob(m_job.data());
233 m_registeredWithWidgetTracker = true;
234 updateUiState();
235 });
236 connect(m_ui.registerKUIServerJobTracker, &QPushButton::clicked, this, [this] {
237 if (!m_uiServerTracker) {
238 m_uiServerTracker.reset(new KUiServerJobTracker(nullptr));
239 }
240 m_uiServerTracker->registerJob(m_job.data());
241 m_registeredWithUiServerTracker = true;
242 updateUiState();
243 });
244 connect(m_ui.registerKUIServerV2JobTracker, &QPushButton::clicked, this, [this] {
245 if (!m_uiServerV2Tracker) {
246 m_uiServerV2Tracker.reset(new KUiServerV2JobTracker(nullptr));
247 }
248 m_uiServerV2Tracker->registerJob(m_job.data());
249 m_registeredWithUiServerV2Tracker = true;
250 updateUiState();
251 });
252 }
253
254 TestDialog::~TestDialog() = default;
255
closeEvent(QCloseEvent * event)256 void TestDialog::closeEvent(QCloseEvent *event)
257 {
258 Q_UNUSED(event)
259 if (m_job) {
260 m_job->kill(KJob::EmitResult);
261 }
262 }
263
updateUiState()264 void TestDialog::updateUiState()
265 {
266 m_ui.destUrl->setEnabled(m_job);
267
268 m_ui.emitDescriptionButton->setEnabled(m_job);
269 m_ui.emitInfoMessage->setEnabled(m_job);
270
271 m_ui.processedBytes->setEnabled(m_job);
272 m_ui.totalBytes->setEnabled(m_job);
273 m_ui.processedFiles->setEnabled(m_job);
274 m_ui.totalFiles->setEnabled(m_job);
275 m_ui.processedDirectories->setEnabled(m_job);
276 m_ui.totalDirectories->setEnabled(m_job);
277 m_ui.processedItems->setEnabled(m_job);
278 m_ui.totalItems->setEnabled(m_job);
279
280 m_ui.percent->setEnabled(m_job);
281 m_ui.speed->setEnabled(m_job);
282 m_ui.errorCombo->setEnabled(m_job);
283 m_ui.errorText->setEnabled(m_job);
284
285 m_ui.createButton->setEnabled(!m_job);
286 m_ui.startButton->setEnabled(m_job && !m_job->started());
287 m_ui.suspendButton->setEnabled(m_job);
288 m_ui.suspendButton->setChecked(m_job && m_job->isSuspended());
289 m_ui.killButton->setEnabled(m_job);
290 m_ui.finishButton->setEnabled(m_job);
291
292 m_ui.registerKWidgetJobTracker->setEnabled(m_job && !m_registeredWithWidgetTracker);
293 m_ui.registerKUIServerJobTracker->setEnabled(m_job && !m_registeredWithUiServerTracker);
294 m_ui.registerKUIServerV2JobTracker->setEnabled(m_job && !m_registeredWithUiServerV2Tracker && !QGuiApplication::desktopFileName().isEmpty());
295 }
296
updateJob()297 void TestDialog::updateJob()
298 {
299 if (!m_job) {
300 return;
301 }
302
303 m_job->setProperty("destUrl", m_ui.destUrl->text());
304 m_job->setProperty("immediateProgressReporting", m_ui.immediateCheck->isChecked());
305
306 m_job->setPercentage(m_ui.percent->value());
307
308 m_job->setProcessedMiB(m_ui.processedBytes->value());
309 m_job->setTotalMiB(m_ui.totalBytes->value());
310 m_job->setProcessedFiles(m_ui.processedFiles->value());
311 m_job->setTotalFiles(m_ui.totalFiles->value());
312 m_job->setProcessedDirectories(m_ui.processedDirectories->value());
313 m_job->setTotalDirectories(m_ui.totalDirectories->value());
314 m_job->setProcessedItems(m_ui.processedItems->value());
315 m_job->setTotalItems(m_ui.totalItems->value());
316
317 m_job->setSpeedMiB(m_ui.speed->value());
318
319 m_job->setErrorState(m_ui.errorCombo->currentIndex(), m_ui.errorText->text());
320
321 m_job->setSuspendable(m_ui.suspendableCheck->isChecked());
322 m_job->setKillable(m_ui.killableCheck->isChecked());
323 }
324
main(int argc,char ** argv)325 int main(int argc, char **argv)
326 {
327 QApplication app(argc, argv);
328 app.setApplicationName(QStringLiteral("kjobcreator"));
329 app.setDesktopFileName(QStringLiteral("org.kde.dolphin"));
330
331 TestDialog dialog;
332 dialog.show();
333
334 return app.exec();
335 }
336