Home | History | Annotate | Download | only in QtTestBrowser
      1 /*
      2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
      3  * Copyright (C) 2009 Girish Ramakrishnan <girish (at) forwardbias.in>
      4  * Copyright (C) 2006 George Staikos <staikos (at) kde.org>
      5  * Copyright (C) 2006 Dirk Mueller <mueller (at) kde.org>
      6  * Copyright (C) 2006 Zack Rusin <zack (at) kde.org>
      7  * Copyright (C) 2006 Simon Hausmann <hausmann (at) kde.org>
      8  *
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     28  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include "launcherwindow.h"
     34 #include "urlloader.h"
     35 
     36 const int gExitClickArea = 80;
     37 QVector<int> LauncherWindow::m_zoomLevels;
     38 
     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 
     58 LauncherWindow::~LauncherWindow()
     59 {
     60     grabZoomKeys(false);
     61     delete m_urlLoader;
     62 }
     63 
     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 
     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 
    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 
    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 
    412 bool LauncherWindow::isGraphicsBased() const
    413 {
    414     return bool(qobject_cast<QGraphicsView*>(m_view));
    415 }
    416 
    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 
    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 
    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 
    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 
    556 void LauncherWindow::loadStarted()
    557 {
    558     m_view->setFocus(Qt::OtherFocusReason);
    559 }
    560 
    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 
    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 
    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 
    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 
    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 
    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 
    636 void LauncherWindow::resetZoom()
    637 {
    638     m_currentZoom = 100;
    639     applyZoom();
    640 }
    641 
    642 void LauncherWindow::toggleZoomTextOnly(bool b)
    643 {
    644     page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b);
    645 }
    646 
    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 
    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 
    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 
    701 void LauncherWindow::dumpHtml()
    702 {
    703     qDebug() << "HTML: " << page()->mainFrame()->toHtml();
    704 }
    705 
    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 
    724 void LauncherWindow::setTouchMocking(bool on)
    725 {
    726     m_touchMocking = on;
    727 }
    728 
    729 void LauncherWindow::toggleWebView(bool graphicsBased)
    730 {
    731     m_windowOptions.useGraphicsView = graphicsBased;
    732     initializeView();
    733     menuBar()->clear();
    734     createChrome();
    735 }
    736 
    737 void LauncherWindow::toggleAcceleratedCompositing(bool toggle)
    738 {
    739     m_windowOptions.useCompositing = toggle;
    740     page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle);
    741 }
    742 
    743 void LauncherWindow::toggleTiledBackingStore(bool toggle)
    744 {
    745     page()->settings()->setAttribute(QWebSettings::TiledBackingStoreEnabled, toggle);
    746 }
    747 
    748 void LauncherWindow::toggleResizesToContents(bool toggle)
    749 {
    750     m_windowOptions.resizesToContents = toggle;
    751     static_cast<WebViewGraphicsBased*>(m_view)->setResizesToContents(toggle);
    752 }
    753 
    754 void LauncherWindow::toggleWebGL(bool toggle)
    755 {
    756     m_windowOptions.useWebGL = toggle;
    757     page()->settings()->setAttribute(QWebSettings::WebGLEnabled, toggle);
    758 }
    759 
    760 void LauncherWindow::animatedFlip()
    761 {
    762     qobject_cast<WebViewGraphicsBased*>(m_view)->animatedFlip();
    763 }
    764 
    765 void LauncherWindow::animatedYFlip()
    766 {
    767     qobject_cast<WebViewGraphicsBased*>(m_view)->animatedYFlip();
    768 }
    769 void LauncherWindow::toggleSpatialNavigation(bool b)
    770 {
    771     page()->settings()->setAttribute(QWebSettings::SpatialNavigationEnabled, b);
    772 }
    773 
    774 void LauncherWindow::toggleFullScreenMode(bool enable)
    775 {
    776     bool alreadyEnabled = windowState() & Qt::WindowFullScreen;
    777     if (enable ^ alreadyEnabled)
    778         setWindowState(windowState() ^ Qt::WindowFullScreen);
    779 }
    780 
    781 void LauncherWindow::toggleFrameFlattening(bool toggle)
    782 {
    783     m_windowOptions.useFrameFlattening = toggle;
    784     page()->settings()->setAttribute(QWebSettings::FrameFlatteningEnabled, toggle);
    785 }
    786 
    787 void LauncherWindow::toggleInterruptingJavaScriptEnabled(bool enable)
    788 {
    789     page()->setInterruptingJavaScriptEnabled(enable);
    790 }
    791 
    792 void LauncherWindow::toggleJavascriptCanOpenWindows(bool enable)
    793 {
    794     page()->settings()->setAttribute(QWebSettings::JavascriptCanOpenWindows, enable);
    795 }
    796 
    797 void LauncherWindow::toggleAutoLoadImages(bool enable)
    798 {
    799     page()->settings()->setAttribute(QWebSettings::AutoLoadImages, !enable);
    800 }
    801 
    802 void LauncherWindow::togglePlugins(bool enable)
    803 {
    804     page()->settings()->setAttribute(QWebSettings::PluginsEnabled, !enable);
    805 }
    806 
    807 #if defined(QT_CONFIGURED_WITH_OPENGL)
    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 
    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 
    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 
    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 
    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 
    914 void LauncherWindow::printURL(const QUrl& url)
    915 {
    916     QTextStream output(stdout);
    917     output << "Loaded: " << url.toString() << endl;
    918 }
    919 
    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 
    931 void LauncherWindow::toggleLocalStorage(bool toggle)
    932 {
    933     m_windowOptions.useLocalStorage = toggle;
    934     page()->settings()->setAttribute(QWebSettings::LocalStorageEnabled, toggle);
    935 }
    936 
    937 void LauncherWindow::toggleOfflineStorageDatabase(bool toggle)
    938 {
    939     m_windowOptions.useOfflineStorageDatabase = toggle;
    940     page()->settings()->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled, toggle);
    941 }
    942 
    943 void LauncherWindow::toggleOfflineWebApplicationCache(bool toggle)
    944 {
    945     m_windowOptions.useOfflineWebApplicationCache = toggle;
    946     page()->settings()->setAttribute(QWebSettings::OfflineWebApplicationCacheEnabled, toggle);
    947 }
    948 
    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 
    965 LauncherWindow* LauncherWindow::newWindow()
    966 {
    967     LauncherWindow* mw = new LauncherWindow(&m_windowOptions);
    968     mw->show();
    969     return mw;
    970 }
    971 
    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