2011-01-10 Laszlo Gombos <laszlo.1.gombos@nokia.com>
[WebKit.git] / Tools / QtTestBrowser / launcherwindow.cpp
1 /*
2  * Copyright (C) 2010 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 "launcherwindow.h"
34
35 const int gExitClickArea = 80;
36 QVector<int> LauncherWindow::m_zoomLevels;
37
38 LauncherWindow::LauncherWindow(WindowOptions* data, QGraphicsScene* sharedScene)
39     : MainWindow()
40     , m_currentZoom(100)
41     , m_view(0)
42     , m_inspector(0)
43     , m_formatMenuAction(0)
44     , m_zoomAnimation(0)
45 {
46     if (data)
47         m_windowOptions = *data;
48
49     init();
50     if (sharedScene && data->useGraphicsView)
51         static_cast<QGraphicsView*>(m_view)->setScene(sharedScene);
52
53     createChrome();
54 }
55
56 LauncherWindow::~LauncherWindow()
57 {
58     grabZoomKeys(false);
59 }
60
61 void LauncherWindow::init()
62 {
63     QSplitter* splitter = new QSplitter(Qt::Vertical, this);
64     setCentralWidget(splitter);
65
66 #if defined(Q_OS_SYMBIAN)
67     setWindowState(Qt::WindowMaximized);
68 #else
69     setWindowState(Qt::WindowNoState);
70     resize(800, 600);
71 #endif
72
73     m_inspector = new WebInspector;
74 #ifndef QT_NO_PROPERTIES
75     if (!m_windowOptions.inspectorUrl.isEmpty())
76         m_inspector->setProperty("_q_inspectorUrl", m_windowOptions.inspectorUrl);
77 #endif
78     connect(this, SIGNAL(destroyed()), m_inspector, SLOT(deleteLater()));
79
80     // the zoom values are chosen to be like in Mozilla Firefox 3
81     if (!m_zoomLevels.count()) {
82         m_zoomLevels << 30 << 50 << 67 << 80 << 90;
83         m_zoomLevels << 100;
84         m_zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300;
85     }
86
87     grabZoomKeys(true);
88
89     initializeView();
90 }
91
92 void LauncherWindow::initializeView()
93 {
94     delete m_view;
95
96     QUrl url = page()->mainFrame()->url();
97     setPage(new WebPage(this));
98     page()->setQnamThreaded(m_windowOptions.useThreadedQnam);
99
100     QSplitter* splitter = static_cast<QSplitter*>(centralWidget());
101
102     if (!m_windowOptions.useGraphicsView) {
103         WebViewTraditional* view = new WebViewTraditional(splitter);
104         view->setPage(page());
105
106         view->installEventFilter(this);
107
108         m_view = view;
109     } else {
110         WebViewGraphicsBased* view = new WebViewGraphicsBased(splitter);
111         view->setPage(page());
112
113         connect(view, SIGNAL(currentFPSUpdated(int)), this, SLOT(updateFPS(int)));
114
115         view->installEventFilter(this);
116         // The implementation of QAbstractScrollArea::eventFilter makes us need
117         // to install the event filter also on the viewport of a QGraphicsView.
118         view->viewport()->installEventFilter(this);
119
120         m_view = view;
121     }
122
123     m_touchMocking = false;
124
125     connect(page(), SIGNAL(loadStarted()), this, SLOT(loadStarted()));
126     connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
127     connect(page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)),
128             this, SLOT(showLinkHover(const QString&, const QString&)));
129     connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool)));
130
131     applyPrefs();
132
133     splitter->addWidget(m_inspector);
134     m_inspector->setPage(page());
135     m_inspector->hide();
136
137     if (m_windowOptions.remoteInspectorPort)
138         page()->setProperty("_q_webInspectorServerPort", m_windowOptions.remoteInspectorPort);
139
140     if (url.isValid())
141         page()->mainFrame()->load(url);
142 }
143
144 void LauncherWindow::applyPrefs()
145 {
146     QWebSettings* settings = page()->settings();
147     settings->setAttribute(QWebSettings::AcceleratedCompositingEnabled, m_windowOptions.useCompositing);
148     settings->setAttribute(QWebSettings::TiledBackingStoreEnabled, m_windowOptions.useTiledBackingStore);
149     settings->setAttribute(QWebSettings::FrameFlatteningEnabled, m_windowOptions.useFrameFlattening);
150     settings->setAttribute(QWebSettings::WebGLEnabled, m_windowOptions.useWebGL);
151
152     if (!isGraphicsBased())
153         return;
154
155     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
156     view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode);
157     view->setFrameRateMeasurementEnabled(m_windowOptions.showFrameRate);
158     view->setItemCacheMode(m_windowOptions.cacheWebView ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache);
159
160     if (m_windowOptions.resizesToContents)
161         toggleResizesToContents(m_windowOptions.resizesToContents);
162 }
163
164 void LauncherWindow::createChrome()
165 {
166 #ifndef QT_NO_SHORTCUT
167     QMenu* fileMenu = menuBar()->addMenu("&File");
168     fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New);
169     fileMenu->addAction(tr("Open File..."), this, SLOT(openFile()), QKeySequence::Open);
170     fileMenu->addAction(tr("Open Location..."), this, SLOT(openLocation()), QKeySequence(Qt::CTRL | Qt::Key_L));
171     fileMenu->addAction("Close Window", this, SLOT(close()), QKeySequence::Close);
172     fileMenu->addSeparator();
173     fileMenu->addAction("Take Screen Shot...", this, SLOT(screenshot()));
174 #ifndef QT_NO_PRINTER
175     fileMenu->addAction(tr("Print..."), this, SLOT(print()), QKeySequence::Print);
176 #endif
177     fileMenu->addSeparator();
178     fileMenu->addAction("Quit", QApplication::instance(), SLOT(closeAllWindows()), QKeySequence(Qt::CTRL | Qt::Key_Q));
179
180     QMenu* editMenu = menuBar()->addMenu("&Edit");
181     editMenu->addAction(page()->action(QWebPage::Undo));
182     editMenu->addAction(page()->action(QWebPage::Redo));
183     editMenu->addSeparator();
184     editMenu->addAction(page()->action(QWebPage::Cut));
185     editMenu->addAction(page()->action(QWebPage::Copy));
186     editMenu->addAction(page()->action(QWebPage::Paste));
187     editMenu->addSeparator();
188     QAction* setEditable = editMenu->addAction("Set Editable", this, SLOT(setEditable(bool)));
189     setEditable->setCheckable(true);
190
191     QMenu* viewMenu = menuBar()->addMenu("&View");
192     viewMenu->addAction(page()->action(QWebPage::Stop));
193     viewMenu->addAction(page()->action(QWebPage::Reload));
194     viewMenu->addSeparator();
195     QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn()));
196     QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut()));
197     QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom()));
198     QAction* zoomTextOnly = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool)));
199     zoomTextOnly->setCheckable(true);
200     zoomTextOnly->setChecked(false);
201     viewMenu->addSeparator();
202     viewMenu->addAction("Dump HTML", this, SLOT(dumpHtml()));
203     // viewMenu->addAction("Dump plugins", this, SLOT(dumpPlugins()));
204
205     zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus));
206     zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus));
207     resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
208
209     QMenu* formatMenu = new QMenu("F&ormat", this);
210     m_formatMenuAction = menuBar()->addMenu(formatMenu);
211     m_formatMenuAction->setVisible(false);
212     formatMenu->addAction(page()->action(QWebPage::ToggleBold));
213     formatMenu->addAction(page()->action(QWebPage::ToggleItalic));
214     formatMenu->addAction(page()->action(QWebPage::ToggleUnderline));
215     QMenu* writingMenu = formatMenu->addMenu(tr("Writing Direction"));
216     writingMenu->addAction(page()->action(QWebPage::SetTextDirectionDefault));
217     writingMenu->addAction(page()->action(QWebPage::SetTextDirectionLeftToRight));
218     writingMenu->addAction(page()->action(QWebPage::SetTextDirectionRightToLeft));
219
220     QMenu* windowMenu = menuBar()->addMenu("&Window");
221     QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool)));
222     toggleFullScreen->setShortcut(Qt::Key_F11);
223     toggleFullScreen->setCheckable(true);
224     toggleFullScreen->setChecked(false);
225     // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must
226     // uncheck the Toggle FullScreen action.
227     toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool)));
228
229     QWebSettings* settings = page()->settings();
230
231     QMenu* toolsMenu = menuBar()->addMenu("&Develop");
232     QMenu* graphicsViewMenu = toolsMenu->addMenu("QGraphicsView");
233     QAction* toggleGraphicsView = graphicsViewMenu->addAction("Toggle use of QGraphicsView", this, SLOT(toggleWebView(bool)));
234     toggleGraphicsView->setCheckable(true);
235     toggleGraphicsView->setChecked(isGraphicsBased());
236
237     QAction* toggleWebGL = toolsMenu->addAction("Toggle WebGL", this, SLOT(toggleWebGL(bool)));
238     toggleWebGL->setCheckable(true);
239     toggleWebGL->setChecked(settings->testAttribute(QWebSettings::WebGLEnabled));
240
241     QAction* toggleThreadedQnam = toolsMenu->addAction("Toggle threaded network", this, SLOT(toggleThreadedQnam(bool)));
242     toggleThreadedQnam->setCheckable(true);
243     toggleThreadedQnam->setChecked(m_windowOptions.useThreadedQnam);
244
245     QAction* spatialNavigationAction = toolsMenu->addAction("Toggle Spatial Navigation", this, SLOT(toggleSpatialNavigation(bool)));
246     spatialNavigationAction->setCheckable(true);
247     spatialNavigationAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_S));
248
249     QAction* toggleFrameFlattening = toolsMenu->addAction("Toggle Frame Flattening", this, SLOT(toggleFrameFlattening(bool)));
250     toggleFrameFlattening->setCheckable(true);
251     toggleFrameFlattening->setChecked(settings->testAttribute(QWebSettings::FrameFlatteningEnabled));
252
253     QAction* touchMockAction = toolsMenu->addAction("Toggle touch mocking", this, SLOT(setTouchMocking(bool)));
254     touchMockAction->setCheckable(true);
255     touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T));
256
257     toolsMenu->addSeparator();
258
259     QAction* toggleInterruptingJavaScripteEnabled = toolsMenu->addAction("Enable interrupting js scripts", this, SLOT(toggleInterruptingJavaScriptEnabled(bool)));
260     toggleInterruptingJavaScripteEnabled->setCheckable(true);
261     toggleInterruptingJavaScripteEnabled->setChecked(false);
262
263     QAction* toggleJavascriptCanOpenWindows = toolsMenu->addAction("Enable js popup windows", this, SLOT(toggleJavascriptCanOpenWindows(bool)));
264     toggleJavascriptCanOpenWindows->setCheckable(true);
265     toggleJavascriptCanOpenWindows->setChecked(false);
266
267     toolsMenu->addSeparator();
268
269     QAction* userAgentAction = toolsMenu->addAction("Change User Agent", this, SLOT(showUserAgentDialog()));
270     userAgentAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_U));
271
272     toolsMenu->addAction("Select Elements...", this, SLOT(selectElements()));
273
274     QAction* showInspectorAction = toolsMenu->addAction("Show Web Inspector", m_inspector, SLOT(setVisible(bool)), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I));
275     showInspectorAction->setCheckable(true);
276     showInspectorAction->connect(m_inspector, SIGNAL(visibleChanged(bool)), SLOT(setChecked(bool)));
277
278     // GraphicsView sub menu.
279     QAction* toggleAcceleratedCompositing = graphicsViewMenu->addAction("Toggle Accelerated Compositing", this, SLOT(toggleAcceleratedCompositing(bool)));
280     toggleAcceleratedCompositing->setCheckable(true);
281     toggleAcceleratedCompositing->setChecked(settings->testAttribute(QWebSettings::AcceleratedCompositingEnabled));
282     toggleAcceleratedCompositing->setEnabled(isGraphicsBased());
283     toggleAcceleratedCompositing->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
284
285     QAction* toggleResizesToContents = graphicsViewMenu->addAction("Toggle Resizes To Contents Mode", this, SLOT(toggleResizesToContents(bool)));
286     toggleResizesToContents->setCheckable(true);
287     toggleResizesToContents->setChecked(m_windowOptions.resizesToContents);
288     toggleResizesToContents->setEnabled(isGraphicsBased());
289     toggleResizesToContents->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
290
291     QAction* toggleTiledBackingStore = graphicsViewMenu->addAction("Toggle Tiled Backing Store", this, SLOT(toggleTiledBackingStore(bool)));
292     toggleTiledBackingStore->setCheckable(true);
293     toggleTiledBackingStore->setChecked(m_windowOptions.useTiledBackingStore);
294     toggleTiledBackingStore->setEnabled(isGraphicsBased());
295     toggleTiledBackingStore->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
296
297 #if defined(QT_CONFIGURED_WITH_OPENGL)
298     QAction* toggleQGLWidgetViewport = graphicsViewMenu->addAction("Toggle use of QGLWidget Viewport", this, SLOT(toggleQGLWidgetViewport(bool)));
299     toggleQGLWidgetViewport->setCheckable(true);
300     toggleQGLWidgetViewport->setChecked(m_windowOptions.useQGLWidgetViewport);
301     toggleQGLWidgetViewport->setEnabled(isGraphicsBased());
302     toggleQGLWidgetViewport->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
303 #endif
304
305     QMenu* viewportUpdateMenu = graphicsViewMenu->addMenu("Change Viewport Update Mode");
306     viewportUpdateMenu->setEnabled(isGraphicsBased());
307     viewportUpdateMenu->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
308
309     QAction* fullUpdate = viewportUpdateMenu->addAction("FullViewportUpdate");
310     fullUpdate->setCheckable(true);
311     fullUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::FullViewportUpdate) ? true : false);
312
313     QAction* minimalUpdate = viewportUpdateMenu->addAction("MinimalViewportUpdate");
314     minimalUpdate->setCheckable(true);
315     minimalUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::MinimalViewportUpdate) ? true : false);
316
317     QAction* smartUpdate = viewportUpdateMenu->addAction("SmartViewportUpdate");
318     smartUpdate->setCheckable(true);
319     smartUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::SmartViewportUpdate) ? true : false);
320
321     QAction* boundingRectUpdate = viewportUpdateMenu->addAction("BoundingRectViewportUpdate");
322     boundingRectUpdate->setCheckable(true);
323     boundingRectUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) ? true : false);
324
325     QAction* noUpdate = viewportUpdateMenu->addAction("NoViewportUpdate");
326     noUpdate->setCheckable(true);
327     noUpdate->setChecked((m_windowOptions.viewportUpdateMode == QGraphicsView::NoViewportUpdate) ? true : false);
328
329     QSignalMapper* signalMapper = new QSignalMapper(viewportUpdateMenu);
330     signalMapper->setMapping(fullUpdate, QGraphicsView::FullViewportUpdate);
331     signalMapper->setMapping(minimalUpdate, QGraphicsView::MinimalViewportUpdate);
332     signalMapper->setMapping(smartUpdate, QGraphicsView::SmartViewportUpdate);
333     signalMapper->setMapping(boundingRectUpdate, QGraphicsView::BoundingRectViewportUpdate);
334     signalMapper->setMapping(noUpdate, QGraphicsView::NoViewportUpdate);
335
336     connect(fullUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
337     connect(minimalUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
338     connect(smartUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
339     connect(boundingRectUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
340     connect(noUpdate, SIGNAL(triggered()), signalMapper, SLOT(map()));
341
342     connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(changeViewportUpdateMode(int)));
343
344     QActionGroup* viewportUpdateModeActions = new QActionGroup(viewportUpdateMenu);
345     viewportUpdateModeActions->addAction(fullUpdate);
346     viewportUpdateModeActions->addAction(minimalUpdate);
347     viewportUpdateModeActions->addAction(smartUpdate);
348     viewportUpdateModeActions->addAction(boundingRectUpdate);
349     viewportUpdateModeActions->addAction(noUpdate);
350
351     graphicsViewMenu->addSeparator();
352
353     QAction* flipAnimated = graphicsViewMenu->addAction("Animated Flip");
354     flipAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
355     flipAnimated->setEnabled(isGraphicsBased());
356     connect(flipAnimated, SIGNAL(triggered()), SLOT(animatedFlip()));
357
358     QAction* flipYAnimated = graphicsViewMenu->addAction("Animated Y-Flip");
359     flipYAnimated->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
360     flipYAnimated->setEnabled(isGraphicsBased());
361     connect(flipYAnimated, SIGNAL(triggered()), SLOT(animatedYFlip()));
362
363     QAction* cloneWindow = graphicsViewMenu->addAction("Clone Window", this, SLOT(cloneWindow()));
364     cloneWindow->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
365     cloneWindow->setEnabled(isGraphicsBased());
366
367     graphicsViewMenu->addSeparator();
368
369     QAction* showFPS = graphicsViewMenu->addAction("Show FPS", this, SLOT(showFPS(bool)));
370     showFPS->setCheckable(true);
371     showFPS->setEnabled(isGraphicsBased());
372     showFPS->connect(toggleGraphicsView, SIGNAL(toggled(bool)), SLOT(setEnabled(bool)));
373     showFPS->setChecked(m_windowOptions.showFrameRate);
374 #endif
375 }
376
377 bool LauncherWindow::isGraphicsBased() const
378 {
379     return bool(qobject_cast<QGraphicsView*>(m_view));
380 }
381
382 void LauncherWindow::keyPressEvent(QKeyEvent* event)
383 {
384 #ifdef Q_WS_MAEMO_5
385     switch (event->key()) {
386     case Qt::Key_F7:
387         zoomIn();
388         event->accept();
389         break;
390     case Qt::Key_F8:
391         zoomOut();
392         event->accept();
393         break;
394     }
395 #endif
396     MainWindow::keyPressEvent(event);
397 }
398
399 void LauncherWindow::grabZoomKeys(bool grab)
400 {
401 #ifdef Q_WS_MAEMO_5
402     if (!winId()) {
403         qWarning("Can't grab keys unless we have a window id");
404         return;
405     }
406
407     Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False);
408     if (!atom) {
409         qWarning("Unable to obtain _HILDON_ZOOM_KEY_ATOM");
410         return;
411     }
412
413     unsigned long val = (grab) ? 1 : 0;
414     XChangeProperty(QX11Info::display(), winId(), atom, XA_INTEGER, 32, PropModeReplace, reinterpret_cast<unsigned char*>(&val), 1);
415 #endif
416 }
417
418 void LauncherWindow::sendTouchEvent()
419 {
420     if (m_touchPoints.isEmpty())
421         return;
422
423     QEvent::Type type = QEvent::TouchUpdate;
424     if (m_touchPoints.size() == 1) {
425         if (m_touchPoints[0].state() == Qt::TouchPointReleased)
426             type = QEvent::TouchEnd;
427         else if (m_touchPoints[0].state() == Qt::TouchPointPressed)
428             type = QEvent::TouchBegin;
429     }
430
431     QTouchEvent touchEv(type);
432     touchEv.setTouchPoints(m_touchPoints);
433     QCoreApplication::sendEvent(page(), &touchEv);
434
435     // After sending the event, remove all touchpoints that were released
436     if (m_touchPoints[0].state() == Qt::TouchPointReleased)
437         m_touchPoints.removeAt(0);
438     if (m_touchPoints.size() > 1 && m_touchPoints[1].state() == Qt::TouchPointReleased)
439         m_touchPoints.removeAt(1);
440 }
441
442 bool LauncherWindow::eventFilter(QObject* obj, QEvent* event)
443 {
444     // If click pos is the bottom right corner (square with size defined by gExitClickArea)
445     // and the window is on FullScreen, the window must return to its original state.
446     if (event->type() == QEvent::MouseButtonRelease) {
447         QMouseEvent* ev = static_cast<QMouseEvent*>(event);
448         if (windowState() == Qt::WindowFullScreen
449             && ev->pos().x() > (width() - gExitClickArea)
450             && ev->pos().y() > (height() - gExitClickArea)) {
451
452             emit enteredFullScreenMode(false);
453         }
454     }
455
456     if (!m_touchMocking)
457         return QObject::eventFilter(obj, event);
458
459     if (event->type() == QEvent::MouseButtonPress
460         || event->type() == QEvent::MouseButtonRelease
461         || event->type() == QEvent::MouseButtonDblClick
462         || event->type() == QEvent::MouseMove) {
463
464         QMouseEvent* ev = static_cast<QMouseEvent*>(event);
465         if (ev->type() == QEvent::MouseMove
466             && !(ev->buttons() & Qt::LeftButton))
467             return false;
468
469         QTouchEvent::TouchPoint touchPoint;
470         touchPoint.setState(Qt::TouchPointMoved);
471         if ((ev->type() == QEvent::MouseButtonPress
472              || ev->type() == QEvent::MouseButtonDblClick))
473             touchPoint.setState(Qt::TouchPointPressed);
474         else if (ev->type() == QEvent::MouseButtonRelease)
475             touchPoint.setState(Qt::TouchPointReleased);
476
477         touchPoint.setId(0);
478         touchPoint.setScreenPos(ev->globalPos());
479         touchPoint.setPos(ev->pos());
480         touchPoint.setPressure(1);
481
482         // If the point already exists, update it. Otherwise create it.
483         if (m_touchPoints.size() > 0 && !m_touchPoints[0].id())
484             m_touchPoints[0] = touchPoint;
485         else if (m_touchPoints.size() > 1 && !m_touchPoints[1].id())
486             m_touchPoints[1] = touchPoint;
487         else
488             m_touchPoints.append(touchPoint);
489
490         sendTouchEvent();
491     } else if (event->type() == QEvent::KeyPress
492         && static_cast<QKeyEvent*>(event)->key() == Qt::Key_F
493         && static_cast<QKeyEvent*>(event)->modifiers() == Qt::ControlModifier) {
494
495         // If the keyboard point is already pressed, release it.
496         // Otherwise create it and append to m_touchPoints.
497         if (m_touchPoints.size() > 0 && m_touchPoints[0].id() == 1) {
498             m_touchPoints[0].setState(Qt::TouchPointReleased);
499             sendTouchEvent();
500         } else if (m_touchPoints.size() > 1 && m_touchPoints[1].id() == 1) {
501             m_touchPoints[1].setState(Qt::TouchPointReleased);
502             sendTouchEvent();
503         } else {
504             QTouchEvent::TouchPoint touchPoint;
505             touchPoint.setState(Qt::TouchPointPressed);
506             touchPoint.setId(1);
507             touchPoint.setScreenPos(QCursor::pos());
508             touchPoint.setPos(m_view->mapFromGlobal(QCursor::pos()));
509             touchPoint.setPressure(1);
510             m_touchPoints.append(touchPoint);
511             sendTouchEvent();
512
513             // After sending the event, change the touchpoint state to stationary
514             m_touchPoints.last().setState(Qt::TouchPointStationary);
515         }
516     }
517
518     return false;
519 }
520
521 void LauncherWindow::loadStarted()
522 {
523     m_view->setFocus(Qt::OtherFocusReason);
524 }
525
526 void LauncherWindow::loadFinished()
527 {
528     QUrl url = page()->mainFrame()->url();
529     setAddressUrl(url.toString(QUrl::RemoveUserInfo));
530     addCompleterEntry(url);
531 }
532
533 void LauncherWindow::showLinkHover(const QString &link, const QString &toolTip)
534 {
535 #ifndef Q_WS_MAEMO_5
536     statusBar()->showMessage(link);
537 #endif
538 #ifndef QT_NO_TOOLTIP
539     if (!toolTip.isEmpty())
540         QToolTip::showText(QCursor::pos(), toolTip);
541 #endif
542 }
543
544 void LauncherWindow::zoomAnimationFinished()
545 {
546     if (!isGraphicsBased())
547         return;
548     QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView();
549     view->setTiledBackingStoreFrozen(false);
550 }
551
552 void LauncherWindow::applyZoom()
553 {
554 #ifndef QT_NO_ANIMATION
555     if (isGraphicsBased() && page()->settings()->testAttribute(QWebSettings::TiledBackingStoreEnabled)) {
556         QGraphicsWebView* view = static_cast<WebViewGraphicsBased*>(m_view)->graphicsWebView();
557         view->setTiledBackingStoreFrozen(true);
558         if (!m_zoomAnimation) {
559             m_zoomAnimation = new QPropertyAnimation(view, "scale");
560             m_zoomAnimation->setStartValue(view->scale());
561             connect(m_zoomAnimation, SIGNAL(finished()), this, SLOT(zoomAnimationFinished()));
562         } else {
563             m_zoomAnimation->stop();
564             m_zoomAnimation->setStartValue(m_zoomAnimation->currentValue());
565         }
566
567         m_zoomAnimation->setDuration(300);
568         m_zoomAnimation->setEndValue(qreal(m_currentZoom) / 100.);
569         m_zoomAnimation->start();
570         return;
571     }
572 #endif
573     page()->mainFrame()->setZoomFactor(qreal(m_currentZoom) / 100.0);
574 }
575
576 void LauncherWindow::zoomIn()
577 {
578     int i = m_zoomLevels.indexOf(m_currentZoom);
579     Q_ASSERT(i >= 0);
580     if (i < m_zoomLevels.count() - 1)
581         m_currentZoom = m_zoomLevels[i + 1];
582
583     applyZoom();
584 }
585
586 void LauncherWindow::zoomOut()
587 {
588     int i = m_zoomLevels.indexOf(m_currentZoom);
589     Q_ASSERT(i >= 0);
590     if (i > 0)
591         m_currentZoom = m_zoomLevels[i - 1];
592
593     applyZoom();
594 }
595
596 void LauncherWindow::resetZoom()
597 {
598     m_currentZoom = 100;
599     applyZoom();
600 }
601
602 void LauncherWindow::toggleZoomTextOnly(bool b)
603 {
604     page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b);
605 }
606
607 void LauncherWindow::print()
608 {
609 #if !defined(QT_NO_PRINTER)
610     QPrintPreviewDialog dlg(this);
611     connect(&dlg, SIGNAL(paintRequested(QPrinter*)),
612             page()->mainFrame(), SLOT(print(QPrinter*)));
613     dlg.exec();
614 #endif
615 }
616
617 void LauncherWindow::screenshot()
618 {
619     QPixmap pixmap = QPixmap::grabWidget(m_view);
620     QLabel* label = 0;
621 #if !defined(Q_OS_SYMBIAN)
622     label = new QLabel;
623     label->setAttribute(Qt::WA_DeleteOnClose);
624     label->setWindowTitle("Screenshot - Preview");
625     label->setPixmap(pixmap);
626     label->show();
627 #endif
628
629 #ifndef QT_NO_FILEDIALOG
630     QString fileName = QFileDialog::getSaveFileName(label, "Screenshot");
631     if (!fileName.isEmpty()) {
632         pixmap.save(fileName, "png");
633         if (label)
634             label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName));
635     }
636 #endif
637
638 #if defined(QT_CONFIGURED_WITH_OPENGL)
639     toggleQGLWidgetViewport(m_windowOptions.useQGLWidgetViewport);
640 #endif
641 }
642
643 void LauncherWindow::setEditable(bool on)
644 {
645     page()->setContentEditable(on);
646     m_formatMenuAction->setVisible(on);
647 }
648
649 /*
650 void LauncherWindow::dumpPlugins() {
651     QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins();
652     foreach (const QWebPluginInfo plugin, plugins) {
653         qDebug() << "Plugin:" << plugin.name();
654         foreach (const QWebPluginInfo::MimeType mime, plugin.mimeTypes()) {
655             qDebug() << "   " << mime.name;
656         }
657     }
658 }
659 */
660
661 void LauncherWindow::dumpHtml()
662 {
663     qDebug() << "HTML: " << page()->mainFrame()->toHtml();
664 }
665
666 void LauncherWindow::selectElements()
667 {
668 #ifndef QT_NO_INPUTDIALOG
669     bool ok;
670     QString str = QInputDialog::getText(this, "Select elements", "Choose elements",
671                                         QLineEdit::Normal, "a", &ok);
672
673     if (ok && !str.isEmpty()) {
674         QWebElementCollection result =  page()->mainFrame()->findAllElements(str);
675         foreach (QWebElement e, result)
676             e.setStyleProperty("background-color", "yellow");
677 #ifndef Q_WS_MAEMO_5
678         statusBar()->showMessage(QString("%1 element(s) selected").arg(result.count()), 5000);
679 #endif
680     }
681 #endif
682 }
683
684 void LauncherWindow::setTouchMocking(bool on)
685 {
686     m_touchMocking = on;
687 }
688
689 void LauncherWindow::toggleWebView(bool graphicsBased)
690 {
691     m_windowOptions.useGraphicsView = graphicsBased;
692     initializeView();
693     menuBar()->clear();
694     createChrome();
695 }
696
697 void LauncherWindow::toggleAcceleratedCompositing(bool toggle)
698 {
699     m_windowOptions.useCompositing = toggle;
700     page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle);
701 }
702
703 void LauncherWindow::toggleTiledBackingStore(bool toggle)
704 {
705     page()->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, toggle);
706 }
707
708 void LauncherWindow::toggleResizesToContents(bool toggle)
709 {
710     m_windowOptions.resizesToContents = toggle;
711     static_cast<WebViewGraphicsBased*>(m_view)->setResizesToContents(toggle);
712 }
713
714 void LauncherWindow::toggleWebGL(bool toggle)
715 {
716     m_windowOptions.useWebGL = toggle;
717     page()->settings()->setAttribute(QWebSettings::WebGLEnabled, toggle);
718 }
719
720 void LauncherWindow::toggleThreadedQnam(bool toggle)
721 {
722     m_windowOptions.useThreadedQnam = toggle;
723     page()->setQnamThreaded(toggle);
724 }
725
726 void LauncherWindow::animatedFlip()
727 {
728     qobject_cast<WebViewGraphicsBased*>(m_view)->animatedFlip();
729 }
730
731 void LauncherWindow::animatedYFlip()
732 {
733     qobject_cast<WebViewGraphicsBased*>(m_view)->animatedYFlip();
734 }
735 void LauncherWindow::toggleSpatialNavigation(bool b)
736 {
737     page()->settings()->setAttribute(QWebSettings::SpatialNavigationEnabled, b);
738 }
739
740 void LauncherWindow::toggleFullScreenMode(bool enable)
741 {
742     if (enable)
743         setWindowState(Qt::WindowFullScreen);
744     else {
745 #if defined(Q_OS_SYMBIAN)
746         setWindowState(Qt::WindowMaximized);
747 #else
748         setWindowState(Qt::WindowNoState);
749 #endif
750     }
751 }
752
753 void LauncherWindow::toggleFrameFlattening(bool toggle)
754 {
755     m_windowOptions.useFrameFlattening = toggle;
756     page()->settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, toggle);
757 }
758
759 void LauncherWindow::toggleInterruptingJavaScriptEnabled(bool enable)
760 {
761     page()->setInterruptingJavaScriptEnabled(enable);
762 }
763
764 void LauncherWindow::toggleJavascriptCanOpenWindows(bool enable)
765 {
766     page()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, enable);
767 }
768
769 #if defined(QT_CONFIGURED_WITH_OPENGL)
770 void LauncherWindow::toggleQGLWidgetViewport(bool enable)
771 {
772     if (!isGraphicsBased())
773         return;
774
775     m_windowOptions.useQGLWidgetViewport = enable;
776     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
777
778     view->setViewport(enable ? new QGLWidget() : 0);
779 }
780 #endif
781
782 void LauncherWindow::changeViewportUpdateMode(int mode)
783 {
784     m_windowOptions.viewportUpdateMode = QGraphicsView::ViewportUpdateMode(mode);
785
786     if (!isGraphicsBased())
787         return;
788
789     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
790     view->setViewportUpdateMode(m_windowOptions.viewportUpdateMode);
791 }
792
793 void LauncherWindow::showFPS(bool enable)
794 {
795     if (!isGraphicsBased())
796         return;
797
798     m_windowOptions.showFrameRate = enable;
799     WebViewGraphicsBased* view = static_cast<WebViewGraphicsBased*>(m_view);
800     view->setFrameRateMeasurementEnabled(enable);
801
802     if (!enable) {
803 #if defined(Q_WS_MAEMO_5) && defined(Q_OS_SYMBIAN)
804         setWindowTitle("");
805 #else
806         statusBar()->clearMessage();
807 #endif
808     }
809 }
810
811 void LauncherWindow::showUserAgentDialog()
812 {
813     QStringList items;
814     QFile file(":/useragentlist.txt");
815     if (file.open(QIODevice::ReadOnly)) {
816          while (!file.atEnd())
817             items << file.readLine().trimmed();
818         file.close();
819     }
820
821     QSettings settings;
822     QString customUserAgent = settings.value("CustomUserAgent").toString();
823     if (!items.contains(customUserAgent) && !customUserAgent.isEmpty())
824         items << customUserAgent;
825
826     QDialog* dialog = new QDialog(this);
827     dialog->resize(size().width() * 0.7, dialog->size().height());
828     dialog->setMaximumHeight(dialog->size().height());
829     dialog->setWindowTitle("Change User Agent");
830
831     QVBoxLayout* layout = new QVBoxLayout(dialog);
832     dialog->setLayout(layout);
833
834 #ifndef QT_NO_COMBOBOX
835     QComboBox* combo = new QComboBox(dialog);
836     combo->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
837     combo->setEditable(true);
838     combo->insertItems(0, items);
839     layout->addWidget(combo);
840
841     int index = combo->findText(page()->userAgentForUrl(QUrl()));
842     combo->setCurrentIndex(index);
843 #endif
844
845     QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok
846             | QDialogButtonBox::Cancel, Qt::Horizontal, dialog);
847     connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
848     connect(buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
849     layout->addWidget(buttonBox);
850
851 #ifndef QT_NO_COMBOBOX
852     if (dialog->exec() && !combo->currentText().isEmpty()) {
853         page()->setUserAgent(combo->currentText());
854         if (!items.contains(combo->currentText()))
855             settings.setValue("CustomUserAgent", combo->currentText());
856     }
857 #endif
858
859     delete dialog;
860 }
861
862 void LauncherWindow::updateFPS(int fps)
863 {
864     QString fpsStatusText = QString("Current FPS: %1").arg(fps);
865
866 #if defined(Q_WS_MAEMO_5) && defined(Q_OS_SYMBIAN)
867     setWindowTitle(fpsStatusText);
868 #else
869     statusBar()->showMessage(fpsStatusText);
870 #endif
871 }
872
873 LauncherWindow* LauncherWindow::newWindow()
874 {
875     LauncherWindow* mw = new LauncherWindow(&m_windowOptions);
876     mw->show();
877     return mw;
878 }
879
880 LauncherWindow* LauncherWindow::cloneWindow()
881 {
882     LauncherWindow* mw = new LauncherWindow(&m_windowOptions, qobject_cast<QGraphicsView*>(m_view)->scene());
883     mw->show();
884     return mw;
885 }
886