KJobWidgets

kwidgetjobtracker.cpp
1 /* This file is part of the KDE project
2  Copyright (C) 2000 Matej Koss <[email protected]>
3  Copyright (C) 2007 Kevin Ottens <[email protected]>
4  Copyright (C) 2007 Rafael Fernández López <[email protected]>
5  Copyright (C) 2009 Shaun Reich <[email protected]>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License version 2 as published by the Free Software Foundation.
10 
11  This library 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 GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 
21 */
22 
23 #include "kwidgetjobtracker.h"
24 #include "kwidgetjobtracker_p.h"
25 #include "kjobtrackerformatters_p.h"
26 
27 #include <QCoreApplication>
28 #include <QDir>
29 #include <QProcess>
30 #include <QTimer>
31 #include <QLabel>
32 #include <QProgressBar>
33 #include <QPushButton>
34 #include <QVBoxLayout>
35 #include <QGridLayout>
36 #include <QEvent>
37 #include <QStyle>
38 
39 #include <ksqueezedtextlabel.h>
40 #include <kseparator.h>
41 
42 void KWidgetJobTracker::Private::_k_showProgressWidget()
43 {
44  if (progressWidgetsToBeShown.isEmpty()) {
45  return;
46  }
47 
48  KJob *job = progressWidgetsToBeShown.dequeue();
49 
50  // If the job has been unregistered before reaching this point, widget will
51  // return 0.
52  QWidget *widget = q->widget(job);
53 
54  if (widget) {
55  // Don't steal the focus from the current widget (e. g. Kate)
56  widget->setAttribute(Qt::WA_ShowWithoutActivating);
57  widget->show();
58  }
59 }
60 
62  : KAbstractWidgetJobTracker(parent), d(new Private(parent, this))
63 {
64 }
65 
67 {
68  delete d;
69 }
70 
72 {
73  return d->progressWidget.value(job, nullptr);
74 }
75 
77 {
78  Private::ProgressWidget *vi = new Private::ProgressWidget(job, this, d->parent);
79  vi->jobRegistered = true;
80  vi->setAttribute(Qt::WA_DeleteOnClose);
81  d->progressWidget.insert(job, vi);
82  d->progressWidgetsToBeShown.enqueue(job);
83 
85 
86  QTimer::singleShot(500, this, SLOT(_k_showProgressWidget()));
87 }
88 
90 {
92 
93  d->progressWidgetsToBeShown.removeAll(job);
94  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
95  if (!pWidget) {
96  return;
97  }
98 
99  pWidget->jobRegistered = false;
100  pWidget->deref();
101 }
102 
103 bool KWidgetJobTracker::keepOpen(KJob *job) const
104 {
105  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
106  if (!pWidget) {
107  return false;
108  }
109 
110  return pWidget->keepOpenCheck->isChecked();
111 }
112 
113 void KWidgetJobTracker::infoMessage(KJob *job, const QString &plain, const QString &rich)
114 {
115  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
116  if (!pWidget) {
117  return;
118  }
119 
120  pWidget->infoMessage(plain, rich);
121 }
122 
123 void KWidgetJobTracker::description(KJob *job, const QString &title,
124  const QPair<QString, QString> &field1,
125  const QPair<QString, QString> &field2)
126 {
127  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
128  if (!pWidget) {
129  return;
130  }
131 
132  pWidget->description(title, field1, field2);
133 }
134 
135 void KWidgetJobTracker::totalAmount(KJob *job, KJob::Unit unit, qulonglong amount)
136 {
137  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
138  if (!pWidget) {
139  return;
140  }
141 
142  pWidget->totalAmount(unit, amount);
143 }
144 
145 void KWidgetJobTracker::processedAmount(KJob *job, KJob::Unit unit, qulonglong amount)
146 {
147  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
148  if (!pWidget) {
149  return;
150  }
151 
152  pWidget->processedAmount(unit, amount);
153 }
154 
155 void KWidgetJobTracker::percent(KJob *job, unsigned long percent)
156 {
157  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
158  if (!pWidget) {
159  return;
160  }
161 
162  pWidget->percent(percent);
163 }
164 
165 void KWidgetJobTracker::speed(KJob *job, unsigned long value)
166 {
167  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
168  if (!pWidget) {
169  return;
170  }
171 
172  pWidget->speed(value);
173 }
174 
175 void KWidgetJobTracker::slotClean(KJob *job)
176 {
177  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
178  if (!pWidget) {
179  return;
180  }
181 
182  pWidget->slotClean();
183 }
184 
185 void KWidgetJobTracker::suspended(KJob *job)
186 {
187  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
188  if (!pWidget) {
189  return;
190  }
191 
192  pWidget->suspended();
193 }
194 
195 void KWidgetJobTracker::resumed(KJob *job)
196 {
197  KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, nullptr);
198  if (!pWidget) {
199  return;
200  }
201 
202  pWidget->resumed();
203 }
204 
205 void KWidgetJobTracker::Private::ProgressWidget::ref()
206 {
207  ++refCount;
208 }
209 
210 void KWidgetJobTracker::Private::ProgressWidget::deref()
211 {
212  if (refCount) {
213  --refCount;
214  }
215 
216  if (!refCount) {
217  if (!keepOpenCheck->isChecked()) {
218  closeNow();
219  } else {
220  slotClean();
221  }
222  }
223 }
224 
225 void KWidgetJobTracker::Private::ProgressWidget::closeNow()
226 {
227  close();
228 
229  // It might happen the next scenario:
230  // - Start a job which opens a progress widget. Keep it open. Address job is 0xdeadbeef
231  // - Start a new job, which is given address 0xdeadbeef. A new window is opened.
232  // This one will take much longer to complete. The key 0xdeadbeef on the widget map now
233  // stores the new widget address.
234  // - Close the first progress widget that was opened (and has already finished) while the
235  // last one is still running. We remove its reference on the map. Wrong.
236  // For that reason we have to check if the map stores the widget as the current one.
237  // ereslibre
238  if (tracker->d->progressWidget[job] == this) {
239  tracker->d->progressWidget.remove(job);
240  tracker->d->progressWidgetsToBeShown.removeAll(job);
241  }
242 }
243 
244 bool KWidgetJobTracker::Private::ProgressWidget::eventFilter(QObject *watched, QEvent *event)
245 {
246  // Handle context menu events for the source/dest labels here, so that we are ref()ed while the
247  // menu is exec()ed, to avoid a crash if the job finishes meanwhile. #159621.
248  if ((watched == sourceEdit || watched == destEdit) && event->type() == QEvent::ContextMenu) {
249  ref();
250  watched->event(event);
251  deref();
252  return true;
253  }
254 
255  return QWidget::eventFilter(watched, event);
256 }
257 
258 void KWidgetJobTracker::Private::ProgressWidget::infoMessage(const QString &plain, const QString &/*rich*/)
259 {
260  speedLabel->setText(plain);
261  speedLabel->setAlignment(speedLabel->alignment() & ~Qt::TextWordWrap);
262 }
263 
264 void KWidgetJobTracker::Private::ProgressWidget::description(const QString &title,
265  const QPair<QString, QString> &field1,
266  const QPair<QString, QString> &field2)
267 {
268  setWindowTitle(title);
269  caption = title;
270  sourceInvite->setText(
271  QCoreApplication::translate("KWidgetJobTracker",
272  "%1:", "%1 is the label, we add a ':' to it"
273  ).arg(field1.first));
274  sourceEdit->setText(field1.second);
275 
276  if (field2.first.isEmpty()) {
277  setDestVisible(false);
278  } else {
279  setDestVisible(true);
280  checkDestination(QUrl::fromUserInput(field2.second)); // path or URL
281  destInvite->setText(
282  QCoreApplication::translate("KWidgetJobTracker",
283  "%1:", "%1 is the label, we add a ':' to it"
284  ).arg(field2.first));
285  destEdit->setText(field2.second);
286  }
287 }
288 
289 void KWidgetJobTracker::Private::ProgressWidget::totalAmount(KJob::Unit unit, qulonglong amount)
290 {
291  switch (unit) {
292  case KJob::Bytes:
293  totalSizeKnown = true;
294  // size is measured in bytes
295  if (totalSize == amount) {
296  return;
297  }
298  totalSize = amount;
299  if (!startTime.isValid()) {
300  startTime.start();
301  }
302  break;
303 
304  case KJob::Files:
305  if (totalFiles == amount) {
306  return;
307  }
308  totalFiles = amount;
309  showTotals();
310  break;
311 
312  case KJob::Directories:
313  if (totalDirs == amount) {
314  return;
315  }
316  totalDirs = amount;
317  showTotals();
318  break;
319  }
320 }
321 
322 void KWidgetJobTracker::Private::ProgressWidget::processedAmount(KJob::Unit unit, qulonglong amount)
323 {
324  QString tmp;
325 
326  switch (unit) {
327  case KJob::Bytes:
328  if (processedSize == amount) {
329  return;
330  }
331  processedSize = amount;
332 
333  if (totalSizeKnown) {
334  //~ singular %1 of %2 complete
335  //~ plural %1 of %2 complete
336  tmp = QCoreApplication::translate("KWidgetJobTracker", "%1 of %2 complete", "", amount)
337  .arg(KJobTrackerFormatters::byteSize(amount), KJobTrackerFormatters::byteSize(totalSize));
338  } else {
339  tmp = KJobTrackerFormatters::byteSize(amount);
340  }
341  sizeLabel->setText(tmp);
342  if (!totalSizeKnown) { // update jumping progressbar
343  progressBar->setValue(amount);
344  }
345  break;
346 
347  case KJob::Directories:
348  if (processedDirs == amount) {
349  return;
350  }
351  processedDirs = amount;
352 
353  //~ singular %1 / %n folder
354  //~ plural %1 / %n folders
355  tmp = QCoreApplication::translate("KWidgetJobTracker", "%1 / %n folder(s)", "", totalDirs).arg(processedDirs);
356  tmp += QLatin1String(" ");
357  //~ singular %1 / %n file
358  //~ plural %1 / %n files
359  tmp += QCoreApplication::translate("KWidgetJobTracker", "%1 / %n file(s)", "", totalFiles).arg(processedFiles);
360  progressLabel->setText(tmp);
361  break;
362 
363  case KJob::Files:
364  if (processedFiles == amount) {
365  return;
366  }
367  processedFiles = amount;
368 
369  if (totalDirs > 1) {
370  //~ singular %1 / %n folder
371  //~ plural %1 / %n folders
372  tmp = QCoreApplication::translate("KWidgetJobTracker", "%1 / %n folder(s)", "", totalDirs).arg(processedDirs);
373  tmp += QLatin1String(" ");
374  }
375  //~ singular %1 / %n file
376  //~ plural %1 / %n files
377  tmp += QCoreApplication::translate("KWidgetJobTracker", "%1 / %n file(s)", "", totalFiles).arg(processedFiles);
378  progressLabel->setText(tmp);
379  }
380 }
381 
382 void KWidgetJobTracker::Private::ProgressWidget::percent(unsigned long percent)
383 {
384  QString title = caption + QLatin1String(" (");
385 
386  if (totalSizeKnown) {
387  title += QCoreApplication::translate("KWidgetJobTracker", "%1% of %2").arg(percent).arg(
388  KJobTrackerFormatters::byteSize(totalSize));
389  } else if (totalFiles) {
390  //~ singular %1% of %n file
391  //~ plural %1% of %n files
392  title += QCoreApplication::translate("KWidgetJobTracker", "%1% of %n file(s)", "", totalFiles).arg(percent);
393  } else {
394  title += QCoreApplication::translate("KWidgetJobTracker", "%1%").arg(percent);
395  }
396 
397  title += QLatin1Char(')');
398 
399  progressBar->setMaximum(100);
400  progressBar->setValue(percent);
401  setWindowTitle(title);
402 }
403 
404 void KWidgetJobTracker::Private::ProgressWidget::speed(unsigned long value)
405 {
406  if (value == 0) {
407  speedLabel->setText(QCoreApplication::translate("KWidgetJobTracker", "Stalled"));
408  } else {
409  const QString speedStr = KJobTrackerFormatters::byteSize(value);
410  if (totalSizeKnown) {
411  const int remaining = 1000 * (totalSize - processedSize) / value;
412  //~ singular %1/s (%2 remaining)
413  //~ plural %1/s (%2 remaining)
414  speedLabel->setText(QCoreApplication::translate("KWidgetJobTracker", "%1/s (%2 remaining)", "", remaining).arg(speedStr, KJobTrackerFormatters::duration(remaining)));
415  } else { // total size is not known (#24228)
416  speedLabel->setText(QCoreApplication::translate("KWidgetJobTracker", "%1/s", "speed in bytes per second").arg(speedStr));
417  }
418  }
419 }
420 
421 void KWidgetJobTracker::Private::ProgressWidget::slotClean()
422 {
423  percent(100);
424  cancelClose->setText(QCoreApplication::translate("KWidgetJobTracker", "&Close"));
425  cancelClose->setIcon(QIcon::fromTheme(QStringLiteral("window-close")));
426  cancelClose->setToolTip(QCoreApplication::translate("KWidgetJobTracker", "Close the current window or document"));
427  openFile->setEnabled(true);
428  if (!totalSizeKnown || totalSize < processedSize) {
429  totalSize = processedSize;
430  }
431  processedAmount(KJob::Bytes, totalSize);
432  keepOpenCheck->setEnabled(false);
433  pauseButton->setEnabled(false);
434  if (startTime.isValid()) {
435  int s = startTime.elapsed();
436  if (!s) {
437  s = 1;
438  }
439  speedLabel->setText(QCoreApplication::translate("KWidgetJobTracker", "%1/s (done)").arg(
440  KJobTrackerFormatters::byteSize(1000 * totalSize / s)));
441  }
442 }
443 
444 void KWidgetJobTracker::Private::ProgressWidget::suspended()
445 {
446  pauseButton->setText(QCoreApplication::translate("KWidgetJobTracker", "&Resume"));
447  suspendedProperty = true;
448 }
449 
450 void KWidgetJobTracker::Private::ProgressWidget::resumed()
451 {
452  pauseButton->setText(QCoreApplication::translate("KWidgetJobTracker", "&Pause"));
453  suspendedProperty = false;
454 }
455 
456 void KWidgetJobTracker::Private::ProgressWidget::closeEvent(QCloseEvent *event)
457 {
458  if (jobRegistered && tracker->stopOnClose(job)) {
459  tracker->slotStop(job);
460  }
461 
462  QWidget::closeEvent(event);
463 }
464 
465 void KWidgetJobTracker::Private::ProgressWidget::init()
466 {
467  setWindowIcon(QIcon::fromTheme(QStringLiteral("document-save"), windowIcon()));
468 
469  QVBoxLayout *topLayout = new QVBoxLayout(this);
470 
471  QGridLayout *grid = new QGridLayout();
472  topLayout->addLayout(grid);
473  const int spacingHint = style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
474  grid->addItem(new QSpacerItem(spacingHint, 0), 0, 1);
475  // filenames or action name
476  sourceInvite = new QLabel(QCoreApplication::translate("KWidgetJobTracker", "Source:", "The source url of a job"), this);
477  grid->addWidget(sourceInvite, 0, 0);
478 
479  sourceEdit = new KSqueezedTextLabel(this);
480  sourceEdit->setTextInteractionFlags(Qt::TextSelectableByMouse);
481  sourceEdit->installEventFilter(this);
482  grid->addWidget(sourceEdit, 0, 2);
483 
484  destInvite = new QLabel(QCoreApplication::translate("KWidgetJobTracker", "Destination:", "The destination url of a job"), this);
485  grid->addWidget(destInvite, 1, 0);
486 
487  destEdit = new KSqueezedTextLabel(this);
488  destEdit->setTextInteractionFlags(Qt::TextSelectableByMouse);
489  destEdit->installEventFilter(this);
490  grid->addWidget(destEdit, 1, 2);
491 
492  QHBoxLayout *progressHBox = new QHBoxLayout();
493  topLayout->addLayout(progressHBox);
494 
495  progressBar = new QProgressBar(this);
496  progressBar->setMaximum(0); // want a jumping progress bar if percent is not emitted
497  progressHBox->addWidget(progressBar);
498 
499  suspendedProperty = false;
500 
501  // processed info
502  QHBoxLayout *hBox = new QHBoxLayout();
503  topLayout->addLayout(hBox);
504 
505  arrowButton = new QPushButton(this);
506  arrowButton->setMaximumSize(QSize(32, 25));
507  arrowButton->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down")));
508  arrowButton->setToolTip(QCoreApplication::translate("KWidgetJobTracker", "Click this to expand the dialog, to show details"));
509  arrowState = Qt::DownArrow;
510  connect(arrowButton, &QPushButton::clicked,
511  this, &KWidgetJobTracker::Private::ProgressWidget::arrowClicked);
512  hBox->addWidget(arrowButton);
513  hBox->addStretch(1);
514 
515  KSeparator *separator1 = new KSeparator(Qt::Horizontal, this);
516  topLayout->addWidget(separator1);
517 
518  sizeLabel = new QLabel(this);
519  hBox->addWidget(sizeLabel, 0, Qt::AlignLeft);
520 
521  resumeLabel = new QLabel(this);
522  hBox->addWidget(resumeLabel);
523 
524  pauseButton = new QPushButton(QCoreApplication::translate("KWidgetJobTracker", "&Pause"), this);
525  pauseButton->setVisible(job && (job->capabilities() & KJob::Suspendable));
526  connect(pauseButton, &QPushButton::clicked,
527  this, &KWidgetJobTracker::Private::ProgressWidget::pauseResumeClicked);
528  hBox->addWidget(pauseButton);
529 
530  hBox = new QHBoxLayout();
531  topLayout->addLayout(hBox);
532 
533  speedLabel = new QLabel(this);
534  hBox->addWidget(speedLabel, 1);
535  speedLabel->hide();
536 
537  hBox = new QHBoxLayout();
538  topLayout->addLayout(hBox);
539 
540  progressLabel = new QLabel(this);
541  progressLabel->setAlignment(Qt::AlignLeft);
542  hBox->addWidget(progressLabel);
543  progressLabel->hide();
544 
545  keepOpenCheck = new QCheckBox(QCoreApplication::translate("KWidgetJobTracker", "&Keep this window open after transfer is complete"), this);
546  connect(keepOpenCheck, &QCheckBox::toggled,
547  this, &KWidgetJobTracker::Private::ProgressWidget::keepOpenToggled);
548  topLayout->addWidget(keepOpenCheck);
549  keepOpenCheck->hide();
550 
551  hBox = new QHBoxLayout();
552  topLayout->addLayout(hBox);
553 
554  openFile = new QPushButton(QCoreApplication::translate("KWidgetJobTracker", "Open &File"), this);
555  connect(openFile, &QPushButton::clicked,
556  this, &KWidgetJobTracker::Private::ProgressWidget::openFileClicked);
557  hBox->addWidget(openFile);
558  openFile->setEnabled(false);
559  openFile->hide();
560 
561  openLocation = new QPushButton(QCoreApplication::translate("KWidgetJobTracker", "Open &Destination"), this);
562  connect(openLocation, &QPushButton::clicked,
563  this, &KWidgetJobTracker::Private::ProgressWidget::openLocationClicked);
564  hBox->addWidget(openLocation);
565  openLocation->hide();
566 
567  hBox->addStretch(1);
568 
569  cancelClose = new QPushButton(this);
570  cancelClose->setText(QCoreApplication::translate("KWidgetJobTracker", "&Cancel"));
571  cancelClose->setIcon(QIcon::fromTheme(QStringLiteral("dialog-cancel")));
572  connect(cancelClose, &QPushButton::clicked,
573  this, &KWidgetJobTracker::Private::ProgressWidget::cancelClicked);
574  hBox->addWidget(cancelClose);
575 
576  resize(sizeHint());
577  setMaximumHeight(sizeHint().height());
578 
579  setWindowTitle(QCoreApplication::translate("KWidgetJobTracker", "Progress Dialog")); // show something better than kuiserver
580 }
581 
582 void KWidgetJobTracker::Private::ProgressWidget::showTotals()
583 {
584  // Show the totals in the progress label, if we still haven't
585  // processed anything. This is useful when the stat'ing phase
586  // of CopyJob takes a long time (e.g. over networks).
587  if (processedFiles == 0 && processedDirs == 0) {
588  QString tmps;
589  if (totalDirs > 1)
590  // that we have a singular to translate looks weired but is only logical
591  {
592  //~ singular %n folder
593  //~ plural %n folders
594  tmps = QCoreApplication::translate("KWidgetJobTracker", "%n folder(s)", "", totalDirs) + QLatin1String(" ");
595  }
596  //~ singular %n file
597  //~ plural %n files
598  tmps += QCoreApplication::translate("KWidgetJobTracker", "%n file(s)", "", totalFiles);
599  progressLabel->setText(tmps);
600  }
601 }
602 
603 void KWidgetJobTracker::Private::ProgressWidget::setDestVisible(bool visible)
604 {
605  // We can't hide the destInvite/destEdit labels,
606  // because it screws up the QGridLayout.
607  if (visible) {
608  destInvite->show();
609  destEdit->show();
610  } else {
611  destInvite->hide();
612  destEdit->hide();
613  destInvite->setText(QString());
614  destEdit->setText(QString());
615  }
616  setMaximumHeight(sizeHint().height());
617 }
618 
619 void KWidgetJobTracker::Private::ProgressWidget::checkDestination(const QUrl &dest)
620 {
621  bool ok = true;
622 
623  if (dest.isLocalFile()) {
624  const QString path = dest.toLocalFile();
625  if (path.contains(QDir::tempPath())) {
626  ok = false; // it's in the tmp directory
627  }
628  }
629 
630  if (ok) {
631  openFile->show();
632  openLocation->show();
633  keepOpenCheck->show();
634  setMaximumHeight(sizeHint().height());
635  location = dest;
636  }
637 }
638 
639 void KWidgetJobTracker::Private::ProgressWidget::keepOpenToggled(bool keepOpen)
640 {
641  if (keepOpen) {
642  Q_ASSERT(!tracker->d->eventLoopLocker);
643  tracker->d->eventLoopLocker = new QEventLoopLocker;
644  } else {
645  delete tracker->d->eventLoopLocker;
646  tracker->d->eventLoopLocker = nullptr;
647  }
648 }
649 
650 void KWidgetJobTracker::Private::ProgressWidget::openFileClicked()
651 {
652  QProcess::startDetached(QStringLiteral("kde-open"), QStringList() << location.toDisplayString());
653 }
654 
655 void KWidgetJobTracker::Private::ProgressWidget::openLocationClicked()
656 {
657  QProcess::startDetached(QStringLiteral("kde-open"), QStringList() << location.adjusted(QUrl::RemoveFilename).toString());
658 }
659 
660 void KWidgetJobTracker::Private::ProgressWidget::pauseResumeClicked()
661 {
662  if (jobRegistered && !suspendedProperty) {
663  tracker->slotSuspend(job);
664  } else if (jobRegistered) {
665  tracker->slotResume(job);
666  }
667 }
668 
669 void KWidgetJobTracker::Private::ProgressWidget::cancelClicked()
670 {
671  if (jobRegistered) {
672  tracker->slotStop(job);
673  }
674  closeNow();
675 }
676 
677 void KWidgetJobTracker::Private::ProgressWidget::arrowClicked()
678 {
679  if (arrowState == Qt::DownArrow) {
680  //The arrow is in the down position, dialog is collapsed, expand it and change icon.
681  progressLabel->show();
682  speedLabel->show();
683  arrowButton->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up")));
684  arrowButton->setToolTip(QCoreApplication::translate("KWidgetJobTracker", "Click this to collapse the dialog, to hide details"));
685  arrowState = Qt::UpArrow;
686  } else {
687  //Collapse the dialog
688  progressLabel->hide();
689  speedLabel->hide();
690  arrowButton->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down")));
691  arrowButton->setToolTip(QCoreApplication::translate("KWidgetJobTracker", "Click this to expand the dialog, to show details"));
692  arrowState = Qt::DownArrow;
693  }
694  setMaximumHeight(sizeHint().height());
695 }
696 
697 #include "moc_kwidgetjobtracker.cpp"
698 #include "moc_kwidgetjobtracker_p.cpp"
QEvent::Type type() const const
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
void registerJob(KJob *job) override
Register a new job in this tracker.
KWidgetJobTracker(QWidget *parent=nullptr)
Creates a new KWidgetJobTracker.
bool startDetached(qint64 *pid)
QString translate(const char *context, const char *sourceText, const char *disambiguation, int n)
The base class for widget based job trackers.
void setAttribute(Qt::WidgetAttribute attribute, bool on)
QUrl fromUserInput(const QString &userInput)
void unregisterJob(KJob *job) override
Unregister a job from this tracker.
virtual bool event(QEvent *e)
void infoMessage(KJob *job, const QString &plain, const QString &rich) override
The following slots are inherited from KJobTrackerInterface.
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
QString tempPath()
void clicked(bool checked)
void unregisterJob(KJob *job) override
Unregister a job from this tracker.
virtual bool eventFilter(QObject *watched, QEvent *event)
void registerJob(KJob *job) override
Register a new job in this tracker.
QString toLocalFile() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
~KWidgetJobTracker() override
Destroys a KWidgetJobTracker.
QWidget * widget(KJob *job) override
The widget associated to this tracker.
void addStretch(int stretch)
void addItem(QLayoutItem *item, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void toggled(bool checked)
QIcon fromTheme(const QString &name)
void show()
virtual void closeEvent(QCloseEvent *event)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString toString() const const
Capabilities capabilities() const
void addLayout(QLayout *layout, int stretch)
bool isLocalFile() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun May 24 2020 22:55:21 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.