From adcfc9f38b3d199452cfb128407006dc4cc02382 Mon Sep 17 00:00:00 2001 From: Tero Ahola Date: Fri, 11 Nov 2011 09:13:07 +0100 Subject: Fix QProgressBar causing timer event spam On Windows you will get a lot of timer events if you use QProgressBar widget. This is because QWindowsStyle uses a timer to animate a progress bar with unknown state (min and max values both zero). The issue was fixed by starting the timer only if needed. Task-number: QTBUG-10501 (cherry picked from commit 72e61b127470b044e370af7017fa8a5b0538244f) Reviewed-by: Friedemann Kleint Change-Id: If9ff2ab99929d9b85a7ffa8f6fd47b045b982f67 Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsstyle.cpp | 56 ++++++++++++++++++++++-------------- src/widgets/styles/qwindowsstyle_p.h | 4 ++- 2 files changed, 37 insertions(+), 23 deletions(-) (limited to 'src/widgets') diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 3460f5c913..6e8459767e 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -133,6 +133,26 @@ QWindowsStylePrivate::QWindowsStylePrivate() startTime.start(); } +void QWindowsStylePrivate::startAnimation(QObject *o, QProgressBar *bar) +{ + if (!animatedProgressBars.contains(bar)) { + animatedProgressBars << bar; + if (!animateTimer) { + Q_ASSERT(animationFps > 0); + animateTimer = o->startTimer(1000 / animationFps); + } + } +} + +void QWindowsStylePrivate::stopAnimation(QObject *o, QProgressBar *bar) +{ + animatedProgressBars.removeAll(bar); + if (animatedProgressBars.isEmpty() && animateTimer) { + o->killTimer(animateTimer); + animateTimer = 0; + } +} + // Returns true if the toplevel parent of \a widget has seen the Alt-key bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const { @@ -150,10 +170,8 @@ void QWindowsStyle::timerEvent(QTimerEvent *event) if (event->timerId() == d->animateTimer) { Q_ASSERT(d->animationFps> 0); d->animateStep = d->startTime.elapsed() / (1000 / d->animationFps); - foreach (QProgressBar *bar, d->bars) { - if ((bar->minimum() == 0 && bar->maximum() == 0)) - bar->update(); - } + foreach (QProgressBar *bar, d->animatedProgressBars) + bar->update(); } #endif // QT_NO_PROGRESSBAR event->ignore(); @@ -212,29 +230,23 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) break; #ifndef QT_NO_PROGRESSBAR case QEvent::StyleChange: + case QEvent::Paint: case QEvent::Show: if (QProgressBar *bar = qobject_cast(o)) { - if (!d->bars.contains(bar)) { - d->bars << bar; - if (d->bars.size() == 1) { - Q_ASSERT(d->animationFps> 0); - if (d->animateTimer == 0) - d->animateTimer = startTimer(1000 / d->animationFps); - } - } + // Animation by timer for progress bars that have their min and + // max values the same + if (bar->minimum() == bar->maximum()) + d->startAnimation(this, bar); + else + d->stopAnimation(this, bar); } break; case QEvent::Destroy: case QEvent::Hide: - // reinterpret_cast because there is no type info when getting - // the destroy event. We know that it is a QProgressBar. - if (QProgressBar *bar = reinterpret_cast(o)) { - d->bars.removeAll(bar); - if (d->bars.isEmpty() && d->animateTimer) { - killTimer(d->animateTimer); - d->animateTimer = 0; - } - } + // Do static_cast because there is no type info when getting + // the destroy event. We know that it is a QProgressBar, since + // we only install a widget event filter for QScrollBars. + d->stopAnimation(this, static_cast(o)); break; #endif // QT_NO_PROGRESSBAR default: @@ -341,7 +353,7 @@ void QWindowsStyle::unpolish(QWidget *widget) if (QProgressBar *bar=qobject_cast(widget)) { Q_D(QWindowsStyle); widget->removeEventFilter(this); - d->bars.removeAll(bar); + d->stopAnimation(this, bar); } #endif } diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h index b9f39a0940..1e517e9e79 100644 --- a/src/widgets/styles/qwindowsstyle_p.h +++ b/src/widgets/styles/qwindowsstyle_p.h @@ -71,13 +71,15 @@ class QWindowsStylePrivate : public QCommonStylePrivate Q_DECLARE_PUBLIC(QWindowsStyle) public: QWindowsStylePrivate(); + void startAnimation(QObject *o, QProgressBar *bar); + void stopAnimation(QObject *o, QProgressBar *bar); bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } bool alt_down; QList seenAlt; int menuBarTimer; - QList bars; + QList animatedProgressBars; int animationFps; int animateTimer; QElapsedTimer startTime; -- cgit v1.2.3