make the webview widget use scrollwidget for flicking

still some issues to fix, but most of the behaviour is ported.
patch based on zack's work
CCMAIL:zack@kde.org

svn path=/trunk/KDE/kdelibs/; revision=1108058
This commit is contained in:
Marco Martin 2010-03-27 17:44:16 +00:00
parent 803bd9b463
commit 2f8e70b7ab
4 changed files with 143 additions and 29 deletions

View File

@ -165,5 +165,28 @@ void AnimableGraphicsWebView::wheelEvent(QGraphicsSceneWheelEvent *event)
event->setAccepted(!m_dragToScroll); event->setAccepted(!m_dragToScroll);
} }
qreal AnimableGraphicsWebView::scrollPositionX() const
{
return page()->mainFrame()->scrollPosition().x();
}
void AnimableGraphicsWebView::setScrollPositionX(qreal position)
{
QPointF pt(position, scrollPositionY());
setScrollPosition(pt);
}
qreal AnimableGraphicsWebView::scrollPositionY() const
{
return page()->mainFrame()->scrollPosition().y();
}
void AnimableGraphicsWebView::setScrollPositionY(qreal position)
{
QPointF pt(scrollPositionX(), position);
setScrollPosition(pt);
}
#include "animablegraphicswebview_p.moc" #include "animablegraphicswebview_p.moc"

View File

@ -38,6 +38,8 @@ class AnimableGraphicsWebView : public KGraphicsWebView
Q_PROPERTY(qreal zoomFactor READ zoom WRITE setZoom) Q_PROPERTY(qreal zoomFactor READ zoom WRITE setZoom)
Q_PROPERTY(QPointF scrollPosition READ scrollPosition WRITE setScrollPosition) Q_PROPERTY(QPointF scrollPosition READ scrollPosition WRITE setScrollPosition)
Q_PROPERTY(qreal scrollPositionX READ scrollPositionX WRITE setScrollPositionX)
Q_PROPERTY(qreal scrollPositionY READ scrollPositionY WRITE setScrollPositionY)
Q_PROPERTY(QSizeF contentsSize READ contentsSize) Q_PROPERTY(QSizeF contentsSize READ contentsSize)
Q_PROPERTY(QRectF viewportGeometry READ viewportGeometry) Q_PROPERTY(QRectF viewportGeometry READ viewportGeometry)
@ -46,6 +48,10 @@ public:
QPointF scrollPosition() const; QPointF scrollPosition() const;
void setScrollPosition(const QPointF &position); void setScrollPosition(const QPointF &position);
qreal scrollPositionX() const;
void setScrollPositionX(qreal position);
qreal scrollPositionY() const;
void setScrollPositionY(qreal position);
QSizeF contentsSize() const; QSizeF contentsSize() const;
QRectF viewportGeometry() const; QRectF viewportGeometry() const;
void setDragToScroll(bool enable); void setDragToScroll(bool enable);

View File

@ -140,6 +140,11 @@ public:
hasOvershoot = true; hasOvershoot = true;
alignment = Qt::AlignLeft | Qt::AlignTop; alignment = Qt::AlignLeft | Qt::AlignTop;
hasContentsProperty = false;
hasOffsetProperty = false;
hasXProperty = false;
hasYProperty = false;
} }
void adjustScrollbars() void adjustScrollbars()
@ -298,7 +303,7 @@ public:
void animateMoveTo(const QPointF &pos) void animateMoveTo(const QPointF &pos)
{ {
qreal duration = 800; qreal duration = 800;
QPointF start = widget.data()->pos(); QPointF start = q->scrollPosition();
QSizeF threshold = q->viewportGeometry().size(); QSizeF threshold = q->viewportGeometry().size();
QPointF diff = pos - start; QPointF diff = pos - start;
@ -345,6 +350,7 @@ public:
qreal duration = qAbs(v / deceleration); qreal duration = qAbs(v / deceleration);
qreal diffY = v * duration + (0.5 * deceleration * duration * duration); qreal diffY = v * duration + (0.5 * deceleration * duration * duration);
qreal startY = val; qreal startY = val;
qreal endY = startY + diffY; qreal endY = startY + diffY;
if (velocity > 0) { if (velocity > 0) {
@ -356,6 +362,12 @@ public:
} }
duration = qAbs((endY-startY)/ (-v/2)); duration = qAbs((endY-startY)/ (-v/2));
if (hasYProperty) {
startY = -startY;
endY = -endY;
}
#if DEBUG #if DEBUG
qDebug()<<"XXX velocity = "<<v <<", target = "<< target qDebug()<<"XXX velocity = "<<v <<", target = "<< target
<<", maxDist = "<<maxDistance; <<", maxDist = "<<maxDistance;
@ -380,12 +392,12 @@ public:
} }
void flickX(qreal velocity) void flickX(qreal velocity)
{ {
flick(flickAnimationX, velocity, widget.data()->x(), minXExtent(), maxXExtent(), flick(flickAnimationX, velocity, widgetX(), minXExtent(), maxXExtent(),
q->viewportGeometry().width()); q->viewportGeometry().width());
} }
void flickY(qreal velocity) void flickY(qreal velocity)
{ {
flick(flickAnimationY, velocity, widget.data()->y(),minYExtent(), maxYExtent(), flick(flickAnimationY, velocity, widgetY(),minYExtent(), maxYExtent(),
q->viewportGeometry().height()); q->viewportGeometry().height());
} }
void fixup(QAnimationGroup *group, void fixup(QAnimationGroup *group,
@ -427,12 +439,12 @@ public:
void fixupX() void fixupX()
{ {
fixup(fixupAnimation.groupX, fixupAnimation.startX, fixupAnimation.endX, fixup(fixupAnimation.groupX, fixupAnimation.startX, fixupAnimation.endX,
widget.data()->x(), minXExtent(), maxXExtent()); widgetX(), minXExtent(), maxXExtent());
} }
void fixupY() void fixupY()
{ {
fixup(fixupAnimation.groupY, fixupAnimation.startY, fixupAnimation.endY, fixup(fixupAnimation.groupY, fixupAnimation.startY, fixupAnimation.endY,
widget.data()->y(), minYExtent(), maxYExtent()); widgetY(), minYExtent(), maxYExtent());
} }
void makeRectVisible() void makeRectVisible()
@ -466,7 +478,7 @@ public:
delta.setX(viewRect.right() - mappedRect.right()); delta.setX(viewRect.right() - mappedRect.right());
} }
animateMoveTo(widget.data()->pos() + delta); animateMoveTo(q->scrollPosition() - delta);
} }
void makeItemVisible(QGraphicsItem *itemToBeVisible) void makeItemVisible(QGraphicsItem *itemToBeVisible)
@ -496,6 +508,35 @@ public:
fixupAnimation.groupY->stop(); fixupAnimation.groupY->stop();
} }
void setWidgetX(qreal x)
{
if (hasXProperty) {
widget.data()->setProperty("scrollPositionX", -x);
} else
widget.data()->setX(x);
}
void setWidgetY(qreal y)
{
if (hasYProperty) {
widget.data()->setProperty("scrollPositionY", -y);
} else
widget.data()->setY(y);
}
qreal widgetX() const
{
if (hasXProperty) {
return -widget.data()->property("scrollPositionX").toReal();
} else
return widget.data()->x();
}
qreal widgetY() const
{
if (hasYProperty) {
return -widget.data()->property("scrollPositionY").toReal();
} else
return widget.data()->y();
}
void handleMousePressEvent(QGraphicsSceneMouseEvent *event) void handleMousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
lastPos = QPoint(); lastPos = QPoint();
@ -533,7 +574,7 @@ public:
rejectY = true; rejectY = true;
} }
if (!rejectY && stealEvent) { if (!rejectY && stealEvent) {
widget.data()->setY(qRound(newY)); setWidgetY(qRound(newY));
moved = true; moved = true;
} }
if (qAbs(dy) > QApplication::startDragDistance()) if (qAbs(dy) > QApplication::startDragDistance())
@ -560,7 +601,7 @@ public:
rejectX = true; rejectX = true;
} }
if (!rejectX && stealEvent) { if (!rejectX && stealEvent) {
widget.data()->setX(qRound(newX)); setWidgetX(qRound(newX));
moved = true; moved = true;
} }
@ -642,7 +683,7 @@ public:
if (!widget.data()) if (!widget.data())
return; return;
QPointF start = widget.data()->pos(); QPointF start = q->scrollPosition();
QPointF end = start; QPointF end = start;
//At some point we should switch to //At some point we should switch to
@ -653,7 +694,7 @@ public:
// is that at this point we don't have any clue what a "line" is and if // is that at this point we don't have any clue what a "line" is and if
// we make it a pixel then scrolling by 3 (default) pixels will be // we make it a pixel then scrolling by 3 (default) pixels will be
// very painful // very painful
qreal step = event->delta()/3; qreal step = -event->delta()/3;
//ifthe widget can scroll in a single axis and the wheel is the other one, scroll the other one //ifthe widget can scroll in a single axis and the wheel is the other one, scroll the other one
Qt::Orientation orientation = event->orientation(); Qt::Orientation orientation = event->orientation();
@ -754,10 +795,18 @@ public:
void createFlickAnimations() void createFlickAnimations()
{ {
if (widget.data()) { if (widget.data()) {
QString xProp = QString::fromLatin1("x");
QString yProp = QString::fromLatin1("y");
if (hasXProperty)
xProp = QString::fromLatin1("scrollPositionX");
if (hasYProperty)
yProp = QString::fromLatin1("scrollPositionY");
flickAnimationX = new QPropertyAnimation(widget.data(), flickAnimationX = new QPropertyAnimation(widget.data(),
"x", widget.data()); xProp.toLatin1(), widget.data());
flickAnimationY = new QPropertyAnimation(widget.data(), flickAnimationY = new QPropertyAnimation(widget.data(),
"y", widget.data()); yProp.toLatin1(), widget.data());
QObject::connect(flickAnimationX, SIGNAL(finished()), QObject::connect(flickAnimationX, SIGNAL(finished()),
q, SLOT(fixupX())); q, SLOT(fixupX()));
QObject::connect(flickAnimationY, SIGNAL(finished()), QObject::connect(flickAnimationY, SIGNAL(finished()),
@ -781,13 +830,13 @@ public:
fixupAnimation.groupX = new QSequentialAnimationGroup(widget.data()); fixupAnimation.groupX = new QSequentialAnimationGroup(widget.data());
fixupAnimation.groupY = new QSequentialAnimationGroup(widget.data()); fixupAnimation.groupY = new QSequentialAnimationGroup(widget.data());
fixupAnimation.startX = new QPropertyAnimation(widget.data(), fixupAnimation.startX = new QPropertyAnimation(widget.data(),
"x", widget.data()); xProp.toLatin1(), widget.data());
fixupAnimation.startY = new QPropertyAnimation(widget.data(), fixupAnimation.startY = new QPropertyAnimation(widget.data(),
"y", widget.data()); yProp.toLatin1(), widget.data());
fixupAnimation.endX = new QPropertyAnimation(widget.data(), fixupAnimation.endX = new QPropertyAnimation(widget.data(),
"x", widget.data()); xProp.toLatin1(), widget.data());
fixupAnimation.endY = new QPropertyAnimation(widget.data(), fixupAnimation.endY = new QPropertyAnimation(widget.data(),
"y", widget.data()); yProp.toLatin1(), widget.data());
fixupAnimation.groupX->addAnimation( fixupAnimation.groupX->addAnimation(
fixupAnimation.startX); fixupAnimation.startX);
fixupAnimation.groupY->addAnimation( fixupAnimation.groupY->addAnimation(
@ -813,9 +862,9 @@ public:
q, SIGNAL(scrollStateChanged(QAbstractAnimation::State, q, SIGNAL(scrollStateChanged(QAbstractAnimation::State,
QAbstractAnimation::State))); QAbstractAnimation::State)));
directMoveAnimation = new QPropertyAnimation(widget.data(), directMoveAnimation = new QPropertyAnimation(q,
"pos", "scrollPosition",
widget.data()); q);
QObject::connect(directMoveAnimation, SIGNAL(finished()), QObject::connect(directMoveAnimation, SIGNAL(finished()),
q, SLOT(fixupX())); q, SLOT(fixupX()));
QObject::connect(directMoveAnimation, SIGNAL(finished()), QObject::connect(directMoveAnimation, SIGNAL(finished()),
@ -900,6 +949,11 @@ public:
bool hasOvershoot; bool hasOvershoot;
Qt::Alignment alignment; Qt::Alignment alignment;
bool hasContentsProperty;
bool hasOffsetProperty;
bool hasXProperty;
bool hasYProperty;
}; };
@ -931,9 +985,14 @@ void ScrollWidget::setWidget(QGraphicsWidget *widget)
} }
d->widget = widget; d->widget = widget;
d->createFlickAnimations();
//it's not good it's setting a size policy here, but it's done to be retrocompatible with older applications //it's not good it's setting a size policy here, but it's done to be retrocompatible with older applications
if (widget) { if (widget) {
d->hasContentsProperty = widget->property("contentsSize").isValid();
d->hasOffsetProperty = widget->property("scrollPosition").isValid();
d->hasXProperty = widget->property("scrollPositionX").isValid();
d->hasYProperty = widget->property("scrollPositionY").isValid();
d->createFlickAnimations();
connect(widget, SIGNAL(xChanged()), this, SLOT(setScrollX())); connect(widget, SIGNAL(xChanged()), this, SLOT(setScrollX()));
connect(widget, SIGNAL(yChanged()), this, SLOT(setScrollY())); connect(widget, SIGNAL(yChanged()), this, SLOT(setScrollY()));
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@ -1011,11 +1070,13 @@ void ScrollWidget::ensureItemVisible(QGraphicsItem *item)
void ScrollWidget::registerAsDragHandle(QGraphicsWidget *item) void ScrollWidget::registerAsDragHandle(QGraphicsWidget *item)
{ {
Q_UNUSED(item);
return; return;
} }
void ScrollWidget::unregisterAsDragHandle(QGraphicsWidget *item) void ScrollWidget::unregisterAsDragHandle(QGraphicsWidget *item)
{ {
Q_UNUSED(item);
return; return;
} }
@ -1031,19 +1092,37 @@ QRectF ScrollWidget::viewportGeometry() const
QSizeF ScrollWidget::contentsSize() const QSizeF ScrollWidget::contentsSize() const
{ {
return d->widget ? d->widget.data()->size() : QSizeF(); if (d->widget) {
if (d->hasContentsProperty) {
QVariant var = d->widget.data()->property("contentsSize");
return var.toSizeF();
} else
return d->widget.data()->size();
}
return QSizeF();
} }
void ScrollWidget::setScrollPosition(const QPointF &position) void ScrollWidget::setScrollPosition(const QPointF &position)
{ {
if (d->widget) { if (d->widget) {
if (d->hasOffsetProperty)
d->widget.data()->setProperty("scrollPosition", position);
else
d->widget.data()->setPos(-position.toPoint()); d->widget.data()->setPos(-position.toPoint());
} }
} }
QPointF ScrollWidget::scrollPosition() const QPointF ScrollWidget::scrollPosition() const
{ {
return d->widget ? -d->widget.data()->pos() : QPointF(); if (d->widget) {
if (d->hasOffsetProperty) {
QVariant var = d->widget.data()->property("scrollPosition");
return var.toPointF();
} else {
return -d->widget.data()->pos();
}
}
return QPointF();
} }
void ScrollWidget::setStyleSheet(const QString &styleSheet) void ScrollWidget::setStyleSheet(const QString &styleSheet)
@ -1176,7 +1255,7 @@ bool ScrollWidget::sceneEventFilter(QGraphicsItem *i, QEvent *e)
{ {
//only the scrolling widget and its children //only the scrolling widget and its children
if (!d->widget.data() || if (!d->widget.data() ||
(!d->widget.data()->isAncestorOf(i) && i != d->scrollingWidget)) (!d->scrollingWidget->isAncestorOf(i) && i != d->scrollingWidget))
return false; return false;
bool stealThisEvent = d->stealEvent; bool stealThisEvent = d->stealEvent;

View File

@ -35,6 +35,7 @@
#include "animator.h" #include "animator.h"
#include "plasma.h" #include "plasma.h"
#include "widgets/webview.h" #include "widgets/webview.h"
#include "widgets/scrollwidget.h"
#include "private/animablegraphicswebview_p.h" #include "private/animablegraphicswebview_p.h"
namespace Plasma namespace Plasma
@ -53,6 +54,7 @@ public:
WebView *q; WebView *q;
AnimableGraphicsWebView *webView; AnimableGraphicsWebView *webView;
ScrollWidget *scrollWidget;
bool loaded; bool loaded;
}; };
@ -66,14 +68,16 @@ WebView::WebView(QGraphicsItem *parent)
setAcceptsHoverEvents(true); setAcceptsHoverEvents(true);
setFlags(QGraphicsItem::ItemIsFocusable); setFlags(QGraphicsItem::ItemIsFocusable);
d->webView = new AnimableGraphicsWebView(this); d->scrollWidget = new Plasma::ScrollWidget(this);
d->webView->setDragToScroll(false); d->webView = new AnimableGraphicsWebView(d->scrollWidget);
d->scrollWidget->setWidget(d->webView);
d->scrollWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
d->scrollWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setDragToScroll(false);
QPalette palette = qApp->palette(); QPalette palette = qApp->palette();
palette.setBrush(QPalette::Base, Qt::transparent); palette.setBrush(QPalette::Base, Qt::transparent);
d->webView->page()->setPalette(palette); d->webView->page()->setPalette(palette);
Plasma::Animator::self()->registerScrollingManager(d->webView);
connect(d->webView, SIGNAL(loadProgress(int)), connect(d->webView, SIGNAL(loadProgress(int)),
this, SIGNAL(loadProgress(int))); this, SIGNAL(loadProgress(int)));
connect(d->webView, SIGNAL(loadFinished(bool)), connect(d->webView, SIGNAL(loadFinished(bool)),
@ -170,6 +174,7 @@ QWebFrame *WebView::mainFrame() const
void WebView::setDragToScroll(bool drag) void WebView::setDragToScroll(bool drag)
{ {
d->webView->setDragToScroll(drag); d->webView->setDragToScroll(drag);
d->scrollWidget->setFiltersChildEvents(drag);
} }
bool WebView::dragToScroll() bool WebView::dragToScroll()
@ -271,7 +276,8 @@ QVariant WebView::itemChange(GraphicsItemChange change, const QVariant &value)
void WebView::setGeometry(const QRectF &geometry) void WebView::setGeometry(const QRectF &geometry)
{ {
QGraphicsWidget::setGeometry(geometry); QGraphicsWidget::setGeometry(geometry);
d->webView->setGeometry(QRectF(0, 0, geometry.width(), geometry.height())); d->scrollWidget->setGeometry(QRectF(0, 0, geometry.width(), geometry.height()));
d->webView->setGeometry(d->scrollWidget->viewportGeometry());
} }
QSizeF WebView::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const QSizeF WebView::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const