diff --git a/util/jobstatus.cpp b/util/jobstatus.cpp --- a/util/jobstatus.cpp +++ b/util/jobstatus.cpp @@ -24,47 +24,103 @@ #include #include -using namespace KDevelop; +#include +namespace KDevelop +{ -class KDevelop::JobStatusPrivate +class JobStatusPrivate : public QObject { public: - explicit JobStatusPrivate(JobStatus* q) : q(q) {} + explicit JobStatusPrivate(JobStatus* q, const QString& statusName); void slotPercent(KJob* job, unsigned long percent); - JobStatus* q; + void slotFinished(KJob *job); + void slotTimeout(); - KJob* m_job; + JobStatus* q; QString m_statusName; + + bool m_hasPercentSignal; + bool m_jobFinished; + + int m_percent; + + QTimer m_timer; + + /* Default timeout for StatusbarProgressWidget is 1000 msec. We must set 'local' timeout value + * greater than 1000, because we must be sured that StatusbarProgressWidget finish it's + * blocking for 'short-lived' statuses. After this we send 'end-signals' if job is already + * finished, this allows us to show status value (100%) for 'short-lived' jobs. + */ + static const int m_timeout = 1300; }; -void JobStatusPrivate::slotPercent(KJob* job, long unsigned int percent) +JobStatusPrivate::JobStatusPrivate(JobStatus* q, const QString& statusName) + : QObject(q) + , q(q) + , m_statusName(statusName) + , m_hasPercentSignal(false) + , m_jobFinished(false) + , m_percent(0) +{ + m_timer.setSingleShot(true); + connect(&m_timer, &QTimer::timeout, this, &JobStatusPrivate::slotTimeout); +} + +void JobStatusPrivate::slotPercent(KJob*, unsigned long percent) +{ + // Blocks percent signals while timer is active. This workaround is necessary + // due strange bug(?) of StatusbarProgressWidget - if we send such signals + // too frequently during initial blocking period then it don't show + // any progress :( + // This should be fixed in StatusbarProgressWidget(?) + if (m_timer.isActive()) + m_percent = percent; + else + emit q->showProgress(q, 0, 100, percent); + + if (!m_hasPercentSignal) { + m_hasPercentSignal = true; + m_timer.start(m_timeout); + } +} + +void JobStatusPrivate::slotFinished(KJob* job) +{ + m_jobFinished = true; + + if (job->error() == KJob::KilledJobError) + emit q->showErrorMessage(i18n("Task aborted")); + + slotTimeout(); +} + +void JobStatusPrivate::slotTimeout() { - Q_UNUSED(job); + if (m_jobFinished) { + emit q->showProgress(q, 0, 100, 100); - emit q->showProgress(q, 0, 100, percent); + if (!m_timer.isActive()) { + emit q->hideProgress(q); + q->deleteLater(); + } + } else + emit q->showProgress(q, 0, 100, m_percent); } JobStatus::JobStatus(KJob* job, const QString& statusName, QObject* parent) : QObject(parent) - , d(new JobStatusPrivate(this)) + , d(new JobStatusPrivate(this, statusName)) { - d->m_job = job; - d->m_statusName = statusName; + connect(job, &KJob::finished, d.data(), &JobStatusPrivate::slotFinished); connect(job, &KJob::infoMessage, this, [this](KJob*, const QString& plain, const QString&) { emit showMessage(this, plain); }); - connect(job, &KJob::finished, this, [this, job]() { - if (job->error() == KJob::KilledJobError) { - emit showErrorMessage(i18n("Task aborted")); - } - emit hideProgress(this); - deleteLater(); - }); + // no new-signal-slot syntax possible :( connect(job, SIGNAL(percent(KJob*, unsigned long)), this, SLOT(slotPercent(KJob*, unsigned long))); } @@ -78,4 +134,6 @@ return d->m_statusName; } +} + #include "moc_jobstatus.cpp"