1/*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2000 Matej Koss <koss@miesto.sk>
4 SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
5 SPDX-FileCopyrightText: 2007 Rafael Fernández López <ereslibre@kde.org>
6
7 SPDX-License-Identifier: LGPL-2.0-only
8*/
9
10#include "kstatusbarjobtracker.h"
11#include "kjobtrackerformatters_p.h"
12#include "kstatusbarjobtracker_p.h"
13
14#include <QCoreApplication>
15#include <QLabel>
16#include <QMouseEvent>
17#include <QObject>
18#include <QProgressBar>
19#include <QPushButton>
20#include <QStackedWidget>
21#include <QWidget>
22
23KStatusBarJobTracker::KStatusBarJobTracker(QWidget *parent, bool button)
24 : KAbstractWidgetJobTracker(*new KStatusBarJobTrackerPrivate(this, parent, button), parent)
25{
26}
27
28KStatusBarJobTracker::~KStatusBarJobTracker() = default;
29
30void KStatusBarJobTracker::registerJob(KJob *job)
31{
32 Q_D(KStatusBarJobTracker);
33
34 KAbstractWidgetJobTracker::registerJob(job);
35
36 if (d->progressWidget.contains(key: job)) {
37 return;
38 }
39
40 auto *vi = new KStatusBarJobTrackerPrivate::ProgressWidget(job, this, d->parent);
41 d->currentProgressWidget = vi;
42
43 d->progressWidget.insert(key: job, value: vi);
44}
45
46void KStatusBarJobTracker::unregisterJob(KJob *job)
47{
48 Q_D(KStatusBarJobTracker);
49
50 KAbstractWidgetJobTracker::unregisterJob(job);
51
52 if (!d->progressWidget.contains(key: job)) {
53 return;
54 }
55
56 if (d->currentProgressWidget == d->progressWidget[job]) {
57 d->currentProgressWidget = nullptr;
58 }
59
60 if (!d->progressWidget[job]->beingDeleted) {
61 delete d->progressWidget[job];
62 }
63
64 d->progressWidget.remove(key: job);
65}
66
67QWidget *KStatusBarJobTracker::widget(KJob *job)
68{
69 Q_D(KStatusBarJobTracker);
70
71 if (!d->progressWidget.contains(key: job)) {
72 return nullptr;
73 }
74
75 return d->progressWidget[job];
76}
77
78void KStatusBarJobTracker::setStatusBarMode(StatusBarModes statusBarMode)
79{
80 Q_D(KStatusBarJobTracker);
81
82 if (!d->currentProgressWidget) {
83 return;
84 }
85
86 d->currentProgressWidget->setMode(statusBarMode);
87}
88
89void KStatusBarJobTracker::description(KJob *job, const QString &title, const QPair<QString, QString> &field1, const QPair<QString, QString> &field2)
90{
91 Q_D(KStatusBarJobTracker);
92
93 if (!d->progressWidget.contains(key: job)) {
94 return;
95 }
96
97 d->progressWidget[job]->description(title, field1, field2);
98}
99
100void KStatusBarJobTracker::totalAmount(KJob *job, KJob::Unit unit, qulonglong amount)
101{
102 Q_D(KStatusBarJobTracker);
103
104 if (!d->progressWidget.contains(key: job)) {
105 return;
106 }
107
108 d->progressWidget[job]->totalAmount(unit, amount);
109}
110
111void KStatusBarJobTracker::percent(KJob *job, unsigned long percent)
112{
113 Q_D(KStatusBarJobTracker);
114
115 if (!d->progressWidget.contains(key: job)) {
116 return;
117 }
118
119 d->progressWidget[job]->percent(percent);
120}
121
122void KStatusBarJobTracker::speed(KJob *job, unsigned long value)
123{
124 Q_D(KStatusBarJobTracker);
125
126 if (!d->progressWidget.contains(key: job)) {
127 return;
128 }
129
130 d->progressWidget[job]->speed(value);
131}
132
133void KStatusBarJobTracker::slotClean(KJob *job)
134{
135 Q_D(KStatusBarJobTracker);
136
137 if (!d->progressWidget.contains(key: job)) {
138 return;
139 }
140
141 d->progressWidget[job]->slotClean();
142}
143
144void KStatusBarJobTrackerPrivate::ProgressWidget::killJob()
145{
146 job->kill(verbosity: KJob::EmitResult); // notify that the job has been killed
147}
148
149void KStatusBarJobTrackerPrivate::ProgressWidget::init(KJob *job, QWidget *parent)
150{
151 widget = new QWidget(parent);
152 int w = fontMetrics().horizontalAdvance(QStringLiteral(" 999.9 kB/s 00:00:01 ")) + 8;
153 box = new QHBoxLayout(widget);
154 box->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0);
155 box->setSpacing(0);
156
157 stack = new QStackedWidget(widget);
158 box->addWidget(stack);
159
160 if (q->d_func()->showStopButton) {
161 button = new QPushButton(QCoreApplication::translate(context: "KStatusBarJobTracker", key: "Stop"), widget);
162 box->addWidget(button);
163 connect(sender: button, signal: &QPushButton::clicked, context: this, slot: &KStatusBarJobTrackerPrivate::ProgressWidget::killJob);
164 } else {
165 button = nullptr;
166 }
167
168 progressBar = new QProgressBar(widget);
169 progressBar->installEventFilter(filterObj: this);
170 progressBar->setMinimumWidth(w);
171 stack->insertWidget(index: 1, w: progressBar);
172
173 label = new QLabel(widget);
174 label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
175 label->installEventFilter(filterObj: this);
176 label->setMinimumWidth(w);
177 stack->insertWidget(index: 2, w: label);
178 setMinimumSize(sizeHint());
179
180 setMode(KStatusBarJobTracker::LabelOnly);
181
182 q->setAutoDelete(job, autoDelete: true);
183
184 QVBoxLayout *layout = new QVBoxLayout(this);
185 layout->addWidget(widget);
186}
187
188void KStatusBarJobTrackerPrivate::ProgressWidget::setMode(KStatusBarJobTracker::StatusBarModes newMode)
189{
190 mode = newMode;
191
192 if (newMode == KStatusBarJobTracker::NoInformation) {
193 stack->hide();
194
195 return;
196 }
197
198 if (newMode & KStatusBarJobTracker::LabelOnly) {
199 stack->show();
200 stack->setCurrentWidget(label);
201
202 return; // TODO: we should make possible to show an informative label and the progress bar
203 }
204
205 if (newMode & KStatusBarJobTracker::ProgressOnly) {
206 stack->show();
207 stack->setCurrentWidget(progressBar);
208 }
209}
210
211void KStatusBarJobTrackerPrivate::ProgressWidget::description(const QString &title,
212 const QPair<QString, QString> &field1,
213 const QPair<QString, QString> &field2)
214{
215 Q_UNUSED(field1);
216 Q_UNUSED(field2);
217
218 label->setText(title);
219}
220
221void KStatusBarJobTrackerPrivate::ProgressWidget::totalAmount(KJob::Unit unit, qulonglong amount)
222{
223 Q_UNUSED(unit);
224 Q_UNUSED(amount);
225#if 0 // currently unused
226 if (unit == KJob::Bytes) {
227 totalSize = amount;
228 }
229#endif
230}
231
232void KStatusBarJobTrackerPrivate::ProgressWidget::percent(unsigned long percent)
233{
234 progressBar->setValue(percent);
235}
236
237void KStatusBarJobTrackerPrivate::ProgressWidget::speed(unsigned long value)
238{
239 if (value == 0) { // speed is measured in bytes-per-second
240 label->setText(QCoreApplication::translate(context: "KStatusBarJobTracker", key: " Stalled "));
241 } else {
242 label->setText(QCoreApplication::translate(context: "KStatusBarJobTracker", key: " %1/s ").arg(a: KJobTrackerFormatters::byteSize(size: value)));
243 }
244}
245
246void KStatusBarJobTrackerPrivate::ProgressWidget::slotClean()
247{
248 // we don't want to delete this widget, only clean
249 progressBar->setValue(0);
250 label->clear();
251
252 setMode(KStatusBarJobTracker::NoInformation);
253}
254
255bool KStatusBarJobTrackerPrivate::ProgressWidget::eventFilter(QObject *obj, QEvent *event)
256{
257 if (obj == progressBar || obj == label) {
258 if (event->type() == QEvent::MouseButtonPress) {
259 QMouseEvent *e = static_cast<QMouseEvent *>(event);
260
261 // TODO: we should make possible to show an informative label and the progress bar
262 if (e->button() == Qt::LeftButton) { // toggle view on left mouse button
263 if (mode == KStatusBarJobTracker::LabelOnly) {
264 setMode(KStatusBarJobTracker::ProgressOnly);
265 } else if (mode == KStatusBarJobTracker::ProgressOnly) {
266 setMode(KStatusBarJobTracker::LabelOnly);
267 }
268 return true;
269 }
270 }
271
272 return false;
273 }
274
275 return QWidget::eventFilter(watched: obj, event);
276}
277
278#include "moc_kstatusbarjobtracker.cpp"
279#include "moc_kstatusbarjobtracker_p.cpp"
280

source code of kjobwidgets/src/kstatusbarjobtracker.cpp