Introduce (private) QStyleAnimation
authorJ-P Nurmi <jpnurmi@digia.com>
Fri, 5 Oct 2012 08:42:10 +0000 (10:42 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 16 Oct 2012 13:29:15 +0000 (15:29 +0200)
QStyleAnimation handles style animations in a generic fashion by
sending StyleAnimationUpdate events back to the animation target
instead of calling QWidget::update() directly. This decouples style
animations from widgets and makes it possible to run style animations
for QQuickItems (ie. the desktop components).

The next step is to add "QObject* QStyleOption::target" and use that
everywhere instead of the widget pointer passed to various QStyle
methods.

Change-Id: Ib963c54872805fc3f0123ff922f82c9962a68b90
Reviewed-by: J-P Nurmi <jpnurmi@digia.com>
Reviewed-by: Jens Bache-Wiig <jens.bache-wiig@digia.com>
20 files changed:
src/widgets/styles/qcleanlooksstyle.cpp
src/widgets/styles/qcleanlooksstyle_p.h
src/widgets/styles/qcommonstyle.cpp
src/widgets/styles/qcommonstyle.h
src/widgets/styles/qcommonstyle_p.h
src/widgets/styles/qgtkstyle.cpp
src/widgets/styles/qmacstyle_mac.mm
src/widgets/styles/qmacstyle_mac_p.h
src/widgets/styles/qplastiquestyle.cpp
src/widgets/styles/qplastiquestyle.h
src/widgets/styles/qstyleanimation.cpp [new file with mode: 0644]
src/widgets/styles/qstyleanimation_p.h [new file with mode: 0644]
src/widgets/styles/qstylesheetstyle.cpp
src/widgets/styles/qwindowsstyle.cpp
src/widgets/styles/qwindowsstyle.h
src/widgets/styles/qwindowsstyle_p.h
src/widgets/styles/qwindowsvistastyle.cpp
src/widgets/styles/qwindowsvistastyle.h
src/widgets/styles/qwindowsvistastyle_p.h
src/widgets/styles/styles.pri

index 99e4b17..896f2ea 100644 (file)
@@ -67,6 +67,7 @@
 #include <qwizard.h>
 #include <qlibrary.h>
 #include <private/qstylehelper_p.h>
+#include <private/qstyleanimation_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -1759,9 +1760,11 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
             } else {
                 Q_D(const QCleanlooksStyle);
                 int slideWidth = ((rect.width() - 4) * 2) / 3;
-                int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth;
-                if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth)
-                    step = slideWidth - step;
+                int step = 0;
+#ifndef QT_NO_ANIMATION
+                if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(widget)))
+                    step = animation->progressStep(slideWidth);
+#endif
                 progressBar.setRect(rect.left() + 1 + step, rect.top() + 1,
                                     slideWidth / 2, rect.height() - 3);
             }
index ccf0d5e..5a6bef5 100644 (file)
@@ -66,7 +66,6 @@ class QCleanlooksStylePrivate : public QWindowsStylePrivate
 public:
     QCleanlooksStylePrivate()
         : QWindowsStylePrivate() {
-        animationFps = 24;
     }
 
     ~QCleanlooksStylePrivate() {
index 5c34cae..50fceab 100644 (file)
@@ -75,6 +75,7 @@
 #include <qsettings.h>
 #include <qvariant.h>
 #include <qpixmapcache.h>
+#include <private/qstyleanimation_p.h>
 
 #include <limits.h>
 
@@ -1048,6 +1049,57 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget
 }
 #endif //QT_NO_TABBAR
 
+/*! \internal */
+QList<const QObject*> QCommonStylePrivate::animationTargets() const
+{
+    return animations.keys();
+}
+
+/*! \internal */
+QStyleAnimation * QCommonStylePrivate::animation(const QObject *target) const
+{
+    return animations.value(target);
+}
+
+/*! \internal */
+void QCommonStylePrivate::startAnimation(QStyleAnimation *animation)
+{
+#ifndef QT_NO_ANIMATION
+    Q_Q(QCommonStyle);
+    stopAnimation(animation->target());
+    q->connect(animation, SIGNAL(finished()), SLOT(_q_removeAnimation()), Qt::UniqueConnection);
+    q->connect(animation, SIGNAL(destroyed()), SLOT(_q_removeAnimation()), Qt::UniqueConnection);
+    animations.insert(animation->target(), animation);
+    animation->start();
+#endif // QT_NO_ANIMATION
+}
+
+/*! \internal */
+void QCommonStylePrivate::stopAnimation(const QObject *target)
+{
+#ifndef QT_NO_ANIMATION
+    QStyleAnimation *animation = animations.value(target);
+    if (animation) {
+        if (animation->state() == QAbstractAnimation::Stopped)
+            animations.take(target)->deleteLater();
+        else
+            animation->stop();
+    }
+#endif // QT_NO_ANIMATION
+}
+
+/*! \internal */
+void QCommonStylePrivate::_q_removeAnimation()
+{
+#ifndef QT_NO_ANIMATION
+    Q_Q(QCommonStyle);
+    QObject *animation = q->sender();
+    if (animation) {
+        animations.remove(animation->parent());
+        animation->deleteLater();
+    }
+#endif // QT_NO_ANIMATION
+}
 
 /*!
   \reimp
@@ -5903,3 +5955,5 @@ void QCommonStyle::unpolish(QApplication *application)
 
 
 QT_END_NAMESPACE
+
+#include "moc_qcommonstyle.cpp"
index ba0837a..8782137 100644 (file)
@@ -100,6 +100,7 @@ protected:
 private:
     Q_DECLARE_PRIVATE(QCommonStyle)
     Q_DISABLE_COPY(QCommonStyle)
+    Q_PRIVATE_SLOT(d_func(), void _q_removeAnimation())
 };
 
 QT_END_NAMESPACE
index 496723f..2032e06 100644 (file)
@@ -44,6 +44,7 @@
 
 #include "qcommonstyle.h"
 #include "qstyle_p.h"
+#include "qstyleanimation_p.h"
 
 #include "qstyleoption.h"
 
@@ -67,17 +68,24 @@ class QCommonStylePrivate : public QStylePrivate
 {
     Q_DECLARE_PUBLIC(QCommonStyle)
 public:
-    inline QCommonStylePrivate()
+    inline QCommonStylePrivate() :
 #ifndef QT_NO_ITEMVIEWS
-    : cachedOption(0)
+    cachedOption(0),
 #endif
+    animationFps(30)
     { }
 
-#ifndef QT_NO_ITEMVIEWS
     ~QCommonStylePrivate()
     {
+#ifndef QT_NO_ANIMATION
+        qDeleteAll(animations);
+#endif
+#ifndef QT_NO_ITEMVIEWS
         delete cachedOption;
+#endif
     }
+
+#ifndef QT_NO_ITEMVIEWS
     void viewItemDrawText(QPainter *p, const QStyleOptionViewItem *option, const QRect &rect) const;
     void viewItemLayout(const QStyleOptionViewItem *opt,  QRect *checkRect,
                         QRect *pixmapRect, QRect *textRect, bool sizehint) const;
@@ -106,6 +114,17 @@ public:
 #ifndef QT_NO_TABBAR
     void tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const;
 #endif
+
+    int animationFps;
+    void _q_removeAnimation();
+
+    QList<const QObject*> animationTargets() const;
+    QStyleAnimation* animation(const QObject *target) const;
+    void startAnimation(QStyleAnimation *animation);
+    void stopAnimation(const QObject *target);
+
+private:
+    QHash<const QObject*, QStyleAnimation*> animations;
 };
 
 QT_END_NAMESPACE
index 9bcf45e..83e70d0 100644 (file)
@@ -71,6 +71,7 @@
 #include <QtWidgets/QWizard>
 
 #include <qpixmapcache.h>
+#include <private/qstyleanimation_p.h>
 #undef signals // Collides with GTK stymbols
 #include <private/qgtkpainter_p.h>
 #include <private/qstylehelper_p.h>
@@ -3491,9 +3492,11 @@ void QGtkStyle::drawControl(ControlElement element,
             } else {
                 Q_D(const QGtkStyle);
                 int slideWidth = ((rect.width() - 4) * 2) / 3;
-                int step = ((d->animateStep * slideWidth) / d->animationFps) % slideWidth;
-                if ((((d->animateStep * slideWidth) / d->animationFps) % (2 * slideWidth)) >= slideWidth)
-                    step = slideWidth - step;
+                int step = 0;
+#ifndef QT_NO_ANIMATION
+                if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(widget)))
+                    step = animation->progressStep(slideWidth);
+#endif
                 progressBar.setRect(rect.left() + step, rect.top(), slideWidth / 2, rect.height());
             }
 
index ecb3e7f..77656f9 100644 (file)
 #include <QtWidgets/qgraphicsproxywidget.h>
 #include <QtWidgets/qgraphicsview.h>
 #include <private/qstylehelper_p.h>
+#include <private/qstyleanimation_p.h>
 #include <qpa/qplatformfontdatabase.h>
 
 QT_USE_NAMESPACE
@@ -125,9 +126,9 @@ QMacStylePrivate *mPrivate;
 {
     Q_UNUSED(notification);
     QEvent event(QEvent::StyleChange);
-    Q_FOREACH (QPointer<QWidget> sb, mPrivate->scrollBars) {
-        if (sb)
-            QCoreApplication::sendEvent(sb, &event);
+    Q_FOREACH (const QObject* target, mPrivate->animationTargets()) {
+        if (target)
+            QCoreApplication::sendEvent(const_cast<QObject*>(target), &event);
     }
 }
 @end
@@ -1668,7 +1669,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
 }
 
 QMacStylePrivate::QMacStylePrivate()
-    : timerID(-1), progressFrame(0), mouseDown(false)
+    : mouseDown(false)
 {
     defaultButtonStart = CFAbsoluteTimeGetCurrent();
     memset(&buttonState, 0, sizeof(ButtonState));
@@ -1696,54 +1697,42 @@ bool QMacStylePrivate::animatable(QMacStylePrivate::Animates as, const QWidget *
             }
             return true;
         }
-    } else if (as == AquaProgressBar) {
-        if (progressBars.contains((const_cast<QWidget *>(w))))
-            return true;
-    } else if (as == AquaScrollBar) {
-        if (scrollBars.contains((const_cast<QWidget *>(w))))
-            return true;
     }
-    return false;
+    return animation(w);
 }
 
 void QMacStylePrivate::stopAnimate(QMacStylePrivate::Animates as, QWidget *w)
 {
+    stopAnimation(w);
     if (as == AquaPushButton && defaultButton) {
+        stopAnimation(defaultButton);
         QPushButton *tmp = defaultButton;
         defaultButton = 0;
         tmp->update();
-    } else if (as == AquaProgressBar) {
-        progressBars.removeAll(w);
     } else if (as == AquaScrollBar) {
-        scrollBars.removeAll(w);
         scrollBarInfos.remove(w);
     }
 }
 
 void QMacStylePrivate::startAnimate(QMacStylePrivate::Animates as, QWidget *w)
 {
+#ifndef QT_NO_ANIMATION
+    if (!animation(w))
+    {
+        if (as == AquaProgressBar)
+            startAnimation(new QProgressStyleAnimation(animateSpeed(as), w));
+        else
+            startAnimation(new QStyleAnimation(w));
+    }
+#endif
     if (as == AquaPushButton)
         defaultButton = static_cast<QPushButton *>(w);
-    else if (as == AquaProgressBar)
-        progressBars.append(w);
-    else if (as == AquaScrollBar)
-        scrollBars.append(w);
-    startAnimationTimer();
-}
-
-void QMacStylePrivate::startAnimationTimer()
-{
-    Q_Q(QMacStyle);
-    if ((defaultButton || !progressBars.isEmpty() || !scrollBars.isEmpty()) && timerID <= -1)
-        timerID = q->startTimer(animateSpeed(AquaListViewItemOpen));
 }
 
 bool QMacStylePrivate::addWidget(QWidget *w)
 {
     //already knew of it
-    if (static_cast<QPushButton*>(w) == defaultButton
-            || progressBars.contains(static_cast<QProgressBar*>(w))
-            || scrollBars.contains(static_cast<QScrollBar*>(w)))
+    if (w == defaultButton || animation(w))
         return false;
 
     Q_Q(QMacStyle);
@@ -1802,68 +1791,6 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
     return tds;
 }
 
-void QMacStylePrivate::animate()
-{
-    Q_Q(QMacStyle);
-    int animated = 0;
-    if (defaultButton && defaultButton->isEnabled() && defaultButton->window()->isActiveWindow()
-        && defaultButton->isVisibleTo(0) && (defaultButton->isDefault()
-        || (defaultButton->autoDefault() && defaultButton->hasFocus()))
-        && doAnimate(AquaPushButton)) {
-        ++animated;
-        defaultButton->update();
-    }
-    if (!progressBars.isEmpty()) {
-        int i = 0;
-        while (i < progressBars.size()) {
-            QWidget *maybeProgress = progressBars.at(i);
-            if (!maybeProgress) {
-                progressBars.removeAt(i);
-            } else {
-                if (QProgressBar *pb = qobject_cast<QProgressBar *>(maybeProgress)) {
-                    if (pb->maximum() == 0 || (pb->value() > 0 && pb->value() < pb->maximum())) {
-                        if (doAnimate(AquaProgressBar))
-                            pb->update();
-                    }
-                }
-                ++i;
-            }
-        }
-        if (i > 0) {
-            ++progressFrame;
-            animated += i;
-        }
-    }
-    if (!scrollBars.isEmpty()) {
-        int i = 0;
-        const qint64 dt = QDateTime::currentMSecsSinceEpoch();
-        while (i < scrollBars.size()) {
-            QWidget *maybeScroll = scrollBars.at(i);
-            if (!maybeScroll) {
-                scrollBars.removeAt(i);
-            } else {
-                if (QScrollBar *sb = qobject_cast<QScrollBar *>(maybeScroll)) {
-                    const OverlayScrollBarInfo& info = scrollBarInfos[sb];
-                    const qreal elapsed = qMax(dt - info.lastHovered,
-                                               dt - info.lastUpdate);
-                    const CGFloat opacity = 1.0 - qMax(0.0, (elapsed - ScrollBarFadeOutDelay) /
-                                                             ScrollBarFadeOutDuration);
-                    if ((opacity > 0.0 || !info.cleared) && (elapsed > ScrollBarFadeOutDelay)) {
-                        if (doAnimate(AquaScrollBar))
-                            sb->update();
-                    }
-                }
-                ++i;
-                ++animated;
-            }
-        }
-    }
-    if (animated <= 0) {
-        q->killTimer(timerID);
-        timerID = -1;
-    }
-}
-
 /*! \reimp */
 bool QMacStyle::eventFilter(QObject *o, QEvent *e)
 {
@@ -1874,12 +1801,11 @@ bool QMacStyle::eventFilter(QObject *o, QEvent *e)
         default:
             break;
         case QEvent::Show:
-            if (!d->progressBars.contains(pb))
-                d->startAnimate(QMacStylePrivate::AquaProgressBar, pb);
+            d->startAnimate(QMacStylePrivate::AquaProgressBar, pb);
             break;
         case QEvent::Destroy:
         case QEvent::Hide:
-            d->progressBars.removeAll(pb);
+            d->stopAnimate(QMacStylePrivate::AquaProgressBar, pb);
         }
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
     } else if (QScrollBar *sb = qobject_cast<QScrollBar *>(o)) {
@@ -1986,17 +1912,6 @@ bool QMacStyle::eventFilter(QObject *o, QEvent *e)
     return false;
 }
 
-bool QMacStylePrivate::doAnimate(QMacStylePrivate::Animates as)
-{
-    if (as == AquaPushButton) {
-    } else if (as == AquaProgressBar) {
-        // something for later...
-    } else if (as == AquaListViewItemOpen) {
-        // To be revived later...
-    }
-    return true;
-}
-
 void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
                                            QPainter *p, const QStyleOption *opt) const
 {
@@ -3754,7 +3669,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
                 bdi.adornment |= kThemeAdornmentDefault;
                 bdi.animation.time.start = d->defaultButtonStart;
                 bdi.animation.time.current = CFAbsoluteTimeGetCurrent();
-                const_cast<QMacStylePrivate*>(d)->startAnimationTimer();
             }
             // Unlike Carbon, we want the button to always be drawn inside its bounds.
             // Therefore, make the button a bit smaller, so that even if it got focus,
@@ -4462,7 +4376,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
             tdi.min = pb->minimum;
             tdi.value = pb->progress;
             tdi.attributes = vertical ? 0 : kThemeTrackHorizontal;
-            tdi.trackInfo.progress.phase = d->progressFrame;
+#ifndef QT_NO_ANIMATION
+            if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(w)))
+                tdi.trackInfo.progress.phase = animation->animationStep();
+#endif
             if (!(pb->state & State_Active))
                 tdi.enableState = kThemeTrackInactive;
             else if (!(pb->state & State_Enabled))
@@ -6514,9 +6431,6 @@ bool QMacStyle::event(QEvent *e)
     } else if(e->type() == QEvent::FocusOut) {
         if(d->focusWidget)
             d->focusWidget->setWidget(0);
-    } else if (e->type() == QEvent::Timer) {
-        if (static_cast<QTimerEvent*>(e)->timerId() == d->timerID)
-            d->animate();
     }
     return false;
 }
index ac482b8..63cc005 100644 (file)
@@ -172,8 +172,6 @@ public:
                              QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
     void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider,
                           HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const;
-    void animate();
-    bool doAnimate(Animates);
     inline int animateSpeed(Animates) const { return 33; }
 
     // Utility functions
@@ -202,13 +200,8 @@ public:
                                HIThemeButtonDrawInfo *bdi) const;
     QPixmap generateBackgroundPattern() const;
 
-    void startAnimationTimer();
-
 public:
     QPointer<QPushButton> defaultButton; //default push buttons
-    int timerID;
-    QList<QPointer<QWidget> > progressBars; //existing progress bars that need animation
-    QList<QPointer<QWidget> > scrollBars; //existing scroll bars that need animation
 
     struct OverlayScrollBarInfo {
         OverlayScrollBarInfo()
@@ -235,7 +228,6 @@ public:
         int frame;
         enum { ButtonDark, ButtonLight } dir;
     } buttonState;
-    UInt8 progressFrame;
     mutable QPointer<QFocusFrame> focusWidget;
     CFAbsoluteTime defaultButtonStart;
     bool mouseDown;
index d22f82f..fe1e5c3 100644 (file)
@@ -79,7 +79,6 @@ static const int blueFrameWidth =  2;  // with of line edit focus frame
 #include <qsplitter.h>
 #include <qstyleoption.h>
 #include <qtextedit.h>
-#include <qelapsedtimer.h>
 #include <qtoolbar.h>
 #include <qtoolbox.h>
 #include <qtoolbutton.h>
@@ -89,6 +88,7 @@ static const int blueFrameWidth =  2;  // with of line edit focus frame
 #include <private/qstylehelper_p.h>
 #include <qpa/qplatformtheme.h>
 #include <private/qguiapplication_p.h>
+#include <private/qstyleanimation_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -987,12 +987,6 @@ public:
     virtual ~QPlastiqueStylePrivate();
     void drawPartialFrame(QPainter *painter, const QStyleOptionComplex *option,
                           const QRect &rect, const QWidget *widget) const;
-
-#ifndef QT_NO_PROGRESSBAR
-    QList<QProgressBar *> bars;
-    int progressBarAnimateTimer;
-    QElapsedTimer timer;
-#endif
 };
 
 /*!
@@ -1000,9 +994,6 @@ public:
  */
 QPlastiqueStylePrivate::QPlastiqueStylePrivate() :
     QWindowsStylePrivate()
-#ifndef QT_NO_PROGRESSBAR
-    , progressBarAnimateTimer(0)
-#endif
 {
 }
 
@@ -2577,9 +2568,11 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
                 }
             } else {
                 int slideWidth = ((rect.width() - 4) * 2) / 3;
-                int step = ((d->animateStep * slideWidth) / ProgressBarFps) % slideWidth;
-                if ((((d->animateStep * slideWidth) / ProgressBarFps) % (2 * slideWidth)) >= slideWidth)
-                    step = slideWidth - step;
+                int step = 0;
+#ifndef QT_NO_ANIMATION
+                if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(widget)))
+                    step = animation->progressStep(slideWidth);
+#endif
                 progressBar.setRect(rect.left() + 2 + step, rect.top() + 2,
                                     slideWidth / 2, rect.height() - 4);
             }
@@ -2732,7 +2725,13 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
             if (!vertical)
                 progressBar.adjust(0, 1, 0, 1);
             if (!indeterminate) {
-                int step = (AnimateProgressBar || (indeterminate && AnimateBusyProgressBar)) ? (d->animateStep % 20) : 0;
+                int step = 0;
+                if (AnimateProgressBar || (indeterminate && AnimateBusyProgressBar)) {
+#ifndef QT_NO_ANIMATION
+                    if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(widget)))
+                        step = animation->animationStep() % 20;
+#endif
+                }
                 if (reverse)
                     painter->drawPixmap(progressBar.left() - 25 + step, progressBar.top(), cache);
                 else
@@ -5706,11 +5705,8 @@ void QPlastiqueStyle::unpolish(QWidget *widget)
     }
 
 #ifndef QT_NO_PROGRESSBAR
-    if (AnimateBusyProgressBar && qobject_cast<QProgressBar *>(widget)) {
-        Q_D(QPlastiqueStyle);
+    if (AnimateBusyProgressBar && qobject_cast<QProgressBar *>(widget))
         widget->removeEventFilter(this);
-        d->bars.removeAll(static_cast<QProgressBar*>(widget));
-    }
 #endif
 
 #if defined QPlastique_MaskButtons
@@ -5834,24 +5830,13 @@ bool QPlastiqueStyle::eventFilter(QObject *watched, QEvent *event)
 
     switch (event->type()) {
     case QEvent::Show:
-        if (QProgressBar *bar = qobject_cast<QProgressBar *>(watched)) {
-            d->bars.append(bar);
-            if (d->bars.size() == 1) {
-                Q_ASSERT(ProgressBarFps > 0);
-                d->timer.start();
-                d->progressBarAnimateTimer = startTimer(1000 / ProgressBarFps);
-            }
-        }
+        if (QProgressBar *bar = qobject_cast<QProgressBar *>(watched))
+            d->startProgressAnimation(this, bar);
         break;
     case QEvent::Destroy:
     case QEvent::Hide:
-        if(!d->bars.isEmpty()) {
-            d->bars.removeAll(reinterpret_cast<QProgressBar*>(watched));
-            if (d->bars.isEmpty()) {
-                killTimer(d->progressBarAnimateTimer);
-                d->progressBarAnimateTimer = 0;
-            }
-        }
+        if (QProgressBar *bar = qobject_cast<QProgressBar *>(watched))
+            d->stopProgressAnimation(this, bar);
         break;
 #if defined QPlastique_MaskButtons
     case QEvent::Resize:
@@ -5879,26 +5864,6 @@ bool QPlastiqueStyle::eventFilter(QObject *watched, QEvent *event)
     return QWindowsStyle::eventFilter(watched, event);
 }
 
-/*!
-    \reimp
-*/
-void QPlastiqueStyle::timerEvent(QTimerEvent *event)
-{
-#ifndef QT_NO_PROGRESSBAR
-    Q_D(QPlastiqueStyle);
-
-    if (event->timerId() == d->progressBarAnimateTimer) {
-        Q_ASSERT(ProgressBarFps > 0);
-        d->animateStep = d->timer.elapsed() / (1000 / ProgressBarFps);
-        foreach (QProgressBar *bar, d->bars) {
-            if (AnimateProgressBar || (bar->minimum() == 0 && bar->maximum() == 0))
-                bar->update();
-        }
-    }
-#endif // QT_NO_PROGRESSBAR
-    event->ignore();
-}
-
 QT_END_NAMESPACE
 
 #endif // !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN)
index 05679a8..bda686e 100644 (file)
@@ -101,7 +101,6 @@ public:
 
 protected:
     bool eventFilter(QObject *watched, QEvent *event);
-    void timerEvent(QTimerEvent *event);
 
 private:
     Q_DISABLE_COPY(QPlastiqueStyle)
diff --git a/src/widgets/styles/qstyleanimation.cpp b/src/widgets/styles/qstyleanimation.cpp
new file mode 100644 (file)
index 0000000..8bc8e9d
--- /dev/null
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstyleanimation_p.h"
+#include <qcoreapplication.h>
+#include <qprogressbar.h>
+#include <qwidget.h>
+#include <qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_ANIMATION
+
+QStyleAnimation::QStyleAnimation(QObject *target) : QAbstractAnimation(target),
+    _startTime(QTime::currentTime())
+{
+}
+
+QStyleAnimation::~QStyleAnimation()
+{
+}
+
+int QStyleAnimation::duration() const
+{
+    return -1;
+}
+
+QObject *QStyleAnimation::target() const
+{
+    return parent();
+}
+
+QTime QStyleAnimation::startTime() const
+{
+    return _startTime;
+}
+
+void QStyleAnimation::setStartTime(const QTime &time)
+{
+    _startTime = time;
+}
+
+bool QStyleAnimation::isUpdateNeeded() const
+{
+    return true;
+}
+
+void QStyleAnimation::updateCurrentTime(int)
+{
+    if (target()->isWidgetType()) {
+        QWidget *widget = static_cast<QWidget *>(target());
+        if (!widget->isVisible() || widget->window()->isMinimized())
+            stop();
+    }
+
+    if (isUpdateNeeded()) {
+        QEvent event(QEvent::StyleAnimationUpdate);
+        QCoreApplication::sendEvent(target(), &event);
+    }
+}
+
+QProgressStyleAnimation::QProgressStyleAnimation(int speed, QObject *target) :
+    QStyleAnimation(target), _speed(speed), _step(-1)
+{
+}
+
+int QProgressStyleAnimation::animationStep() const
+{
+    return currentTime() / (1000.0 / _speed);
+}
+
+int QProgressStyleAnimation::progressStep(int width) const
+{
+    int step = animationStep();
+    int progress = (step * width / _speed) % width;
+    if (((step * width / _speed) % (2 * width)) >= width)
+        progress = width - progress;
+    return progress;
+}
+
+int QProgressStyleAnimation::speed() const
+{
+    return _speed;
+}
+
+void QProgressStyleAnimation::setSpeed(int speed)
+{
+    _speed = speed;
+}
+
+bool QProgressStyleAnimation::isUpdateNeeded() const
+{
+    QProgressBar *pb = qobject_cast<QProgressBar*>(parent());
+    if (pb && pb->minimum() == 0 && pb->maximum() == 0) {
+        int current = animationStep();
+        if (_step == -1 || _step != current)
+        {
+            _step = current;
+            return true;
+        }
+    } else {
+        // the progress bar is no longer indeterminate -> stop
+        const_cast<QProgressStyleAnimation *>(this)->stop();
+    }
+    return false;
+}
+
+#endif // QT_NO_ANIMATION
+
+QT_END_NAMESPACE
diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h
new file mode 100644 (file)
index 0000000..2c00048
--- /dev/null
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTYLEANIMATION_P_H
+#define QSTYLEANIMATION_P_H
+
+#include "qabstractanimation.h"
+#include "qdatetime.h"
+
+QT_BEGIN_NAMESPACE
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API. It exists for the convenience of
+// qcommonstyle.cpp.  This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QT_NO_ANIMATION
+
+class QStyleAnimation : public QAbstractAnimation
+{
+    Q_OBJECT
+
+public:
+    QStyleAnimation(QObject *target);
+    virtual ~QStyleAnimation();
+
+    int duration() const;
+    QObject *target() const;
+
+    QTime startTime() const;
+    void setStartTime(const QTime &time);
+
+protected:
+    virtual bool isUpdateNeeded() const;
+    virtual void updateCurrentTime(int time);
+
+private:
+    QTime _startTime;
+};
+
+class QProgressStyleAnimation : public QStyleAnimation
+{
+    Q_OBJECT
+
+public:
+    QProgressStyleAnimation(int speed, QObject *target);
+
+    int animationStep() const;
+    int progressStep(int width) const;
+
+    int speed() const;
+    void setSpeed(int speed);
+
+protected:
+    bool isUpdateNeeded() const;
+
+private:
+    int _speed;
+    mutable int _step;
+};
+
+#endif // QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+#endif // QSTYLEANIMATION_P_H
index 1cd9a98..068b7a4 100644 (file)
@@ -71,6 +71,7 @@
 #include <qheaderview.h>
 #include <qprogressbar.h>
 #include <private/qwindowsstyle_p.h>
+#include <private/qstyleanimation_p.h>
 #include <qtabbar.h>
 #include <QMetaProperty>
 #include <qmainwindow.h>
@@ -3832,7 +3833,11 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
                 if (pb->minimum == 0 && pb->maximum == 0) {
                     Q_D(const QWindowsStyle);
                     int chunkCount = fillWidth/chunkWidth;
-                    int offset = (d->animateStep*8%rect.width());
+                    int offset = 0;
+#ifndef QT_NO_ANIMATION
+                    if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(w)))
+                        offset = animation->animationStep() * 8 % rect.width();
+#endif
                     int x = reverse ? r.left() + r.width() - offset - chunkWidth : r.x() + offset;
                     while (chunkCount > 0) {
                         r.setRect(x, rect.y(), chunkWidth, rect.height());
index 355ecf8..ee13852 100644 (file)
@@ -70,6 +70,7 @@
 #include <qmath.h>
 
 #include <private/qstylehelper_p.h>
+#include <private/qstyleanimation_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -117,7 +118,7 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight };
     \internal
 */
 QWindowsStylePrivate::QWindowsStylePrivate()
-    : alt_down(false), menuBarTimer(0), animationFps(10), animateTimer(0), animateStep(0)
+    : alt_down(false), menuBarTimer(0)
 {
 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
     if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
@@ -126,27 +127,21 @@ QWindowsStylePrivate::QWindowsStylePrivate()
         pSHGetStockIconInfo = (PtrSHGetStockIconInfo)shellLib.resolve("SHGetStockIconInfo");
     }
 #endif
-    startTime.start();
 }
 
-void QWindowsStylePrivate::startAnimation(QObject *o, QProgressBar *bar)
+void QWindowsStylePrivate::startProgressAnimation(QObject *o, QProgressBar *bar)
 {
-    if (!animatedProgressBars.contains(bar)) {
-        animatedProgressBars << bar;
-        if (!animateTimer) {
-            Q_ASSERT(animationFps > 0);
-            animateTimer = o->startTimer(1000 / animationFps);
-        }
-    }
+    Q_UNUSED(o);
+#ifndef QT_NO_ANIMATION
+    if (!animation(bar))
+        startAnimation(new QProgressStyleAnimation(animationFps, bar));
+#endif
 }
 
-void QWindowsStylePrivate::stopAnimation(QObject *o, QProgressBar *bar)
+void QWindowsStylePrivate::stopProgressAnimation(QObject *o, QProgressBar *bar)
 {
-    animatedProgressBars.removeAll(bar);
-    if (animatedProgressBars.isEmpty() && animateTimer) {
-        o->killTimer(animateTimer);
-        animateTimer = 0;
-    }
+    Q_UNUSED(o);
+    stopAnimation(bar);
 }
 
 // Returns true if the toplevel parent of \a widget has seen the Alt-key
@@ -159,23 +154,6 @@ bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const
 /*!
     \reimp
 */
-void QWindowsStyle::timerEvent(QTimerEvent *event)
-{
-#ifndef QT_NO_PROGRESSBAR
-    Q_D(QWindowsStyle);
-    if (event->timerId() == d->animateTimer) {
-        Q_ASSERT(d->animationFps> 0);
-        d->animateStep = d->startTime.elapsed() / (1000 / d->animationFps);
-        foreach (QProgressBar *bar, d->animatedProgressBars)
-            bar->update();
-    }
-#endif // QT_NO_PROGRESSBAR
-    event->ignore();
-}
-
-/*!
-    \reimp
-*/
 bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
 {
     // Records Alt- and Focus events
@@ -232,9 +210,9 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
             // Animation by timer for progress bars that have their min and
             // max values the same
             if (bar->minimum() == bar->maximum())
-                d->startAnimation(this, bar);
+                d->startProgressAnimation(this, bar);
             else
-                d->stopAnimation(this, bar);
+                d->stopProgressAnimation(this, bar);
         }
         break;
     case QEvent::Destroy:
@@ -242,7 +220,7 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e)
         // 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));
+        d->stopProgressAnimation(this, static_cast<QProgressBar *>(o));
         break;
 #endif // QT_NO_PROGRESSBAR
     default:
@@ -349,7 +327,7 @@ void QWindowsStyle::unpolish(QWidget *widget)
     if (QProgressBar *bar=qobject_cast<QProgressBar *>(widget)) {
         Q_D(QWindowsStyle);
         widget->removeEventFilter(this);
-        d->stopAnimation(this, bar);
+        d->stopProgressAnimation(this, bar);
     }
 #endif
 }
@@ -2405,8 +2383,12 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
                 pbBits.rect = rect;
                 pbBits.palette = pal2;
 
+                int step = 0;
                 int chunkCount = w / unit_width + 1;
-                int step = d->animateStep%chunkCount;
+#ifndef QT_NO_ANIMATION
+                if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(widget)))
+                    step = (animation->animationStep() / 3) % chunkCount;
+#endif
                 int chunksInRow = 5;
                 int myY = pbBits.rect.y();
                 int myHeight = pbBits.rect.height();
index cacaeaa..1d9347a 100644 (file)
@@ -91,7 +91,6 @@ public:
 
 protected:
     bool eventFilter(QObject *o, QEvent *e);
-    void timerEvent(QTimerEvent *event);
     QWindowsStyle(QWindowsStylePrivate &dd);
 
 private:
index 0cf53b9..f24696f 100644 (file)
@@ -59,7 +59,6 @@
 #ifndef QT_NO_STYLE_WINDOWS
 #include <qlist.h>
 #include <qhash.h>
-#include <qelapsedtimer.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -71,19 +70,14 @@ class QWindowsStylePrivate : public QCommonStylePrivate
     Q_DECLARE_PUBLIC(QWindowsStyle)
 public:
     QWindowsStylePrivate();
-    void startAnimation(QObject *o, QProgressBar *bar);
-    void stopAnimation(QObject *o, QProgressBar *bar);
+    void startProgressAnimation(QObject *o, QProgressBar *bar);
+    void stopProgressAnimation(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 *> animatedProgressBars;
-    int animationFps;
-    int animateTimer;
-    QElapsedTimer startTime;
-    int animateStep;    
     QColor inactiveCaptionText;
     QColor activeCaptionColor;
     QColor activeGradientCaptionColor;
index cb34a20..d1a0af3 100644 (file)
@@ -43,6 +43,7 @@
 #include "qwindowsvistastyle_p.h"
 #include <qscreen.h>
 #include <qwindow.h>
+#include <private/qstyleanimation_p.h>
 #include <private/qstylehelper_p.h>
 #include <private/qsystemlibrary_p.h>
 #include <private/qapplication_p.h>
@@ -202,6 +203,11 @@ void QWindowsVistaAnimation::paint(QPainter *painter, const QStyleOption *option
     Q_UNUSED(painter);
 }
 
+bool QWindowsVistaAnimation::isUpdateNeeded() const
+{
+    return QWindowsVistaStylePrivate::useVista();
+}
+
 /*! \internal
 
   Helperfunction to paint the current transition state between two
@@ -255,7 +261,7 @@ void QWindowsVistaAnimation::drawBlendedImage(QPainter *painter, QRect rect, flo
 /*! \internal
   Paints a transition state. The result will be a mix between the
   initial and final state of the transition, depending on the time
-  difference between _startTime and current time.
+  difference between startTime and current time.
 */
 void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *option)
 {
@@ -263,18 +269,18 @@ void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *optio
     if (_duration > 0) {
         QTime current = QTime::currentTime();
 
-        if (_startTime > current)
-            _startTime = current;
+        if (startTime() > current)
+            setStartTime(current);
 
-        int timeDiff = _startTime.msecsTo(current);
+        int timeDiff = startTime().msecsTo(current);
         alpha = timeDiff/(float)_duration;
         if (timeDiff > _duration) {
-            _running = false;
+            stop();
             alpha = 1.0;
         }
     }
     else {
-        _running = false;
+        stop();
     }
     drawBlendedImage(painter, option->rect, alpha);
 }
@@ -282,7 +288,7 @@ void QWindowsVistaTransition::paint(QPainter *painter, const QStyleOption *optio
 /*! \internal
   Paints a pulse. The result will be a mix between the primary and
   secondary pulse images depending on the time difference between
-  _startTime and current time.
+  startTime and current time.
 */
 void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
 {
@@ -290,15 +296,15 @@ void QWindowsVistaPulse::paint(QPainter *painter, const QStyleOption *option)
     if (_duration > 0) {
         QTime current = QTime::currentTime();
 
-        if (_startTime > current)
-            _startTime = current;
+        if (startTime() > current)
+            setStartTime(current);
 
-        int timeDiff = _startTime.msecsTo(current) % _duration*2;
+        int timeDiff = startTime().msecsTo(current) % _duration*2;
         if (timeDiff > _duration)
             timeDiff = _duration*2 - timeDiff;
         alpha = timeDiff/(float)_duration;
     } else {
-        _running = false;
+        stop();
     }
     drawBlendedImage(painter, option->rect, alpha);
 }
@@ -341,6 +347,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
 
     int state = option->state;
     if (!QWindowsVistaStylePrivate::useVista()) {
+        foreach (const QObject *target, d->animationTargets())
+            d->stopAnimation(target);
         QWindowsStyle::drawPrimitive(element, option, painter, widget);
         return;
     }
@@ -399,9 +407,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
                 startImage.fill(0);
                 QPainter startPainter(&startImage);
 
-                QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
-                QWindowsVistaTransition *t = new QWindowsVistaTransition;
-                t->setWidget(w);
+                QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
+                QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
 
                 // If we have a running animation on the widget already, we will use that to paint the initial
                 // state of the new transition, this ensures a smooth transition from a current animation such as a
@@ -539,7 +546,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
     case PE_IndicatorCheckBox:
     case PE_IndicatorRadioButton:
         {
-            if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
+            if (QWindowsVistaAnimation *a = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget)) ){
                 a->paint(painter, option);
             } else {
                 QWindowsXPStyle::drawPrimitive(element, option, painter, widget);
@@ -655,7 +662,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
         break;
 
     case PE_FrameLineEdit:
-        if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
+        if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget))) {
             anim->paint(painter, option);
         } else {
             QPainter *p = painter;
@@ -903,6 +910,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
 
     if (!QWindowsVistaStylePrivate::useVista()) {
+        foreach (const QObject *target, d->animationTargets())
+            d->stopAnimation(target);
         QWindowsStyle::drawControl(element, option, painter, widget);
         return;
     }
@@ -950,14 +959,13 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
                 if (doTransition) {
                     QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
                     QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
-                    QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
+                    QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
 
                     QStyleOptionButton opt = *button;
                     opt.state = (QStyle::State)oldState;
 
                     startImage.fill(0);
-                    QWindowsVistaTransition *t = new QWindowsVistaTransition;
-                    t->setWidget(w);
+                    QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
                     QPainter startPainter(&startImage);
 
                     if (!anim) {
@@ -992,7 +1000,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
     case CE_PushButtonBevel:
         if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option))
         {
-            QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
+            QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
             if (anim && (btn->state & State_Enabled)) {
                 anim->paint(painter, option);
             } else {
@@ -1026,8 +1034,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
                             QImage alternateImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
                             alternateImage.fill(0);
 
-                            QWindowsVistaPulse *pulse = new QWindowsVistaPulse;
-                            pulse->setWidget(const_cast<QWidget*>(widget));
+                            QWindowsVistaPulse *pulse = new QWindowsVistaPulse(const_cast<QWidget*>(widget));
 
                             QPainter startPainter(&startImage);
                             stateId = PBS_DEFAULTED;
@@ -1095,16 +1102,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
             }
 
             if (const QProgressBar *progressbar = qobject_cast<const QProgressBar *>(widget)) {
-                if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled())) {
-                    if (!d->widgetAnimation(progressbar)) {
-                        QWindowsVistaAnimation *a = new QWindowsVistaAnimation;
-                        a->setWidget(const_cast<QWidget*>(widget));
-                        a->setStartTime(QTime::currentTime());
-                        d->startAnimation(a);
-                    }
-                } else {
+                if (isIndeterminate || (progressbar->value() > 0 && (progressbar->value() < progressbar->maximum()) && d->transitionsEnabled()))
+                    d->startProgressAnimation(0, const_cast<QProgressBar *>(progressbar));
+                else
                     d->stopAnimation(progressbar);
-                }
             }
 
             XPThemeData theme(widget, painter,
@@ -1115,7 +1116,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
             QTime current = QTime::currentTime();
 
             if (isIndeterminate) {
-                if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
+                if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(widget))) {
                     int glowSize = 120;
                     int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
                     int animOffset = a->startTime().msecsTo(current) / 4;
@@ -1185,7 +1186,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
                 }
                 d->drawBackground(theme);
 
-                if (QWindowsVistaAnimation *a = d->widgetAnimation(widget)) {
+                if (QProgressStyleAnimation *a = qobject_cast<QProgressStyleAnimation *>(d->animation(widget))) {
                     int glowSize = 140;
                     int animationWidth = glowSize * 2 + (vertical ? theme.rect.height() : theme.rect.width());
                     int animOffset = a->startTime().msecsTo(current) / 4;
@@ -1574,6 +1575,8 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
 {
     QWindowsVistaStylePrivate *d = const_cast<QWindowsVistaStylePrivate*>(d_func());
     if (!QWindowsVistaStylePrivate::useVista()) {
+        foreach (const QObject *target, d->animationTargets())
+            d->stopAnimation(target);
         QWindowsStyle::drawComplexControl(control, option, painter, widget);
         return;
     }
@@ -1636,9 +1639,8 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
             if (doTransition) {
                 QImage startImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
                 QImage endImage(option->rect.size(), QImage::Format_ARGB32_Premultiplied);
-                QWindowsVistaAnimation *anim = d->widgetAnimation(widget);
-                QWindowsVistaTransition *t = new QWindowsVistaTransition;
-                t->setWidget(w);
+                QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget));
+                QWindowsVistaTransition *t = new QWindowsVistaTransition(w);
                 if (!anim) {
                     if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox*>(option)) {
                         //Combo boxes are special cased to avoid cleartype issues
@@ -1692,7 +1694,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
                     t->setDuration(500);
             }
 
-            if (QWindowsVistaAnimation *anim = d->widgetAnimation(widget)) {
+            if (QWindowsVistaAnimation *anim = qobject_cast<QWindowsVistaAnimation *>(d->animation(widget))) {
                 anim->paint(painter, option);
                 return;
             }
@@ -2338,29 +2340,6 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
 /*!
  \internal
  */
-bool QWindowsVistaStyle::event(QEvent *e)
-{
-    Q_D(QWindowsVistaStyle);
-    switch (e->type()) {
-    case QEvent::Timer:
-        {
-            QTimerEvent *timerEvent = (QTimerEvent *)e;
-            if (d->animationTimer.timerId() == timerEvent->timerId()) {
-                d->timerEvent();
-                e->accept();
-                return true;
-            }
-        }
-        break;
-    default:
-        break;
-    }
-    return QWindowsXPStyle::event(e);
-}
-
-/*!
- \internal
- */
 QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option,
                                                           const QPoint &pos, const QWidget *widget) const
 {
@@ -2549,53 +2528,9 @@ QWindowsVistaStylePrivate::QWindowsVistaStylePrivate() :
 
 QWindowsVistaStylePrivate::~QWindowsVistaStylePrivate()
 {
-    qDeleteAll(animations);
     cleanupTreeViewTheming();
 }
 
-void QWindowsVistaStylePrivate::timerEvent()
-{
-    for (int i = animations.size() - 1 ; i >= 0 ; --i) {
-
-        if (animations[i]->widget())
-            animations[i]->widget()->update();
-
-        if (!animations[i]->widget() ||
-            !animations[i]->widget()->isVisible() ||
-            animations[i]->widget()->window()->isMinimized() ||
-            !animations[i]->running() ||
-            !QWindowsVistaStylePrivate::useVista())
-        {
-            QWindowsVistaAnimation *a = animations.takeAt(i);
-            delete a;
-        }
-    }
-    if (animations.size() == 0 && animationTimer.isActive()) {
-        animationTimer.stop();
-    }
-}
-
-void QWindowsVistaStylePrivate::stopAnimation(const QWidget *w)
-{
-    for (int i = animations.size() - 1 ; i >= 0 ; --i) {
-        if (animations[i]->widget() == w) {
-            QWindowsVistaAnimation *a = animations.takeAt(i);
-            delete a;
-            break;
-        }
-    }
-}
-
-void QWindowsVistaStylePrivate::startAnimation(QWindowsVistaAnimation *t)
-{
-    Q_Q(QWindowsVistaStyle);
-    stopAnimation(t->widget());
-    animations.append(t);
-    if (animations.size() > 0 && !animationTimer.isActive()) {
-        animationTimer.start(45, q);
-    }
-}
-
 bool QWindowsVistaStylePrivate::transitionsEnabled() const
 {
     BOOL animEnabled = false;
@@ -2607,19 +2542,6 @@ bool QWindowsVistaStylePrivate::transitionsEnabled() const
     return false;
 }
 
-
-QWindowsVistaAnimation * QWindowsVistaStylePrivate::widgetAnimation(const QWidget *widget) const
-{
-    if (!widget)
-        return 0;
-    foreach (QWindowsVistaAnimation *a, animations) {
-        if (a->widget() == widget)
-            return a;
-    }
-    return 0;
-}
-
-
 /*! \internal
     Returns true if all the necessary theme engine symbols were
     resolved.
index 5a030af..0b17881 100644 (file)
@@ -88,7 +88,6 @@ public:
     void polish(QPalette &pal);
     void polish(QApplication *app);
     void unpolish(QApplication *app);
-    bool event(QEvent *event);
     QPalette standardPalette() const;
 
 private:
index faf3777..1d427fe 100644 (file)
@@ -57,6 +57,7 @@
 
 #if !defined(QT_NO_STYLE_WINDOWSVISTA)
 #include <private/qwindowsxpstyle_p.h>
+#include <private/qstyleanimation_p.h>
 #include <private/qpaintengine_raster_p.h>
 #include <qlibrary.h>
 #include <qpaintengine.h>
@@ -83,7 +84,6 @@
 #include <qdialogbuttonbox.h>
 #include <qinputdialog.h>
 #include <qtableview.h>
-#include <qbasictimer.h>
 #include <qdatetime.h>
 #include <qcommandlinkbutton.h>
 
@@ -135,57 +135,50 @@ QT_BEGIN_NAMESPACE
 #define TDLG_SECONDARYPANEL         8
 #endif
 
-class QWindowsVistaAnimation
+class QWindowsVistaAnimation : public QStyleAnimation
 {
-public :
-    QWindowsVistaAnimation() : _running(true) { }
+    Q_OBJECT
+public:
+    QWindowsVistaAnimation(QObject *target) : QStyleAnimation(target), _duration(-1) { }
     virtual ~QWindowsVistaAnimation() { }
-    QWidget * widget() const { return _widget; }
-    bool running() const { return _running; }
-    const QTime &startTime() const { return _startTime; }
-    void setRunning(bool val) { _running = val; }
-    void setWidget(QWidget *widget) { _widget = widget; }
-    void setStartTime(const QTime &startTime) { _startTime = startTime; }
     virtual void paint(QPainter *painter, const QStyleOption *option);
+    virtual bool isUpdateNeeded() const;
+    virtual int duration() const { return _duration; }
+    //set time in ms to complete a state transition / pulse cycle
+    void setDuration(int duration) { _duration = duration; }
 
 protected:
     void drawBlendedImage(QPainter *painter, QRect rect, float value);
-    QTime _startTime;
-    QPointer<QWidget> _widget;
     QImage _primaryImage;
     QImage _secondaryImage;
     QImage _tempImage;
-    bool _running;
+    int _duration;
 };
 
 
 // Handles state transition animations
 class QWindowsVistaTransition : public QWindowsVistaAnimation
 {
-public :
-    QWindowsVistaTransition() : QWindowsVistaAnimation() {}
+    Q_OBJECT
+public:
+    QWindowsVistaTransition(QObject *target) : QWindowsVistaAnimation(target) {}
     virtual ~QWindowsVistaTransition() { }
-    void setDuration(int duration) { _duration = duration; }
     void setStartImage(const QImage &image) { _primaryImage = image; }
     void setEndImage(const QImage &image) { _secondaryImage = image; }
     virtual void paint(QPainter *painter, const QStyleOption *option);
-    int duration() const { return _duration; }
-    int _duration; //set time in ms to complete a state transition
 };
 
 
 // Handles pulse animations (default buttons)
 class QWindowsVistaPulse: public QWindowsVistaAnimation
 {
-public :
-    QWindowsVistaPulse() : QWindowsVistaAnimation() {}
+    Q_OBJECT
+public:
+    QWindowsVistaPulse(QObject *target) : QWindowsVistaAnimation(target) {}
     virtual ~QWindowsVistaPulse() { }
-    void setDuration(int duration) { _duration = duration; }
     void setPrimaryImage(const QImage &image) { _primaryImage = image; }
     void setAlternateImage(const QImage &image) { _secondaryImage = image; }
     virtual void paint(QPainter *painter, const QStyleOption *option);
-    int duration() const { return _duration; }
-    int _duration; //time in ms to complete a pulse cycle
 };
 
 
@@ -198,18 +191,12 @@ public:
     ~QWindowsVistaStylePrivate();
     static bool resolveSymbols();
     static inline bool useVista();
-    void startAnimation(QWindowsVistaAnimation *);
-    void stopAnimation(const QWidget *);
-    QWindowsVistaAnimation* widgetAnimation(const QWidget *) const;
-    void timerEvent();
     bool transitionsEnabled() const;
 
 private:
     bool initTreeViewTheming();
     void cleanupTreeViewTheming();
 
-    QList <QWindowsVistaAnimation*> animations;
-    QBasicTimer animationTimer;
     HWND m_treeViewHelper;
 };
 
index 6ba9875..d04b3d5 100644 (file)
@@ -3,6 +3,7 @@
 HEADERS += \
         styles/qdrawutil.h \
         styles/qstyle.h \
+        styles/qstyleanimation_p.h \
         styles/qstylefactory.h \
         styles/qstyleoption.h \
         styles/qstyleplugin.h \
@@ -11,12 +12,14 @@ HEADERS += \
         styles/qstylehelper_p.h \
         styles/qproxystyle.h \
         styles/qproxystyle_p.h \
+        styles/qcommonstyle_p.h \
         styles/qstylepainter.h \
         styles/qstylesheetstyle_p.h
 
 SOURCES += \
         styles/qdrawutil.cpp \
         styles/qstyle.cpp \
+        styles/qstyleanimation.cpp \
         styles/qstylefactory.cpp \
         styles/qstyleoption.cpp \
         styles/qstyleplugin.cpp \