Home | History | Annotate | Download | only in QtTestBrowser
      1 /*
      2  * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
      3  * Copyright (C) 2009 Girish Ramakrishnan <girish (at) forwardbias.in>
      4  * Copyright (C) 2006 George Staikos <staikos (at) kde.org>
      5  * Copyright (C) 2006 Dirk Mueller <mueller (at) kde.org>
      6  * Copyright (C) 2006 Zack Rusin <zack (at) kde.org>
      7  * Copyright (C) 2006 Simon Hausmann <hausmann (at) kde.org>
      8  *
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include "webview.h"
     34 
     35 #include <QtGui>
     36 #include <QGraphicsScene>
     37 
     38 WebViewGraphicsBased::WebViewGraphicsBased(QWidget* parent)
     39     : QGraphicsView(parent)
     40     , m_item(new GraphicsWebView)
     41     , m_numPaintsTotal(0)
     42     , m_numPaintsSinceLastMeasure(0)
     43     , m_measureFps(false)
     44     , m_resizesToContents(false)
     45     , m_machine(0)
     46 {
     47     setScene(new QGraphicsScene(this));
     48     scene()->addItem(m_item);
     49     scene()->setFocusItem(m_item);
     50 
     51     setFrameShape(QFrame::NoFrame);
     52     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     53     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
     54 
     55     m_updateTimer = new QTimer(this);
     56     m_updateTimer->setInterval(1000);
     57     connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameRate()));
     58 }
     59 
     60 void WebViewGraphicsBased::setPage(QWebPage* page)
     61 {
     62     connect(page->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), SLOT(contentsSizeChanged(const QSize&)));
     63     connect(page, SIGNAL(scrollRequested(int, int, const QRect&)), SLOT(scrollRequested(int, int)));
     64     graphicsWebView()->setPage(page);
     65 }
     66 
     67 void WebViewGraphicsBased::scrollRequested(int x, int y)
     68 {
     69     if (!m_resizesToContents)
     70         return;
     71 
     72     // Turn off interactive mode while scrolling, or QGraphicsView will replay the
     73     // last mouse event which may cause WebKit to initiate a drag operation.
     74     bool interactive = isInteractive();
     75     setInteractive(false);
     76 
     77     verticalScrollBar()->setValue(-y);
     78     horizontalScrollBar()->setValue(-x);
     79 
     80     setInteractive(interactive);
     81 }
     82 
     83 void WebViewGraphicsBased::contentsSizeChanged(const QSize& size)
     84 {
     85     if (m_resizesToContents)
     86         scene()->setSceneRect(0, 0, size.width(), size.height());
     87 }
     88 
     89 void WebViewGraphicsBased::setResizesToContents(bool b)
     90 {
     91     if (b == m_resizesToContents)
     92         return;
     93 
     94     m_resizesToContents = b;
     95     graphicsWebView()->setResizesToContents(m_resizesToContents);
     96 
     97     // When setting resizesToContents ON, our web view widget will always size as big as the
     98     // web content being displayed, and so will the QWebPage's viewport. It implies that internally
     99     // WebCore will work as if there was no content rendered offscreen, and then no scrollbars need
    100     // drawing. In order to keep scrolling working, we:
    101     //
    102     // 1) Set QGraphicsView's scrollbars policy back to 'auto'.
    103     // 2) Set scene's boundaries rect to an invalid size, which automatically makes it to be as big
    104     //    as it needs to enclose all items onto it. We do that because QGraphicsView also calculates
    105     //    the size of its scrollable area according to the amount of content in scene that is rendered
    106     //    offscreen.
    107     // 3) Set QWebPage's preferredContentsSize according to the size of QGraphicsView's viewport,
    108     //    so WebCore properly lays pages out.
    109     //
    110     // On the other hand, when toggling resizesToContents OFF, we set back the default values, as
    111     // opposite as described above.
    112     if (m_resizesToContents) {
    113         setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    114         setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
    115         graphicsWebView()->page()->setPreferredContentsSize(size());
    116         QRectF itemRect(graphicsWebView()->geometry().topLeft(), graphicsWebView()->page()->mainFrame()->contentsSize());
    117         graphicsWebView()->setGeometry(itemRect);
    118         scene()->setSceneRect(itemRect);
    119     } else {
    120         setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    121         setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    122         graphicsWebView()->page()->setPreferredContentsSize(QSize());
    123         QRect viewportRect(QPoint(0, 0), size());
    124         graphicsWebView()->setGeometry(viewportRect);
    125         scene()->setSceneRect(viewportRect);
    126     }
    127 }
    128 
    129 void WebViewGraphicsBased::resizeEvent(QResizeEvent* event)
    130 {
    131     QGraphicsView::resizeEvent(event);
    132 
    133     QSize size(event->size());
    134 
    135     if (m_resizesToContents) {
    136         graphicsWebView()->page()->setPreferredContentsSize(size);
    137         return;
    138     }
    139 
    140     QRectF rect(QPoint(0, 0), size);
    141     graphicsWebView()->setGeometry(rect);
    142     scene()->setSceneRect(rect);
    143 }
    144 
    145 void WebViewGraphicsBased::setFrameRateMeasurementEnabled(bool enabled)
    146 {
    147     m_measureFps = enabled;
    148     if (m_measureFps) {
    149         m_lastConsultTime = m_startTime = QTime::currentTime();
    150         m_fpsTimer.start();
    151         m_updateTimer->start();
    152     } else {
    153         m_fpsTimer.stop();
    154         m_updateTimer->stop();
    155     }
    156 }
    157 
    158 void WebViewGraphicsBased::updateFrameRate()
    159 {
    160     const QTime now = QTime::currentTime();
    161     int interval = m_lastConsultTime.msecsTo(now);
    162     int frames = m_fpsTimer.numFrames(interval);
    163     int current = interval ? frames * 1000 / interval : 0;
    164 
    165     emit currentFPSUpdated(current);
    166 
    167     m_lastConsultTime = now;
    168 }
    169 
    170 void WebViewGraphicsBased::animatedFlip()
    171 {
    172 #ifndef QT_NO_ANIMATION
    173     QSizeF center = graphicsWebView()->boundingRect().size() / 2;
    174     QPointF centerPoint = QPointF(center.width(), center.height());
    175     graphicsWebView()->setTransformOriginPoint(centerPoint);
    176 
    177     QPropertyAnimation* animation = new QPropertyAnimation(graphicsWebView(), "rotation", this);
    178     animation->setDuration(1000);
    179 
    180     int rotation = int(graphicsWebView()->rotation());
    181 
    182     animation->setStartValue(rotation);
    183     animation->setEndValue(rotation + 180 - (rotation % 180));
    184 
    185     animation->start(QAbstractAnimation::DeleteWhenStopped);
    186 #endif
    187 }
    188 
    189 void WebViewGraphicsBased::animatedYFlip()
    190 {
    191 #ifndef QT_NO_ANIMATION
    192     if (!m_machine) {
    193         m_machine = new QStateMachine(this);
    194 
    195         QState* s0 = new QState(m_machine);
    196         s0->assignProperty(this, "yRotation", 0);
    197 
    198         QState* s1 = new QState(m_machine);
    199         s1->assignProperty(this, "yRotation", 90);
    200 
    201         QAbstractTransition* t1 = s0->addTransition(s1);
    202         QPropertyAnimation* yRotationAnim = new QPropertyAnimation(this, "yRotation", this);
    203         t1->addAnimation(yRotationAnim);
    204 
    205         QState* s2 = new QState(m_machine);
    206         s2->assignProperty(this, "yRotation", -90);
    207         s1->addTransition(s1, SIGNAL(propertiesAssigned()), s2);
    208 
    209         QState* s3 = new QState(m_machine);
    210         s3->assignProperty(this, "yRotation", 0);
    211 
    212         QAbstractTransition* t2 = s2->addTransition(s3);
    213         t2->addAnimation(yRotationAnim);
    214 
    215         QFinalState* final = new QFinalState(m_machine);
    216         s3->addTransition(s3, SIGNAL(propertiesAssigned()), final);
    217 
    218         m_machine->setInitialState(s0);
    219         yRotationAnim->setDuration(1000);
    220     }
    221 
    222     m_machine->start();
    223 #endif
    224 }
    225 
    226 void WebViewGraphicsBased::paintEvent(QPaintEvent* event)
    227 {
    228     QGraphicsView::paintEvent(event);
    229     if (!m_measureFps)
    230         return;
    231 }
    232 
    233 static QMenu* createContextMenu(QWebPage* page, QPoint position)
    234 {
    235     QMenu* menu = page->createStandardContextMenu();
    236 
    237     QWebHitTestResult r = page->mainFrame()->hitTestContent(position);
    238 
    239     if (!r.linkUrl().isEmpty()) {
    240         WebPage* webPage = qobject_cast<WebPage*>(page);
    241         QAction* newTabAction = menu->addAction("Open in Default &Browser", webPage, SLOT(openUrlInDefaultBrowser()));
    242         newTabAction->setData(r.linkUrl());
    243         menu->insertAction(menu->actions().at(2), newTabAction);
    244     }
    245     return menu;
    246 }
    247 
    248 void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event)
    249 {
    250     setProperty("mouseButtons", QVariant::fromValue(int(event->buttons())));
    251     setProperty("keyboardModifiers", QVariant::fromValue(int(event->modifiers())));
    252 
    253     QGraphicsWebView::mousePressEvent(event);
    254 }
    255 
    256 void WebViewTraditional::mousePressEvent(QMouseEvent* event)
    257 {
    258     setProperty("mouseButtons", QVariant::fromValue(int(event->buttons())));
    259     setProperty("keyboardModifiers", QVariant::fromValue(int(event->modifiers())));
    260 
    261     QWebView::mousePressEvent(event);
    262 }
    263 
    264 void GraphicsWebView::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
    265 {
    266     QMenu* menu = createContextMenu(page(), event->pos().toPoint());
    267     menu->exec(event->screenPos());
    268     delete menu;
    269 }
    270 
    271 void WebViewTraditional::contextMenuEvent(QContextMenuEvent* event)
    272 {
    273     QMenu* menu = createContextMenu(page(), event->pos());
    274     menu->exec(event->globalPos());
    275     delete menu;
    276 }
    277 
    278