1 /* |
|
2 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) |
|
3 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> |
|
4 * Copyright (C) 2006 George Staikos <staikos@kde.org> |
|
5 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org> |
|
6 * Copyright (C) 2006 Zack Rusin <zack@kde.org> |
|
7 * Copyright (C) 2006 Simon Hausmann <hausmann@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 { |
|
46 setScene(new QGraphicsScene(this)); |
|
47 scene()->addItem(m_item); |
|
48 |
|
49 setFrameShape(QFrame::NoFrame); |
|
50 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
51 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
52 |
|
53 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) |
|
54 QStateMachine* machine = new QStateMachine(this); |
|
55 QState* s0 = new QState(machine); |
|
56 s0->assignProperty(this, "yRotation", 0); |
|
57 |
|
58 QState* s1 = new QState(machine); |
|
59 s1->assignProperty(this, "yRotation", 90); |
|
60 |
|
61 QAbstractTransition* t1 = s0->addTransition(this, SIGNAL(yFlipRequest()), s1); |
|
62 QPropertyAnimation* yRotationAnim = new QPropertyAnimation(this, "yRotation", this); |
|
63 yRotationAnim->setDuration(1000); |
|
64 t1->addAnimation(yRotationAnim); |
|
65 |
|
66 QState* s2 = new QState(machine); |
|
67 s2->assignProperty(this, "yRotation", -90); |
|
68 s1->addTransition(s1, SIGNAL(propertiesAssigned()), s2); |
|
69 |
|
70 QAbstractTransition* t2 = s2->addTransition(s0); |
|
71 t2->addAnimation(yRotationAnim); |
|
72 |
|
73 machine->setInitialState(s0); |
|
74 machine->start(); |
|
75 #endif |
|
76 |
|
77 m_updateTimer = new QTimer(this); |
|
78 m_updateTimer->setInterval(1000); |
|
79 connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(updateFrameRate())); |
|
80 } |
|
81 |
|
82 void WebViewGraphicsBased::setPage(QWebPage* page) |
|
83 { |
|
84 connect(page->mainFrame(), SIGNAL(contentsSizeChanged(const QSize&)), SLOT(contentsSizeChanged(const QSize&))); |
|
85 m_item->setPage(page); |
|
86 } |
|
87 |
|
88 void WebViewGraphicsBased::contentsSizeChanged(const QSize& size) |
|
89 { |
|
90 if (m_resizesToContents) |
|
91 scene()->setSceneRect(0, 0, size.width(), size.height()); |
|
92 } |
|
93 |
|
94 void WebViewGraphicsBased::setResizesToContents(bool b) |
|
95 { |
|
96 if (b == m_resizesToContents) |
|
97 return; |
|
98 |
|
99 m_resizesToContents = b; |
|
100 m_item->setResizesToContents(m_resizesToContents); |
|
101 |
|
102 // When setting resizesToContents ON, our web view widget will always size as big as the |
|
103 // web content being displayed, and so will the QWebPage's viewport. It implies that internally |
|
104 // WebCore will work as if there was no content rendered offscreen, and then no scrollbars need |
|
105 // drawing. In order to keep scrolling working, we: |
|
106 // |
|
107 // 1) Set QGraphicsView's scrollbars policy back to 'auto'. |
|
108 // 2) Set scene's boundaries rect to an invalid size, which automatically makes it to be as big |
|
109 // as it needs to enclose all items onto it. We do that because QGraphicsView also calculates |
|
110 // the size of its scrollable area according to the amount of content in scene that is rendered |
|
111 // offscreen. |
|
112 // 3) Set QWebPage's preferredContentsSize according to the size of QGraphicsView's viewport, |
|
113 // so WebCore properly lays pages out. |
|
114 // |
|
115 // On the other hand, when toggling resizesToContents OFF, we set back the default values, as |
|
116 // opposite as described above. |
|
117 if (m_resizesToContents) { |
|
118 setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); |
|
119 setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); |
|
120 m_item->page()->setPreferredContentsSize(size()); |
|
121 QRectF itemRect(m_item->geometry().topLeft(), m_item->page()->mainFrame()->contentsSize()); |
|
122 m_item->setGeometry(itemRect); |
|
123 scene()->setSceneRect(itemRect); |
|
124 } else { |
|
125 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
126 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); |
|
127 m_item->page()->setPreferredContentsSize(QSize()); |
|
128 QRect viewportRect(QPoint(0, 0), size()); |
|
129 m_item->setGeometry(viewportRect); |
|
130 scene()->setSceneRect(viewportRect); |
|
131 } |
|
132 } |
|
133 |
|
134 void WebViewGraphicsBased::resizeEvent(QResizeEvent* event) |
|
135 { |
|
136 QGraphicsView::resizeEvent(event); |
|
137 |
|
138 QSize size(event->size()); |
|
139 |
|
140 if (m_resizesToContents) { |
|
141 m_item->page()->setPreferredContentsSize(size); |
|
142 return; |
|
143 } |
|
144 |
|
145 QRectF rect(QPoint(0, 0), size); |
|
146 m_item->setGeometry(rect); |
|
147 scene()->setSceneRect(rect); |
|
148 } |
|
149 |
|
150 void WebViewGraphicsBased::setFrameRateMeasurementEnabled(bool enabled) |
|
151 { |
|
152 m_measureFps = enabled; |
|
153 if (m_measureFps) { |
|
154 m_lastConsultTime = m_startTime = QTime::currentTime(); |
|
155 m_fpsTimer.start(); |
|
156 m_updateTimer->start(); |
|
157 } else { |
|
158 m_fpsTimer.stop(); |
|
159 m_updateTimer->stop(); |
|
160 } |
|
161 } |
|
162 |
|
163 void WebViewGraphicsBased::updateFrameRate() |
|
164 { |
|
165 const QTime now = QTime::currentTime(); |
|
166 int interval = m_lastConsultTime.msecsTo(now); |
|
167 int frames = m_fpsTimer.numFrames(interval); |
|
168 int current = interval ? frames * 1000 / interval : 0; |
|
169 |
|
170 emit currentFPSUpdated(current); |
|
171 |
|
172 m_lastConsultTime = now; |
|
173 } |
|
174 |
|
175 void WebViewGraphicsBased::animatedFlip() |
|
176 { |
|
177 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) |
|
178 QSizeF center = m_item->boundingRect().size() / 2; |
|
179 QPointF centerPoint = QPointF(center.width(), center.height()); |
|
180 m_item->setTransformOriginPoint(centerPoint); |
|
181 |
|
182 QPropertyAnimation* animation = new QPropertyAnimation(m_item, "rotation", this); |
|
183 animation->setDuration(1000); |
|
184 |
|
185 int rotation = int(m_item->rotation()); |
|
186 |
|
187 animation->setStartValue(rotation); |
|
188 animation->setEndValue(rotation + 180 - (rotation % 180)); |
|
189 |
|
190 animation->start(QAbstractAnimation::DeleteWhenStopped); |
|
191 #endif |
|
192 } |
|
193 |
|
194 void WebViewGraphicsBased::animatedYFlip() |
|
195 { |
|
196 emit yFlipRequest(); |
|
197 } |
|
198 |
|
199 void WebViewGraphicsBased::paintEvent(QPaintEvent* event) |
|
200 { |
|
201 QGraphicsView::paintEvent(event); |
|
202 if (!m_measureFps) |
|
203 return; |
|
204 } |
|
205 |
|
206 static QMenu* createContextMenu(QWebPage* page, QPoint position) |
|
207 { |
|
208 QMenu* menu = page->createStandardContextMenu(); |
|
209 |
|
210 QWebHitTestResult r = page->mainFrame()->hitTestContent(position); |
|
211 |
|
212 if (!r.linkUrl().isEmpty()) { |
|
213 WebPage* webPage = qobject_cast<WebPage*>(page); |
|
214 QAction* newTabAction = menu->addAction("Open in Default &Browser", webPage, SLOT(openUrlInDefaultBrowser())); |
|
215 newTabAction->setData(r.linkUrl()); |
|
216 menu->insertAction(menu->actions().at(2), newTabAction); |
|
217 } |
|
218 return menu; |
|
219 } |
|
220 |
|
221 void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* event) |
|
222 { |
|
223 setProperty("mouseButtons", QVariant::fromValue(int(event->buttons()))); |
|
224 setProperty("keyboardModifiers", QVariant::fromValue(int(event->modifiers()))); |
|
225 |
|
226 QGraphicsWebView::mousePressEvent(event); |
|
227 } |
|
228 |
|
229 void WebViewTraditional::mousePressEvent(QMouseEvent* event) |
|
230 { |
|
231 setProperty("mouseButtons", QVariant::fromValue(int(event->buttons()))); |
|
232 setProperty("keyboardModifiers", QVariant::fromValue(int(event->modifiers()))); |
|
233 |
|
234 QWebView::mousePressEvent(event); |
|
235 } |
|
236 |
|
237 void GraphicsWebView::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) |
|
238 { |
|
239 QMenu* menu = createContextMenu(page(), event->pos().toPoint()); |
|
240 menu->exec(event->screenPos()); |
|
241 delete menu; |
|
242 } |
|
243 |
|
244 void WebViewTraditional::contextMenuEvent(QContextMenuEvent* event) |
|
245 { |
|
246 QMenu* menu = createContextMenu(page(), event->pos()); |
|
247 menu->exec(event->globalPos()); |
|
248 delete menu; |
|
249 } |
|
250 |
|