KJobWidgets

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

KDE's Doxygen guidelines are available online.