KDEUI
kwidgetjobtracker.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2000 Matej Koss <koss@miesto.sk> 00003 Copyright (C) 2007 Kevin Ottens <ervin@kde.org> 00004 Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org> 00005 Copyright (C) 2009 Shaun Reich <shaun.reich@kdemail.net> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 00021 */ 00022 00023 #include "kwidgetjobtracker.h" 00024 #include "kwidgetjobtracker_p.h" 00025 00026 #include <QProcess> 00027 #include <QTimer> 00028 #include <QLabel> 00029 #include <QProgressBar> 00030 #include <QVBoxLayout> 00031 #include <QGridLayout> 00032 #include <QMenu> 00033 #include <QEvent> 00034 00035 #include <kurl.h> 00036 #include <kpushbutton.h> 00037 #include <ksqueezedtextlabel.h> 00038 #include <kguiitem.h> 00039 #include <kiconloader.h> 00040 #include <kdialog.h> 00041 #include <kstandarddirs.h> 00042 #include <kdebug.h> 00043 #include <klocale.h> 00044 #include <kwindowsystem.h> 00045 #include <kseparator.h> 00046 00047 void KWidgetJobTracker::Private::_k_showProgressWidget() 00048 { 00049 if (progressWidgetsToBeShown.isEmpty()) { 00050 return; 00051 } 00052 00053 KJob *job = progressWidgetsToBeShown.dequeue(); 00054 00055 // If the job has been unregistered before reaching this point, widget will 00056 // return 0. 00057 QWidget *widget = q->widget(job); 00058 00059 if (widget) { 00060 widget->show(); 00061 } 00062 } 00063 00064 KWidgetJobTracker::KWidgetJobTracker(QWidget *parent) 00065 : KAbstractWidgetJobTracker(parent), d(new Private(parent, this)) 00066 { 00067 } 00068 00069 KWidgetJobTracker::~KWidgetJobTracker() 00070 { 00071 delete d; 00072 } 00073 00074 QWidget *KWidgetJobTracker::widget(KJob *job) 00075 { 00076 return d->progressWidget.value(job, 0); 00077 } 00078 00079 void KWidgetJobTracker::registerJob(KJob *job) 00080 { 00081 Private::ProgressWidget *vi = new Private::ProgressWidget(job, this, d->parent); 00082 vi->jobRegistered = true; 00083 vi->setAttribute(Qt::WA_DeleteOnClose); 00084 d->progressWidget.insert(job, vi); 00085 d->progressWidgetsToBeShown.enqueue(job); 00086 00087 KAbstractWidgetJobTracker::registerJob(job); 00088 00089 QTimer::singleShot(500, this, SLOT(_k_showProgressWidget())); 00090 } 00091 00092 void KWidgetJobTracker::unregisterJob(KJob *job) 00093 { 00094 KAbstractWidgetJobTracker::unregisterJob(job); 00095 00096 d->progressWidgetsToBeShown.removeAll(job); 00097 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00098 if (!pWidget) { 00099 return; 00100 } 00101 00102 pWidget->jobRegistered = false; 00103 pWidget->deref(); 00104 } 00105 00106 bool KWidgetJobTracker::keepOpen(KJob *job) const 00107 { 00108 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00109 if (!pWidget) { 00110 return false; 00111 } 00112 00113 return pWidget->keepOpenCheck->isChecked(); 00114 } 00115 00116 void KWidgetJobTracker::infoMessage(KJob *job, const QString &plain, const QString &rich) 00117 { 00118 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00119 if (!pWidget) { 00120 return; 00121 } 00122 00123 pWidget->infoMessage(plain, rich); 00124 } 00125 00126 void KWidgetJobTracker::description(KJob *job, const QString &title, 00127 const QPair<QString, QString> &field1, 00128 const QPair<QString, QString> &field2) 00129 { 00130 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00131 if (!pWidget) { 00132 return; 00133 } 00134 00135 pWidget->description(title, field1, field2); 00136 } 00137 00138 void KWidgetJobTracker::totalAmount(KJob *job, KJob::Unit unit, qulonglong amount) 00139 { 00140 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00141 if (!pWidget) { 00142 return; 00143 } 00144 00145 pWidget->totalAmount(unit, amount); 00146 } 00147 00148 void KWidgetJobTracker::processedAmount(KJob *job, KJob::Unit unit, qulonglong amount) 00149 { 00150 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00151 if (!pWidget) { 00152 return; 00153 } 00154 00155 pWidget->processedAmount(unit, amount); 00156 } 00157 00158 void KWidgetJobTracker::percent(KJob *job, unsigned long percent) 00159 { 00160 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00161 if (!pWidget) { 00162 return; 00163 } 00164 00165 pWidget->percent(percent); 00166 } 00167 00168 void KWidgetJobTracker::speed(KJob *job, unsigned long value) 00169 { 00170 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00171 if (!pWidget) { 00172 return; 00173 } 00174 00175 pWidget->speed(value); 00176 } 00177 00178 void KWidgetJobTracker::slotClean(KJob *job) 00179 { 00180 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00181 if (!pWidget) { 00182 return; 00183 } 00184 00185 pWidget->slotClean(); 00186 } 00187 00188 void KWidgetJobTracker::suspended(KJob *job) 00189 { 00190 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00191 if (!pWidget) { 00192 return; 00193 } 00194 00195 pWidget->suspended(); 00196 } 00197 00198 void KWidgetJobTracker::resumed(KJob *job) 00199 { 00200 KWidgetJobTracker::Private::ProgressWidget *pWidget = d->progressWidget.value(job, 0); 00201 if (!pWidget) { 00202 return; 00203 } 00204 00205 pWidget->resumed(); 00206 } 00207 00208 void KWidgetJobTracker::Private::ProgressWidget::ref() 00209 { 00210 ++refCount; 00211 } 00212 00213 void KWidgetJobTracker::Private::ProgressWidget::deref() 00214 { 00215 if (refCount) { 00216 --refCount; 00217 } 00218 00219 if (!refCount) { 00220 if (!keepOpenCheck->isChecked()) { 00221 closeNow(); 00222 } else { 00223 slotClean(); 00224 } 00225 } 00226 } 00227 00228 void KWidgetJobTracker::Private::ProgressWidget::closeNow() 00229 { 00230 close(); 00231 00232 // It might happen the next scenario: 00233 // - Start a job which opens a progress widget. Keep it open. Address job is 0xdeadbeef 00234 // - Start a new job, which is given address 0xdeadbeef. A new window is opened. 00235 // This one will take much longer to complete. The key 0xdeadbeef on the widget map now 00236 // stores the new widget address. 00237 // - Close the first progress widget that was opened (and has already finished) while the 00238 // last one is still running. We remove its reference on the map. Wrong. 00239 // For that reason we have to check if the map stores the widget as the current one. 00240 // ereslibre 00241 if (tracker->d->progressWidget[job] == this) { 00242 tracker->d->progressWidget.remove(job); 00243 tracker->d->progressWidgetsToBeShown.removeAll(job); 00244 } 00245 } 00246 00247 bool KWidgetJobTracker::Private::ProgressWidget::eventFilter(QObject *watched, QEvent *event) 00248 { 00249 // Handle context menu events for the source/dest labels here, so that we are ref()ed while the 00250 // menu is exec()ed, to avoid a crash if the job finishes meanwhile. #159621. 00251 if ((watched == sourceEdit || watched == destEdit) && event->type() == QEvent::ContextMenu) { 00252 ref(); 00253 watched->event(event); 00254 deref(); 00255 return true; 00256 } 00257 00258 return QWidget::eventFilter(watched, event); 00259 } 00260 00261 void KWidgetJobTracker::Private::ProgressWidget::infoMessage(const QString &plain, const QString &/*rich*/) 00262 { 00263 speedLabel->setText(plain); 00264 speedLabel->setAlignment(speedLabel->alignment() & ~Qt::TextWordWrap); 00265 } 00266 00267 void KWidgetJobTracker::Private::ProgressWidget::description(const QString &title, 00268 const QPair<QString, QString> &field1, 00269 const QPair<QString, QString> &field2) 00270 { 00271 setWindowTitle(title); 00272 caption = title; 00273 00274 sourceInvite->setText(i18nc("%1 is the label, we add a ':' to it", "%1:", field1.first)); 00275 sourceEdit->setText(field1.second); 00276 00277 if (field2.first.isEmpty()) { 00278 setDestVisible(false); 00279 } else { 00280 setDestVisible(true); 00281 checkDestination(KUrl(field2.second)); 00282 destInvite->setText(i18nc("%1 is the label, we add a ':' to it", "%1:", field2.first)); 00283 destEdit->setText(field2.second); 00284 } 00285 } 00286 00287 void KWidgetJobTracker::Private::ProgressWidget::totalAmount(KJob::Unit unit, qulonglong amount) 00288 { 00289 switch(unit) 00290 { 00291 case KJob::Bytes: 00292 totalSizeKnown = true; 00293 // size is measured in bytes 00294 if (totalSize == amount) 00295 return; 00296 totalSize = amount; 00297 if (startTime.isNull()) 00298 startTime.start(); 00299 break; 00300 00301 case KJob::Files: 00302 if (totalFiles == amount) 00303 return; 00304 totalFiles = amount; 00305 showTotals(); 00306 break; 00307 00308 case KJob::Directories: 00309 if (totalDirs == amount) 00310 return; 00311 totalDirs = amount; 00312 showTotals(); 00313 break; 00314 } 00315 } 00316 00317 void KWidgetJobTracker::Private::ProgressWidget::processedAmount(KJob::Unit unit, qulonglong amount) 00318 { 00319 QString tmp; 00320 00321 switch(unit) 00322 { 00323 case KJob::Bytes: 00324 if (processedSize == amount) 00325 return; 00326 processedSize = amount; 00327 00328 if (totalSizeKnown) { 00329 tmp = i18np( "%2 of %3 complete", "%2 of %3 complete", 00330 amount, 00331 KGlobal::locale()->formatByteSize(amount), 00332 KGlobal::locale()->formatByteSize(totalSize)); 00333 } else { 00334 tmp = KGlobal::locale()->formatByteSize(amount); 00335 } 00336 sizeLabel->setText(tmp); 00337 if (!totalSizeKnown) // update jumping progressbar 00338 progressBar->setValue(amount); 00339 break; 00340 00341 case KJob::Directories: 00342 if (processedDirs == amount) 00343 return; 00344 processedDirs = amount; 00345 00346 tmp = i18np("%2 / %1 folder", "%2 / %1 folders", totalDirs, processedDirs); 00347 tmp += " "; 00348 tmp += i18np("%2 / %1 file", "%2 / %1 files", totalFiles, processedFiles); 00349 progressLabel->setText(tmp); 00350 break; 00351 00352 case KJob::Files: 00353 if (processedFiles == amount) 00354 return; 00355 processedFiles = amount; 00356 00357 if (totalDirs > 1) { 00358 tmp = i18np("%2 / %1 folder", "%2 / %1 folders", totalDirs, processedDirs); 00359 tmp += " "; 00360 } 00361 tmp += i18np("%2 / %1 file", "%2 / %1 files", totalFiles, processedFiles); 00362 progressLabel->setText(tmp); 00363 } 00364 } 00365 00366 void KWidgetJobTracker::Private::ProgressWidget::percent(unsigned long percent) 00367 { 00368 QString title = caption + " ("; 00369 00370 if (totalSizeKnown) { 00371 title += i18n("%1% of %2", percent, 00372 KGlobal::locale()->formatByteSize(totalSize)); 00373 } else if (totalFiles) { 00374 title += i18np("%2% of 1 file", "%2% of %1 files", totalFiles, percent); 00375 } else { 00376 title += i18n("%1%", percent); 00377 } 00378 00379 title += ')'; 00380 00381 progressBar->setMaximum(100); 00382 progressBar->setValue(percent); 00383 setWindowTitle(title); 00384 } 00385 00386 void KWidgetJobTracker::Private::ProgressWidget::speed(unsigned long value) 00387 { 00388 if (value == 0) { 00389 speedLabel->setText(i18n("Stalled")); 00390 } else { 00391 const QString speedStr = KGlobal::locale()->formatByteSize(value); 00392 if (totalSizeKnown) { 00393 const int remaining = 1000*(totalSize - processedSize)/value; 00394 speedLabel->setText(i18np("%2/s (%3 remaining)", "%2/s (%3 remaining)", remaining, speedStr, 00395 KGlobal::locale()->prettyFormatDuration(remaining))); 00396 } else { // total size is not known (#24228) 00397 speedLabel->setText(i18nc("speed in bytes per second", "%1/s", speedStr)); 00398 } 00399 } 00400 } 00401 00402 void KWidgetJobTracker::Private::ProgressWidget::slotClean() 00403 { 00404 percent(100); 00405 cancelClose->setGuiItem(KStandardGuiItem::close()); 00406 openFile->setEnabled(true); 00407 if (!totalSizeKnown || totalSize < processedSize) 00408 totalSize = processedSize; 00409 processedAmount(KJob::Bytes, totalSize); 00410 keepOpenCheck->setEnabled(false); 00411 pauseButton->setEnabled(false); 00412 if (!startTime.isNull()) { 00413 int s = startTime.elapsed(); 00414 if (!s) 00415 s = 1; 00416 speedLabel->setText(i18n("%1/s (done)", 00417 KGlobal::locale()->formatByteSize(1000 * totalSize / s))); 00418 } 00419 } 00420 00421 void KWidgetJobTracker::Private::ProgressWidget::suspended() 00422 { 00423 pauseButton->setText(i18n("&Resume")); 00424 suspendedProperty = true; 00425 } 00426 00427 void KWidgetJobTracker::Private::ProgressWidget::resumed() 00428 { 00429 pauseButton->setText(i18n("&Pause")); 00430 suspendedProperty = false; 00431 } 00432 00433 void KWidgetJobTracker::Private::ProgressWidget::closeEvent(QCloseEvent *event) 00434 { 00435 if (jobRegistered && tracker->stopOnClose(job)) { 00436 tracker->slotStop(job); 00437 } 00438 00439 QWidget::closeEvent(event); 00440 } 00441 00442 void KWidgetJobTracker::Private::ProgressWidget::init() 00443 { 00444 // Set a useful icon for this window! 00445 KWindowSystem::setIcons( winId(), 00446 KIconLoader::global()->loadIcon( "document-save", KIconLoader::NoGroup, 32 ), 00447 KIconLoader::global()->loadIcon( "document-save", KIconLoader::NoGroup, 16 ) ); 00448 00449 QVBoxLayout *topLayout = new QVBoxLayout(this); 00450 00451 QGridLayout *grid = new QGridLayout(); 00452 topLayout->addLayout(grid); 00453 grid->addItem(new QSpacerItem(KDialog::spacingHint(),0),0,1); 00454 // filenames or action name 00455 sourceInvite = new QLabel(i18nc("The source url of a job", "Source:"), this); 00456 grid->addWidget(sourceInvite, 0, 0); 00457 00458 sourceEdit = new KSqueezedTextLabel(this); 00459 sourceEdit->setTextInteractionFlags(Qt::TextSelectableByMouse); 00460 sourceEdit->installEventFilter(this); 00461 grid->addWidget(sourceEdit, 0, 2); 00462 00463 destInvite = new QLabel(i18nc("The destination url of a job", "Destination:"), this); 00464 grid->addWidget(destInvite, 1, 0); 00465 00466 destEdit = new KSqueezedTextLabel(this); 00467 destEdit->setTextInteractionFlags(Qt::TextSelectableByMouse); 00468 destEdit->installEventFilter(this); 00469 grid->addWidget(destEdit, 1, 2); 00470 00471 QHBoxLayout *progressHBox = new QHBoxLayout(); 00472 topLayout->addLayout(progressHBox); 00473 00474 progressBar = new QProgressBar(this); 00475 progressBar->setMaximum(0); // want a jumping progress bar if percent is not emitted 00476 progressHBox->addWidget(progressBar); 00477 00478 suspendedProperty = false; 00479 00480 // processed info 00481 QHBoxLayout *hBox = new QHBoxLayout(); 00482 topLayout->addLayout(hBox); 00483 00484 arrowButton = new KPushButton(this); 00485 arrowButton->setMaximumSize(QSize(32,25)); 00486 arrowButton->setIcon(KIcon("arrow-down")); 00487 arrowButton->setToolTip(i18n("Click this to expand the dialog, to show details")); 00488 arrowState = Qt::DownArrow; 00489 connect(arrowButton, SIGNAL(clicked()), this, SLOT(_k_arrowToggled())); 00490 hBox->addWidget(arrowButton); 00491 hBox->addStretch(1); 00492 00493 KSeparator *separator1 = new KSeparator(Qt::Horizontal, this); 00494 topLayout->addWidget(separator1); 00495 00496 sizeLabel = new QLabel(this); 00497 hBox->addWidget(sizeLabel, 0, Qt::AlignLeft); 00498 00499 resumeLabel = new QLabel(this); 00500 hBox->addWidget(resumeLabel); 00501 00502 pauseButton = new KPushButton(i18n("&Pause"), this); 00503 connect(pauseButton, SIGNAL(clicked()), this, SLOT(_k_pauseResumeClicked())); 00504 hBox->addWidget(pauseButton); 00505 00506 hBox = new QHBoxLayout(); 00507 topLayout->addLayout(hBox); 00508 00509 speedLabel = new QLabel(this); 00510 hBox->addWidget(speedLabel, 1); 00511 speedLabel->hide(); 00512 00513 hBox = new QHBoxLayout(); 00514 topLayout->addLayout(hBox); 00515 00516 progressLabel = new QLabel(this); 00517 progressLabel->setAlignment(Qt::AlignLeft); 00518 hBox->addWidget(progressLabel); 00519 progressLabel->hide(); 00520 00521 keepOpenCheck = new QCheckBox(i18n("&Keep this window open after transfer is complete"), this); 00522 connect(keepOpenCheck, SIGNAL(toggled(bool)), this, SLOT(_k_keepOpenToggled(bool))); 00523 topLayout->addWidget(keepOpenCheck); 00524 keepOpenCheck->hide(); 00525 00526 hBox = new QHBoxLayout(); 00527 topLayout->addLayout(hBox); 00528 00529 openFile = new KPushButton(i18n("Open &File"), this); 00530 connect(openFile, SIGNAL(clicked()), this, SLOT(_k_openFile())); 00531 hBox->addWidget(openFile); 00532 openFile->setEnabled(false); 00533 openFile->hide(); 00534 00535 openLocation = new KPushButton(i18n("Open &Destination"), this); 00536 connect(openLocation, SIGNAL(clicked()), this, SLOT(_k_openLocation())); 00537 hBox->addWidget(openLocation); 00538 openLocation->hide(); 00539 00540 hBox->addStretch(1); 00541 00542 cancelClose = new KPushButton(KStandardGuiItem::cancel(), this); 00543 connect(cancelClose, SIGNAL(clicked()), this, SLOT(_k_stop())); 00544 hBox->addWidget(cancelClose); 00545 00546 resize(sizeHint()); 00547 setMaximumHeight(sizeHint().height()); 00548 00549 setWindowTitle(i18n("Progress Dialog")); // show something better than kuiserver 00550 } 00551 00552 void KWidgetJobTracker::Private::ProgressWidget::showTotals() 00553 { 00554 // Show the totals in the progress label, if we still haven't 00555 // processed anything. This is useful when the stat'ing phase 00556 // of CopyJob takes a long time (e.g. over networks). 00557 if (processedFiles == 0 && processedDirs == 0) 00558 { 00559 QString tmps; 00560 if (totalDirs > 1) 00561 // that we have a singular to translate looks weired but is only logical 00562 tmps = i18np("%1 folder", "%1 folders", totalDirs) + " "; 00563 tmps += i18np("%1 file", "%1 files", totalFiles); 00564 progressLabel->setText( tmps ); 00565 } 00566 } 00567 00568 void KWidgetJobTracker::Private::ProgressWidget::setDestVisible(bool visible) 00569 { 00570 // We can't hide the destInvite/destEdit labels, 00571 // because it screws up the QGridLayout. 00572 if (visible) 00573 { 00574 destInvite->show(); 00575 destEdit->show(); 00576 } 00577 else 00578 { 00579 destInvite->hide(); 00580 destEdit->hide(); 00581 destInvite->setText( QString() ); 00582 destEdit->setText( QString() ); 00583 } 00584 setMaximumHeight(sizeHint().height()); 00585 } 00586 00587 void KWidgetJobTracker::Private::ProgressWidget::checkDestination(const KUrl &dest) 00588 { 00589 bool ok = true; 00590 00591 if (dest.isLocalFile()) { 00592 QString path = dest.toLocalFile( KUrl::RemoveTrailingSlash ); 00593 const QStringList tmpDirs = KGlobal::dirs()->resourceDirs( "tmp" ); 00594 for (QStringList::ConstIterator it = tmpDirs.begin() ; ok && it != tmpDirs.end() ; ++it) 00595 if (path.contains(*it)) 00596 ok = false; // it's in the tmp resource 00597 } 00598 00599 if (ok) { 00600 openFile->show(); 00601 openLocation->show(); 00602 keepOpenCheck->show(); 00603 setMaximumHeight(sizeHint().height()); 00604 location=dest; 00605 } 00606 } 00607 00608 void KWidgetJobTracker::Private::ProgressWidget::_k_keepOpenToggled(bool keepOpen) 00609 { 00610 if (keepOpen) { 00611 KGlobal::ref(); 00612 } else { 00613 KGlobal::deref(); 00614 } 00615 } 00616 00617 void KWidgetJobTracker::Private::ProgressWidget::_k_openFile() 00618 { 00619 QProcess::startDetached("kde-open", QStringList() << location.prettyUrl()); 00620 } 00621 00622 void KWidgetJobTracker::Private::ProgressWidget::_k_openLocation() 00623 { 00624 KUrl dirLocation(location); 00625 dirLocation.setFileName(QString()); 00626 QProcess::startDetached("kde-open", QStringList() << dirLocation.prettyUrl()); 00627 } 00628 00629 void KWidgetJobTracker::Private::ProgressWidget::_k_pauseResumeClicked() 00630 { 00631 if (jobRegistered && !suspendedProperty) { 00632 tracker->slotSuspend(job); 00633 } else if (jobRegistered) { 00634 tracker->slotResume(job); 00635 } 00636 } 00637 00638 void KWidgetJobTracker::Private::ProgressWidget::_k_stop() 00639 { 00640 if (jobRegistered) { 00641 tracker->slotStop(job); 00642 } 00643 closeNow(); 00644 } 00645 00646 void KWidgetJobTracker::Private::ProgressWidget::_k_arrowToggled() 00647 { 00648 if (arrowState == Qt::DownArrow) { 00649 //The arrow is in the down position, dialog is collapsed, expand it and change icon. 00650 progressLabel->show(); 00651 speedLabel->show(); 00652 arrowButton->setIcon(KIcon("arrow-up")); 00653 arrowButton->setToolTip(i18n("Click this to collapse the dialog, to hide details")); 00654 arrowState = Qt::UpArrow; 00655 } else { 00656 //Collapse the dialog 00657 progressLabel->hide(); 00658 speedLabel->hide(); 00659 arrowButton->setIcon(KIcon("arrow-down")); 00660 arrowButton->setToolTip(i18n("Click this to expand the dialog, to show details")); 00661 arrowState = Qt::DownArrow; 00662 } 00663 setMaximumHeight(sizeHint().height()); 00664 } 00665 00666 #include "kwidgetjobtracker.moc" 00667 #include "kwidgetjobtracker_p.moc"
KDE 4.6 API Reference