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