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