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 <Friedemann.Kleint@nokia.com>

Change-Id: If9ff2ab99929d9b85a7ffa8f6fd47b045b982f67
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
Tero Ahola 2011-11-11 09:13:07 +01:00 committed by Qt by Nokia
parent ebfe3a4217
commit adcfc9f38b
2 changed files with 37 additions and 23 deletions

View File

@ -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<QProgressBar *>(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<QProgressBar *>(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<QProgressBar *>(o));
break;
#endif // QT_NO_PROGRESSBAR
default:
@ -341,7 +353,7 @@ void QWindowsStyle::unpolish(QWidget *widget)
if (QProgressBar *bar=qobject_cast<QProgressBar *>(widget)) {
Q_D(QWindowsStyle);
widget->removeEventFilter(this);
d->bars.removeAll(bar);
d->stopAnimation(this, bar);
}
#endif
}

View File

@ -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<const QWidget *> seenAlt;
int menuBarTimer;
QList<QProgressBar *> bars;
QList<QProgressBar *> animatedProgressBars;
int animationFps;
int animateTimer;
QElapsedTimer startTime;