305 lines
8.4 KiB
C++
305 lines
8.4 KiB
C++
|
/****************************************************************************
|
||
|
**
|
||
|
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
||
|
** All rights reserved.
|
||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||
|
**
|
||
|
** This file is part of the test suite of the Qt Toolkit.
|
||
|
**
|
||
|
** $QT_BEGIN_LICENSE:LGPL$
|
||
|
** No Commercial Usage
|
||
|
** This file contains pre-release code and may not be distributed.
|
||
|
** You may use this file in accordance with the terms and conditions
|
||
|
** contained in the Technology Preview License Agreement accompanying
|
||
|
** this package.
|
||
|
**
|
||
|
** 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, Nokia gives you certain additional
|
||
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||
|
**
|
||
|
** If you have questions regarding the use of this file, please contact
|
||
|
** Nokia at qt-info@nokia.com.
|
||
|
**
|
||
|
**
|
||
|
**
|
||
|
**
|
||
|
**
|
||
|
**
|
||
|
**
|
||
|
**
|
||
|
** $QT_END_LICENSE$
|
||
|
**
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "webview.h"
|
||
|
#include "webview_p.h"
|
||
|
#include <QtGui>
|
||
|
|
||
|
static const int MotionEndWaitTime = 2000;
|
||
|
static const int TileSideLength = 128;
|
||
|
|
||
|
WebViewPrivate::WebViewPrivate(WebView *w)
|
||
|
: q(w)
|
||
|
, cache(0)
|
||
|
{
|
||
|
web = new QGraphicsWebView;
|
||
|
|
||
|
web->setParentItem(q->viewport());
|
||
|
|
||
|
web->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||
|
web->page()->mainFrame()->setScrollBarPolicy(
|
||
|
Qt::Horizontal, Qt::ScrollBarAlwaysOff);
|
||
|
web->page()->mainFrame()->setScrollBarPolicy(
|
||
|
Qt::Vertical, Qt::ScrollBarAlwaysOff);
|
||
|
web->setZValue(3);
|
||
|
|
||
|
// cache = new WebViewCache(web);
|
||
|
// web->setGraphicsEffect(cache);
|
||
|
|
||
|
adjustSize();
|
||
|
}
|
||
|
|
||
|
void WebViewPrivate::adjustSize()
|
||
|
{
|
||
|
QSizeF contentSize = web->page()->mainFrame()->contentsSize();
|
||
|
QPointF pos = web->pos();
|
||
|
|
||
|
qreal w = qMax(contentSize.width(), q->viewport()->boundingRect().width());
|
||
|
qreal h = qMax(contentSize.height(), q->viewport()->boundingRect().height());
|
||
|
|
||
|
if (web->boundingRect().size() != QSizeF(w, h)) {
|
||
|
//qDebug() << "WebView: adjustSize:" << QSizeF(w, h);
|
||
|
|
||
|
web->resize(w, h);
|
||
|
web->setPos(pos);
|
||
|
|
||
|
if (w > q->viewport()->boundingRect().width())
|
||
|
q->horizontalScrollBar()->setSliderSize(w);
|
||
|
else
|
||
|
q->horizontalScrollBar()->setSliderSize(0.0);
|
||
|
|
||
|
|
||
|
if (h > q->viewport()->boundingRect().height())
|
||
|
q->verticalScrollBar()->setSliderSize(h);
|
||
|
else
|
||
|
q->verticalScrollBar()->setSliderSize(0.0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void WebViewPrivate::_q_loadStarted()
|
||
|
{
|
||
|
qDebug() << "WebView: load started";
|
||
|
adjustSize();
|
||
|
}
|
||
|
|
||
|
void WebViewPrivate::_q_loadProgress(int progress)
|
||
|
{
|
||
|
Q_UNUSED(progress)
|
||
|
// qDebug() << "WebView: load progress" << progress;
|
||
|
adjustSize();
|
||
|
}
|
||
|
|
||
|
void WebViewPrivate::_q_loadFinished(bool ok)
|
||
|
{
|
||
|
qDebug() << "WebView: load finished" << (ok ? "ok" : "not ok");
|
||
|
adjustSize();
|
||
|
}
|
||
|
|
||
|
void WebViewPrivate::_q_viewportChanged(QGraphicsWidget* viewport)
|
||
|
{
|
||
|
web->setParentItem(viewport);
|
||
|
viewport->setFlag(QGraphicsItem::ItemClipsChildrenToShape,
|
||
|
true);
|
||
|
adjustSize();
|
||
|
}
|
||
|
|
||
|
void WebViewPrivate::_q_motionEnded()
|
||
|
{
|
||
|
motionTimer.stop();
|
||
|
qDebug() << "Motion ended";
|
||
|
q->prepareGeometryChange();
|
||
|
}
|
||
|
|
||
|
WebViewCache::WebViewCache(QGraphicsWebView *webView)
|
||
|
: m_webView(webView)
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
WebViewCache::~WebViewCache()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void WebViewCache::draw(QPainter * painter, QGraphicsEffectSource * source)
|
||
|
{
|
||
|
const QGraphicsItem *item = source->graphicsItem();
|
||
|
|
||
|
QSizeF itemSize = item->boundingRect().size();
|
||
|
|
||
|
if (!qFuzzyCompare(itemSize.width(), m_itemSize.width()) ||
|
||
|
!qFuzzyCompare(itemSize.height(), m_itemSize.height())) {
|
||
|
qDebug() << "Refresh tile cache, for new size" << itemSize;
|
||
|
|
||
|
for (int i = 0; i < m_tilePixmaps.size(); i++) {
|
||
|
QPixmapCache::remove(m_tilePixmaps[i]);
|
||
|
}
|
||
|
|
||
|
m_tilePixmaps.clear();
|
||
|
m_tileRects.clear();
|
||
|
|
||
|
int itemWidth = itemSize.width() + 0.5;
|
||
|
int itemHeight = itemSize.height() + 0.5;
|
||
|
|
||
|
int tilesX = itemWidth / TileSideLength;
|
||
|
int tilesY = itemHeight / TileSideLength;
|
||
|
|
||
|
if ((itemWidth % TileSideLength) != 0) {
|
||
|
++tilesX;
|
||
|
}
|
||
|
|
||
|
if ((itemHeight % TileSideLength) != 0) {
|
||
|
++tilesY;
|
||
|
}
|
||
|
|
||
|
int tilesCount = tilesX * tilesY;
|
||
|
|
||
|
m_tilePixmaps.resize(tilesCount);
|
||
|
m_tileRects.resize(tilesCount);
|
||
|
|
||
|
for (int i = 0; i < tilesX; i++) {
|
||
|
for (int j = 0; j < tilesY; j++) {
|
||
|
int x = i * TileSideLength;
|
||
|
int y = j * TileSideLength;
|
||
|
|
||
|
m_tileRects[i + j * tilesX]
|
||
|
= QRectF(x, y, TileSideLength, TileSideLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_itemSize = itemSize;
|
||
|
}
|
||
|
|
||
|
const QGraphicsItem *parentItem = item->parentItem();
|
||
|
QPointF itemPos = item->pos();
|
||
|
QRectF parentRect = parentItem->boundingRect();
|
||
|
|
||
|
for (int i = 0; i < m_tileRects.size(); i++) {
|
||
|
QRectF tileRect = m_tileRects[i].translated(itemPos);
|
||
|
|
||
|
if (!tileRect.intersects(parentRect) && !tileRect.contains(parentRect)) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
QPixmap tilePixmap;
|
||
|
|
||
|
if (!QPixmapCache::find(m_tilePixmaps[i], &tilePixmap)) {
|
||
|
tilePixmap = QPixmap(TileSideLength, TileSideLength);
|
||
|
|
||
|
QWebFrame *webFrame = m_webView->page()->mainFrame();
|
||
|
|
||
|
QPainter tilePainter(&tilePixmap);
|
||
|
tilePainter.translate(-m_tileRects[i].left(), -m_tileRects[i].top());
|
||
|
webFrame->render(&tilePainter, m_tileRects[i].toRect());
|
||
|
tilePainter.end();
|
||
|
|
||
|
m_tilePixmaps[i] = QPixmapCache::insert(tilePixmap);
|
||
|
}
|
||
|
|
||
|
tileRect = tileRect.translated(-itemPos);
|
||
|
|
||
|
painter->drawPixmap(tileRect.topLeft(), tilePixmap);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WebView::WebView(QGraphicsWidget *parent)
|
||
|
: AbstractScrollArea(parent)
|
||
|
, d(new WebViewPrivate(this))
|
||
|
{
|
||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||
|
setContentsMargins(0, 0, 0, 0);
|
||
|
connect(d->web->page(), SIGNAL(loadStarted()),
|
||
|
this, SLOT(_q_loadStarted()));
|
||
|
connect(d->web->page(), SIGNAL(loadProgress(int)),
|
||
|
this, SLOT(_q_loadProgress(int)));
|
||
|
connect(d->web->page(), SIGNAL(loadFinished(bool)),
|
||
|
this, SLOT(_q_loadFinished(bool)));
|
||
|
connect(this, SIGNAL(viewportChanged(QGraphicsWidget*)),
|
||
|
this, SLOT(_q_viewportChanged(QGraphicsWidget*)));
|
||
|
connect(&d->motionTimer, SIGNAL(timeout()),
|
||
|
this, SLOT(_q_motionEnded()));
|
||
|
}
|
||
|
|
||
|
WebView::~WebView()
|
||
|
{
|
||
|
d->web->setGraphicsEffect(0);
|
||
|
delete d->cache;
|
||
|
}
|
||
|
|
||
|
void WebView::setUrl(const QUrl& url)
|
||
|
{
|
||
|
d->adjustSize();
|
||
|
d->web->setUrl(url);
|
||
|
}
|
||
|
|
||
|
void WebView::scrollContentsBy(qreal dx, qreal dy)
|
||
|
{
|
||
|
if (qFuzzyCompare((float)dy, 0.0f) && qFuzzyCompare((float)dx, 0.0f))
|
||
|
return;
|
||
|
|
||
|
if (!d->motionTimer.isActive()) {
|
||
|
d->motionTimer.start(MotionEndWaitTime);
|
||
|
}
|
||
|
|
||
|
QSizeF contentSize = d->web->page()->mainFrame()->contentsSize();
|
||
|
QRectF viewportRect = viewport()->boundingRect();
|
||
|
QPointF pos = d->web->pos();
|
||
|
|
||
|
qreal w = qMax(contentSize.width(), viewportRect.width());
|
||
|
qreal h = qMax(contentSize.height(), viewportRect.height());
|
||
|
|
||
|
qreal minx = qMin(0.0f, (float) -(w - viewportRect.width()));
|
||
|
qreal miny = qMin(0.0f, (float) -(h - viewportRect.height()));
|
||
|
|
||
|
qreal x = d->web->pos().x() - dx;
|
||
|
|
||
|
if (x < minx)
|
||
|
x = minx;
|
||
|
else if (x > 0)
|
||
|
x = 0.0;
|
||
|
|
||
|
qreal y = d->web->pos().y() - dy;
|
||
|
|
||
|
if (y < miny)
|
||
|
y = miny;
|
||
|
else if (y > 0)
|
||
|
y = 0.0;
|
||
|
|
||
|
d->web->setPos(x, y);
|
||
|
}
|
||
|
|
||
|
QSizeF WebView::sizeHint(Qt::SizeHint which, const QSizeF & constraint) const
|
||
|
{
|
||
|
if (which == Qt::PreferredSize) {
|
||
|
QSizeF contentSize = d->web->page()->mainFrame()->contentsSize();
|
||
|
return contentSize;
|
||
|
}
|
||
|
|
||
|
return AbstractScrollArea::sizeHint(which, constraint);
|
||
|
}
|
||
|
|
||
|
void WebView::resizeEvent(QGraphicsSceneResizeEvent *event)
|
||
|
{
|
||
|
AbstractScrollArea::resizeEvent(event);
|
||
|
d->adjustSize();
|
||
|
}
|
||
|
|
||
|
#include "moc_webview.cpp"
|