From 0b98562c222f27e758cdc98aaf0a57150451e750 Mon Sep 17 00:00:00 2001 From: nowrep Date: Wed, 11 Apr 2012 16:38:46 +0200 Subject: [PATCH] Using QTimeLine for animations in Tab preview. - QPropertyAnimation is now never used in our code, it should fix issue when tab moving animation break without reason --- src/lib/webview/tabpreview.cpp | 186 ++++++++++++++++++--------------- src/lib/webview/tabpreview.h | 26 +++-- 2 files changed, 121 insertions(+), 91 deletions(-) diff --git a/src/lib/webview/tabpreview.cpp b/src/lib/webview/tabpreview.cpp index 02689eb68..0f0db7e68 100644 --- a/src/lib/webview/tabpreview.cpp +++ b/src/lib/webview/tabpreview.cpp @@ -21,29 +21,31 @@ #include "webtab.h" #include "tabbedwebview.h" -#include #include #include #include #include #include -#include -#include TabPreview::TabPreview(QupZilla* mainClass, QWidget* parent) : QFrame(parent) , p_QupZilla(mainClass) - , m_pixmap(new QLabel) - , m_title(new QLabel) , m_previewIndex(-1) , m_animationsEnabled(true) + , m_stepX(0) + , m_stepY(0) + , m_stepWidth(0) + , m_stepHeight(0) { - m_pixmap->setAlignment(Qt::AlignHCenter); + m_pixmapLabel = new QLabel(this); + m_pixmapLabel->setAlignment(Qt::AlignHCenter); + + m_title = new QLabel(this); m_title->setAlignment(Qt::AlignHCenter); m_title->setWordWrap(true); QVBoxLayout* layout = new QVBoxLayout(this); - layout->addWidget(m_pixmap); + layout->addWidget(m_pixmapLabel); layout->addWidget(m_title); layout->setMargin(0); layout->setAlignment(Qt::AlignCenter); @@ -56,12 +58,14 @@ TabPreview::TabPreview(QupZilla* mainClass, QWidget* parent) setMaximumWidth(250); setMaximumHeight(170); - m_animation = new QPropertyAnimation(this, "geometry", this); - m_opacityEffect = new QGraphicsOpacityEffect(this); - m_opacityAnimation = new QPropertyAnimation(m_opacityEffect, "opacity", this); + setGraphicsEffect(&m_opacityEffect); + m_opacityEffect.setOpacity(0.0); + connect(&m_opacityTimeLine, SIGNAL(frameChanged(int)), this, SLOT(setOpacity(int))); - setGraphicsEffect(m_opacityEffect); - m_opacityEffect->setOpacity(0.0); + m_animation.setDuration(400); + m_animation.setFrameRange(0, 100); + m_animation.setUpdateInterval(20); // 50 fps + connect(&m_animation, SIGNAL(frameChanged(int)), this, SLOT(setAnimationFrame(int))); } int TabPreview::previewIndex() @@ -78,12 +82,12 @@ void TabPreview::setWebTab(WebTab* webTab, bool noPixmap) { if (webTab->isRestored() && !webTab->isLoading() && !noPixmap) { m_title->setText(webTab->title()); - m_pixmap->setPixmap(webTab->renderTabPreview()); - m_pixmap->show(); + m_pixmapLabel->setPixmap(webTab->renderTabPreview()); + m_pixmapLabel->show(); } else { m_title->setText(webTab->title()); - m_pixmap->hide(); + m_pixmapLabel->hide(); } } @@ -94,17 +98,17 @@ void TabPreview::setAnimationsEnabled(bool enabled) void TabPreview::hideAnimated() { - if (m_opacityAnimation->state() == QPropertyAnimation::Running) { - m_opacityAnimation->stop(); + if (m_opacityTimeLine.state() == QTimeLine::Running) { + m_opacityTimeLine.stop(); } if (m_animationsEnabled) { - m_opacityAnimation->setDuration(400); - m_opacityAnimation->setStartValue(m_opacityEffect->opacity()); - m_opacityAnimation->setEndValue(0.0); - m_opacityAnimation->start(); + m_opacityTimeLine.setDuration(400); + m_opacityTimeLine.setStartFrame(m_opacityEffect.opacity() * 100); + m_opacityTimeLine.setEndFrame(0); + m_opacityTimeLine.start(); - connect(m_opacityAnimation, SIGNAL(finished()), this, SLOT(hide())); + connect(&m_opacityTimeLine, SIGNAL(finished()), this, SLOT(hide())); } else { QFrame::hide(); @@ -114,7 +118,7 @@ void TabPreview::hideAnimated() void TabPreview::hide() { m_previewIndex = -1; - disconnect(m_opacityAnimation, SIGNAL(finished()), this, SLOT(hide())); + disconnect(&m_opacityTimeLine, SIGNAL(finished()), this, SLOT(hide())); QFrame::hide(); } @@ -128,17 +132,81 @@ void TabPreview::show() QFrame::show(); } +void TabPreview::showOnRect(const QRect &r) +{ + if (m_animation.state() == QTimeLine::Running) { + m_animation.stop(); + } + + m_startGeometry = geometry(); + bool wasVisible = isVisible(); + QRect finishingGeometry; + + resize(QSize(250, 170)); + QFrame::show(); + + if (m_pixmapLabel->isVisible()) { + m_title->setWordWrap(false); + m_title->setText(m_title->fontMetrics().elidedText(m_title->text(), Qt::ElideRight, 240)); + + QSize previewSize(250, 170); + finishingGeometry = QRect(calculatePosition(r, previewSize), previewSize); + } + else { + m_title->setWordWrap(true); + + QSize previewSize = sizeHint(); + previewSize.setWidth(qMin(previewSize.width() + 2 * 5, 240)); + previewSize.setHeight(qMin(previewSize.height() + 2 * 5, 130)); + + finishingGeometry = QRect(calculatePosition(r, previewSize), previewSize); + } + + if (!m_animationsEnabled) { + m_opacityEffect.setOpacity(1.0); + QFrame::setGeometry(finishingGeometry); + return; + } + else { + showAnimated(); + } + + if (!wasVisible) { + m_startGeometry = finishingGeometry; + } + + calculateSteps(m_startGeometry, finishingGeometry); + m_animation.start(); +} + +void TabPreview::setOpacity(int opacity) +{ + m_opacityEffect.setOpacity(opacity / 100.0); +} + +void TabPreview::setAnimationFrame(int frame) +{ + QRect g; + g.setX(m_startGeometry.x() + frame * m_stepX); + g.setY(m_startGeometry.y() + frame * m_stepY); + g.setWidth(m_startGeometry.width() + frame * m_stepWidth); + g.setHeight(m_startGeometry.height() + frame * m_stepHeight); + + setGeometry(g); +} + void TabPreview::showAnimated() { - disconnect(m_opacityAnimation, SIGNAL(finished()), this, SLOT(hide())); + disconnect(&m_opacityTimeLine, SIGNAL(finished()), this, SLOT(hide())); - if (m_opacityAnimation->state() == QPropertyAnimation::Running) { - m_opacityAnimation->stop(); + if (m_opacityTimeLine.state() == QTimeLine::Running) { + m_opacityTimeLine.stop(); } - m_opacityAnimation->setDuration(400); - m_opacityAnimation->setStartValue(m_opacityEffect->opacity()); - m_opacityAnimation->setEndValue(1.0); - m_opacityAnimation->start(); + + m_opacityTimeLine.setDuration(400); + m_opacityTimeLine.setStartFrame(m_opacityEffect.opacity() * 100); + m_opacityTimeLine.setEndFrame(100); + m_opacityTimeLine.start(); } void TabPreview::paintEvent(QPaintEvent* pe) @@ -151,11 +219,12 @@ void TabPreview::paintEvent(QPaintEvent* pe) painter.drawPrimitive(QStyle::PE_PanelTipLabel, opt); } -void TabPreview::setFinishingGeometry(const QRect &oldGeometry, const QRect &newGeometry) +void TabPreview::calculateSteps(const QRect &oldGeometry, const QRect &newGeometry) { - m_animation->setDuration(400); - m_animation->setStartValue(oldGeometry); - m_animation->setEndValue(newGeometry); + m_stepX = (newGeometry.x() - oldGeometry.x()) / 100.0; + m_stepY = (newGeometry.y() - oldGeometry.y()) / 100.0; + m_stepWidth = (newGeometry.width() - oldGeometry.width()) / 100.0; + m_stepHeight = (newGeometry.height() - oldGeometry.height()) / 100.0; } QPoint TabPreview::calculatePosition(const QRect &tabRect, const QSize &previewSize) @@ -184,52 +253,3 @@ QPoint TabPreview::calculatePosition(const QRect &tabRect, const QSize &previewS return p; } - -void TabPreview::showOnRect(const QRect &r) -{ - if (m_animation->state() == QPropertyAnimation::Running) { - m_animation->stop(); - } - - QRect oldGeometry = geometry(); - bool wasVisible = isVisible(); - - resize(QSize(250, 170)); - QFrame::show(); - - QRect finishingGeometry; - - if (m_pixmap->isVisible()) { - m_title->setWordWrap(false); - m_title->setText(m_title->fontMetrics().elidedText(m_title->text(), Qt::ElideRight, 240)); - - QSize previewSize(250, 170); - finishingGeometry = QRect(calculatePosition(r, previewSize), previewSize); - } - else { - m_title->setWordWrap(true); - - QSize previewSize = sizeHint(); - previewSize.setWidth(qMin(previewSize.width() + 2 * 5, 240)); - previewSize.setHeight(qMin(previewSize.height() + 2 * 5, 130)); - - finishingGeometry = QRect(calculatePosition(r, previewSize), previewSize); - } - - if (!m_animationsEnabled) { - m_opacityEffect->setOpacity(1.0); - QFrame::setGeometry(finishingGeometry); - return; - } - else { - showAnimated(); - } - - if (!wasVisible) { - oldGeometry = finishingGeometry; - } - - setFinishingGeometry(oldGeometry, finishingGeometry); - m_animation->start(); - -} diff --git a/src/lib/webview/tabpreview.h b/src/lib/webview/tabpreview.h index 7ae2d0f0b..5a5797d1d 100644 --- a/src/lib/webview/tabpreview.h +++ b/src/lib/webview/tabpreview.h @@ -20,13 +20,12 @@ #define TABPREVIEW_H #include +#include +#include class QupZilla; class WebTab; class QLabel; -class QPropertyAnimation; -class QParallelAnimationGroup; -class QGraphicsOpacityEffect; class TabPreview : public QFrame { @@ -48,23 +47,34 @@ public slots: void show(); +private slots: + void setOpacity(int opacity); + void setAnimationFrame(int frame); + protected: void paintEvent(QPaintEvent* pe); private: void showAnimated(); - void setFinishingGeometry(const QRect &oldGeometry, const QRect &newGeometry); + void calculateSteps(const QRect &oldGeometry, const QRect &newGeometry); QPoint calculatePosition(const QRect &tabRect, const QSize &previewSize); QupZilla* p_QupZilla; - QLabel* m_pixmap; + QLabel* m_pixmapLabel; QLabel* m_title; int m_previewIndex; bool m_animationsEnabled; - QPropertyAnimation* m_animation; - QPropertyAnimation* m_opacityAnimation; - QGraphicsOpacityEffect* m_opacityEffect; + + QTimeLine m_opacityTimeLine; + QGraphicsOpacityEffect m_opacityEffect; + + QTimeLine m_animation; + QRect m_startGeometry; + qreal m_stepX; + qreal m_stepY; + qreal m_stepWidth; + qreal m_stepHeight; }; #endif // TABPREVIEW_H