File indexing completed on 2024-04-28 15:28:06

0001 /*
0002     This file is part of the KDE project
0003     SPDX-FileCopyrightText: 2000 Matej Koss <koss@miesto.sk>
0004     SPDX-FileCopyrightText: 2007 Kevin Ottens <ervin@kde.org>
0005     SPDX-FileCopyrightText: 2007 Rafael Fernández López <ereslibre@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-only
0008 */
0009 
0010 #include "kstatusbarjobtracker.h"
0011 #include "kjobtrackerformatters_p.h"
0012 #include "kstatusbarjobtracker_p.h"
0013 
0014 #include <QCoreApplication>
0015 #include <QLabel>
0016 #include <QMouseEvent>
0017 #include <QObject>
0018 #include <QProgressBar>
0019 #include <QPushButton>
0020 #include <QStackedWidget>
0021 #include <QWidget>
0022 
0023 KStatusBarJobTracker::KStatusBarJobTracker(QWidget *parent, bool button)
0024     : KAbstractWidgetJobTracker(*new KStatusBarJobTrackerPrivate(this, parent, button), parent)
0025 {
0026 }
0027 
0028 KStatusBarJobTracker::~KStatusBarJobTracker() = default;
0029 
0030 void KStatusBarJobTracker::registerJob(KJob *job)
0031 {
0032     Q_D(KStatusBarJobTracker);
0033 
0034     KAbstractWidgetJobTracker::registerJob(job);
0035 
0036     if (d->progressWidget.contains(job)) {
0037         return;
0038     }
0039 
0040     auto *vi = new KStatusBarJobTrackerPrivate::ProgressWidget(job, this, d->parent);
0041     d->currentProgressWidget = vi;
0042 
0043     d->progressWidget.insert(job, vi);
0044 }
0045 
0046 void KStatusBarJobTracker::unregisterJob(KJob *job)
0047 {
0048     Q_D(KStatusBarJobTracker);
0049 
0050     KAbstractWidgetJobTracker::unregisterJob(job);
0051 
0052     if (!d->progressWidget.contains(job)) {
0053         return;
0054     }
0055 
0056     if (d->currentProgressWidget == d->progressWidget[job]) {
0057         d->currentProgressWidget = nullptr;
0058     }
0059 
0060     if (!d->progressWidget[job]->beingDeleted) {
0061         delete d->progressWidget[job];
0062     }
0063 
0064     d->progressWidget.remove(job);
0065 }
0066 
0067 QWidget *KStatusBarJobTracker::widget(KJob *job)
0068 {
0069     Q_D(KStatusBarJobTracker);
0070 
0071     if (!d->progressWidget.contains(job)) {
0072         return nullptr;
0073     }
0074 
0075     return d->progressWidget[job];
0076 }
0077 
0078 void KStatusBarJobTracker::setStatusBarMode(StatusBarModes statusBarMode)
0079 {
0080     Q_D(KStatusBarJobTracker);
0081 
0082     if (!d->currentProgressWidget) {
0083         return;
0084     }
0085 
0086     d->currentProgressWidget->setMode(statusBarMode);
0087 }
0088 
0089 void KStatusBarJobTracker::description(KJob *job, const QString &title, const QPair<QString, QString> &field1, const QPair<QString, QString> &field2)
0090 {
0091     Q_D(KStatusBarJobTracker);
0092 
0093     if (!d->progressWidget.contains(job)) {
0094         return;
0095     }
0096 
0097     d->progressWidget[job]->description(title, field1, field2);
0098 }
0099 
0100 void KStatusBarJobTracker::totalAmount(KJob *job, KJob::Unit unit, qulonglong amount)
0101 {
0102     Q_D(KStatusBarJobTracker);
0103 
0104     if (!d->progressWidget.contains(job)) {
0105         return;
0106     }
0107 
0108     d->progressWidget[job]->totalAmount(unit, amount);
0109 }
0110 
0111 void KStatusBarJobTracker::percent(KJob *job, unsigned long percent)
0112 {
0113     Q_D(KStatusBarJobTracker);
0114 
0115     if (!d->progressWidget.contains(job)) {
0116         return;
0117     }
0118 
0119     d->progressWidget[job]->percent(percent);
0120 }
0121 
0122 void KStatusBarJobTracker::speed(KJob *job, unsigned long value)
0123 {
0124     Q_D(KStatusBarJobTracker);
0125 
0126     if (!d->progressWidget.contains(job)) {
0127         return;
0128     }
0129 
0130     d->progressWidget[job]->speed(value);
0131 }
0132 
0133 void KStatusBarJobTracker::slotClean(KJob *job)
0134 {
0135     Q_D(KStatusBarJobTracker);
0136 
0137     if (!d->progressWidget.contains(job)) {
0138         return;
0139     }
0140 
0141     d->progressWidget[job]->slotClean();
0142 }
0143 
0144 void KStatusBarJobTrackerPrivate::ProgressWidget::killJob()
0145 {
0146     job->kill(KJob::EmitResult); // notify that the job has been killed
0147 }
0148 
0149 void KStatusBarJobTrackerPrivate::ProgressWidget::init(KJob *job, QWidget *parent)
0150 {
0151     widget = new QWidget(parent);
0152     int w = fontMetrics().horizontalAdvance(QStringLiteral(" 999.9 kB/s 00:00:01 ")) + 8;
0153     box = new QHBoxLayout(widget);
0154     box->setContentsMargins(0, 0, 0, 0);
0155     box->setSpacing(0);
0156 
0157     stack = new QStackedWidget(widget);
0158     box->addWidget(stack);
0159 
0160     if (q->d_func()->showStopButton) {
0161         button = new QPushButton(QCoreApplication::translate("KStatusBarJobTracker", "Stop"), widget);
0162         box->addWidget(button);
0163         connect(button, &QPushButton::clicked, this, &KStatusBarJobTrackerPrivate::ProgressWidget::killJob);
0164     } else {
0165         button = nullptr;
0166     }
0167 
0168     progressBar = new QProgressBar(widget);
0169     progressBar->installEventFilter(this);
0170     progressBar->setMinimumWidth(w);
0171     stack->insertWidget(1, progressBar);
0172 
0173     label = new QLabel(widget);
0174     label->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
0175     label->installEventFilter(this);
0176     label->setMinimumWidth(w);
0177     stack->insertWidget(2, label);
0178     setMinimumSize(sizeHint());
0179 
0180     setMode(KStatusBarJobTracker::LabelOnly);
0181 
0182     q->setAutoDelete(job, true);
0183 
0184     QVBoxLayout *layout = new QVBoxLayout(this);
0185     layout->addWidget(widget);
0186 }
0187 
0188 void KStatusBarJobTrackerPrivate::ProgressWidget::setMode(KStatusBarJobTracker::StatusBarModes newMode)
0189 {
0190     mode = newMode;
0191 
0192     if (newMode == KStatusBarJobTracker::NoInformation) {
0193         stack->hide();
0194 
0195         return;
0196     }
0197 
0198     if (newMode & KStatusBarJobTracker::LabelOnly) {
0199         stack->show();
0200         stack->setCurrentWidget(label);
0201 
0202         return; // TODO: we should make possible to show an informative label and the progress bar
0203     }
0204 
0205     if (newMode & KStatusBarJobTracker::ProgressOnly) {
0206         stack->show();
0207         stack->setCurrentWidget(progressBar);
0208     }
0209 }
0210 
0211 void KStatusBarJobTrackerPrivate::ProgressWidget::description(const QString &title,
0212                                                               const QPair<QString, QString> &field1,
0213                                                               const QPair<QString, QString> &field2)
0214 {
0215     Q_UNUSED(field1);
0216     Q_UNUSED(field2);
0217 
0218     label->setText(title);
0219 }
0220 
0221 void KStatusBarJobTrackerPrivate::ProgressWidget::totalAmount(KJob::Unit unit, qulonglong amount)
0222 {
0223     Q_UNUSED(unit);
0224     Q_UNUSED(amount);
0225 #if 0 // currently unused
0226     if (unit == KJob::Bytes) {
0227         totalSize = amount;
0228     }
0229 #endif
0230 }
0231 
0232 void KStatusBarJobTrackerPrivate::ProgressWidget::percent(unsigned long percent)
0233 {
0234     progressBar->setValue(percent);
0235 }
0236 
0237 void KStatusBarJobTrackerPrivate::ProgressWidget::speed(unsigned long value)
0238 {
0239     if (value == 0) { // speed is measured in bytes-per-second
0240         label->setText(QCoreApplication::translate("KStatusBarJobTracker", " Stalled "));
0241     } else {
0242         label->setText(QCoreApplication::translate("KStatusBarJobTracker", " %1/s ").arg(KJobTrackerFormatters::byteSize(value)));
0243     }
0244 }
0245 
0246 void KStatusBarJobTrackerPrivate::ProgressWidget::slotClean()
0247 {
0248     // we don't want to delete this widget, only clean
0249     progressBar->setValue(0);
0250     label->clear();
0251 
0252     setMode(KStatusBarJobTracker::NoInformation);
0253 }
0254 
0255 bool KStatusBarJobTrackerPrivate::ProgressWidget::eventFilter(QObject *obj, QEvent *event)
0256 {
0257     if (obj == progressBar || obj == label) {
0258         if (event->type() == QEvent::MouseButtonPress) {
0259             QMouseEvent *e = static_cast<QMouseEvent *>(event);
0260 
0261             // TODO: we should make possible to show an informative label and the progress bar
0262             if (e->button() == Qt::LeftButton) { // toggle view on left mouse button
0263                 if (mode == KStatusBarJobTracker::LabelOnly) {
0264                     setMode(KStatusBarJobTracker::ProgressOnly);
0265                 } else if (mode == KStatusBarJobTracker::ProgressOnly) {
0266                     setMode(KStatusBarJobTracker::LabelOnly);
0267                 }
0268                 return true;
0269             }
0270         }
0271 
0272         return false;
0273     }
0274 
0275     return QWidget::eventFilter(obj, event);
0276 }
0277 
0278 #include "moc_kstatusbarjobtracker.cpp"
0279 #include "moc_kstatusbarjobtracker_p.cpp"