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);
}
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"

View File

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

View File

@ -140,6 +140,11 @@ public:
hasOvershoot = true;
alignment = Qt::AlignLeft | Qt::AlignTop;
hasContentsProperty = false;
hasOffsetProperty = false;
hasXProperty = false;
hasYProperty = false;
}
void adjustScrollbars()
@ -298,7 +303,7 @@ public:
void animateMoveTo(const QPointF &pos)
{
qreal duration = 800;
QPointF start = widget.data()->pos();
QPointF start = q->scrollPosition();
QSizeF threshold = q->viewportGeometry().size();
QPointF diff = pos - start;
@ -345,6 +350,7 @@ public:
qreal duration = qAbs(v / deceleration);
qreal diffY = v * duration + (0.5 * deceleration * duration * duration);
qreal startY = val;
qreal endY = startY + diffY;
if (velocity > 0) {
@ -356,6 +362,12 @@ public:
}
duration = qAbs((endY-startY)/ (-v/2));
if (hasYProperty) {
startY = -startY;
endY = -endY;
}
#if DEBUG
qDebug()<<"XXX velocity = "<<v <<", target = "<< target
<<", maxDist = "<<maxDistance;
@ -380,12 +392,12 @@ public:
}
void flickX(qreal velocity)
{
flick(flickAnimationX, velocity, widget.data()->x(), minXExtent(), maxXExtent(),
flick(flickAnimationX, velocity, widgetX(), minXExtent(), maxXExtent(),
q->viewportGeometry().width());
}
void flickY(qreal velocity)
{
flick(flickAnimationY, velocity, widget.data()->y(),minYExtent(), maxYExtent(),
flick(flickAnimationY, velocity, widgetY(),minYExtent(), maxYExtent(),
q->viewportGeometry().height());
}
void fixup(QAnimationGroup *group,
@ -427,12 +439,12 @@ public:
void fixupX()
{
fixup(fixupAnimation.groupX, fixupAnimation.startX, fixupAnimation.endX,
widget.data()->x(), minXExtent(), maxXExtent());
widgetX(), minXExtent(), maxXExtent());
}
void fixupY()
{
fixup(fixupAnimation.groupY, fixupAnimation.startY, fixupAnimation.endY,
widget.data()->y(), minYExtent(), maxYExtent());
widgetY(), minYExtent(), maxYExtent());
}
void makeRectVisible()
@ -466,7 +478,7 @@ public:
delta.setX(viewRect.right() - mappedRect.right());
}
animateMoveTo(widget.data()->pos() + delta);
animateMoveTo(q->scrollPosition() - delta);
}
void makeItemVisible(QGraphicsItem *itemToBeVisible)
@ -496,6 +508,35 @@ public:
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)
{
lastPos = QPoint();
@ -533,7 +574,7 @@ public:
rejectY = true;
}
if (!rejectY && stealEvent) {
widget.data()->setY(qRound(newY));
setWidgetY(qRound(newY));
moved = true;
}
if (qAbs(dy) > QApplication::startDragDistance())
@ -560,7 +601,7 @@ public:
rejectX = true;
}
if (!rejectX && stealEvent) {
widget.data()->setX(qRound(newX));
setWidgetX(qRound(newX));
moved = true;
}
@ -642,7 +683,7 @@ public:
if (!widget.data())
return;
QPointF start = widget.data()->pos();
QPointF start = q->scrollPosition();
QPointF end = start;
//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
// we make it a pixel then scrolling by 3 (default) pixels will be
// 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
Qt::Orientation orientation = event->orientation();
@ -754,10 +795,18 @@ public:
void createFlickAnimations()
{
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(),
"x", widget.data());
xProp.toLatin1(), widget.data());
flickAnimationY = new QPropertyAnimation(widget.data(),
"y", widget.data());
yProp.toLatin1(), widget.data());
QObject::connect(flickAnimationX, SIGNAL(finished()),
q, SLOT(fixupX()));
QObject::connect(flickAnimationY, SIGNAL(finished()),
@ -781,13 +830,13 @@ public:
fixupAnimation.groupX = new QSequentialAnimationGroup(widget.data());
fixupAnimation.groupY = new QSequentialAnimationGroup(widget.data());
fixupAnimation.startX = new QPropertyAnimation(widget.data(),
"x", widget.data());
xProp.toLatin1(), widget.data());
fixupAnimation.startY = new QPropertyAnimation(widget.data(),
"y", widget.data());
yProp.toLatin1(), widget.data());
fixupAnimation.endX = new QPropertyAnimation(widget.data(),
"x", widget.data());
xProp.toLatin1(), widget.data());
fixupAnimation.endY = new QPropertyAnimation(widget.data(),
"y", widget.data());
yProp.toLatin1(), widget.data());
fixupAnimation.groupX->addAnimation(
fixupAnimation.startX);
fixupAnimation.groupY->addAnimation(
@ -813,9 +862,9 @@ public:
q, SIGNAL(scrollStateChanged(QAbstractAnimation::State,
QAbstractAnimation::State)));
directMoveAnimation = new QPropertyAnimation(widget.data(),
"pos",
widget.data());
directMoveAnimation = new QPropertyAnimation(q,
"scrollPosition",
q);
QObject::connect(directMoveAnimation, SIGNAL(finished()),
q, SLOT(fixupX()));
QObject::connect(directMoveAnimation, SIGNAL(finished()),
@ -900,6 +949,11 @@ public:
bool hasOvershoot;
Qt::Alignment alignment;
bool hasContentsProperty;
bool hasOffsetProperty;
bool hasXProperty;
bool hasYProperty;
};
@ -931,9 +985,14 @@ void ScrollWidget::setWidget(QGraphicsWidget *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
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(yChanged()), this, SLOT(setScrollY()));
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
@ -1011,11 +1070,13 @@ void ScrollWidget::ensureItemVisible(QGraphicsItem *item)
void ScrollWidget::registerAsDragHandle(QGraphicsWidget *item)
{
Q_UNUSED(item);
return;
}
void ScrollWidget::unregisterAsDragHandle(QGraphicsWidget *item)
{
Q_UNUSED(item);
return;
}
@ -1031,19 +1092,37 @@ QRectF ScrollWidget::viewportGeometry() 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)
{
if (d->widget) {
d->widget.data()->setPos(-position.toPoint());
if (d->hasOffsetProperty)
d->widget.data()->setProperty("scrollPosition", position);
else
d->widget.data()->setPos(-position.toPoint());
}
}
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)
@ -1176,7 +1255,7 @@ bool ScrollWidget::sceneEventFilter(QGraphicsItem *i, QEvent *e)
{
//only the scrolling widget and its children
if (!d->widget.data() ||
(!d->widget.data()->isAncestorOf(i) && i != d->scrollingWidget))
(!d->scrollingWidget->isAncestorOf(i) && i != d->scrollingWidget))
return false;
bool stealThisEvent = d->stealEvent;

View File

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