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