1 /* 2 * Copyright (C) 2009 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 <QtGui> 34 #include <QtNetwork/QNetworkRequest> 35 #if !defined(QT_NO_PRINTER) 36 #include <QPrintPreviewDialog> 37 #endif 38 39 #ifndef QT_NO_UITOOLS 40 #include <QtUiTools/QUiLoader> 41 #endif 42 43 #include <QDebug> 44 45 #include <cstdio> 46 #include "mainwindow.h" 47 #include <qevent.h> 48 #include <qwebelement.h> 49 #include <qwebframe.h> 50 #include <qwebinspector.h> 51 #include <qwebsettings.h> 52 53 #ifdef Q_WS_MAEMO_5 54 #include <qx11info_x11.h> 55 #endif 56 57 #include "urlloader.h" 58 #include "utils.h" 59 #include "webinspector.h" 60 #include "webpage.h" 61 #include "webview.h" 62 63 #ifdef Q_WS_MAEMO_5 64 #include <X11/Xatom.h> 65 #include <X11/Xlib.h> 66 #undef KeyPress 67 #endif 68 69 #ifndef NDEBUG 70 void QWEBKIT_EXPORT qt_drt_garbageCollector_collect(); 71 #endif 72 73 74 static bool gUseGraphicsView = false; 75 static bool gUseCompositing = false; 76 static bool gCacheWebView = false; 77 static bool gShowFrameRate = false; 78 static QGraphicsView::ViewportUpdateMode gViewportUpdateMode = QGraphicsView::MinimalViewportUpdate; 79 80 81 class LauncherWindow : public MainWindow { 82 Q_OBJECT 83 84 public: 85 LauncherWindow(QString url = QString()); 86 virtual ~LauncherWindow(); 87 88 virtual void keyPressEvent(QKeyEvent* event); 89 void grabZoomKeys(bool grab); 90 91 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 92 void sendTouchEvent(); 93 bool eventFilter(QObject* obj, QEvent* event); 94 #endif 95 96 protected slots: 97 void loadStarted(); 98 void loadFinished(); 99 100 void showLinkHover(const QString &link, const QString &toolTip); 101 102 void zoomIn(); 103 void zoomOut(); 104 void resetZoom(); 105 void toggleZoomTextOnly(bool on); 106 107 void print(); 108 void screenshot(); 109 110 void setEditable(bool on); 111 112 /* void dumpPlugins() */ 113 void dumpHtml(); 114 115 void selectElements(); 116 117 void setTouchMocking(bool on); 118 void toggleAcceleratedCompositing(bool toggle); 119 void initializeView(bool useGraphicsView = false); 120 121 public slots: 122 void newWindow(const QString& url = QString()); 123 124 private: 125 // create the status bar, tool bar & menu 126 void setupUI(); 127 128 private: 129 QVector<int> zoomLevels; 130 int currentZoom; 131 132 QWidget* m_view; 133 WebInspector* inspector; 134 135 QAction* formatMenuAction; 136 137 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 138 QList<QTouchEvent::TouchPoint> touchPoints; 139 bool touchMocking; 140 #endif 141 }; 142 143 144 LauncherWindow::LauncherWindow(QString url) 145 : MainWindow(url) 146 , currentZoom(100) 147 { 148 QSplitter* splitter = new QSplitter(Qt::Vertical, this); 149 setCentralWidget(splitter); 150 151 #if defined(Q_WS_S60) 152 showMaximized(); 153 #else 154 resize(800, 600); 155 #endif 156 157 m_view = 0; 158 initializeView(); 159 160 connect(page(), SIGNAL(loadStarted()), this, SLOT(loadStarted())); 161 connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished())); 162 connect(page(), SIGNAL(linkHovered(const QString&, const QString&, const QString&)), 163 this, SLOT(showLinkHover(const QString&, const QString&))); 164 165 inspector = new WebInspector(splitter); 166 inspector->setPage(page()); 167 inspector->hide(); 168 connect(this, SIGNAL(destroyed()), inspector, SLOT(deleteLater())); 169 170 setupUI(); 171 172 // the zoom values are chosen to be like in Mozilla Firefox 3 173 zoomLevels << 30 << 50 << 67 << 80 << 90; 174 zoomLevels << 100; 175 zoomLevels << 110 << 120 << 133 << 150 << 170 << 200 << 240 << 300; 176 177 grabZoomKeys(true); 178 179 load(url); 180 } 181 182 LauncherWindow::~LauncherWindow() 183 { 184 grabZoomKeys(false); 185 } 186 187 void LauncherWindow::keyPressEvent(QKeyEvent* event) 188 { 189 #ifdef Q_WS_MAEMO_5 190 switch (event->key()) { 191 case Qt::Key_F7: 192 zoomIn(); 193 event->accept(); 194 break; 195 case Qt::Key_F8: 196 zoomOut(); 197 event->accept(); 198 break; 199 } 200 #endif 201 MainWindow::keyPressEvent(event); 202 } 203 204 void LauncherWindow::grabZoomKeys(bool grab) 205 { 206 #ifdef Q_WS_MAEMO_5 207 if (!winId()) { 208 qWarning("Can't grab keys unless we have a window id"); 209 return; 210 } 211 212 Atom atom = XInternAtom(QX11Info::display(), "_HILDON_ZOOM_KEY_ATOM", False); 213 if (!atom) { 214 qWarning("Unable to obtain _HILDON_ZOOM_KEY_ATOM"); 215 return; 216 } 217 218 unsigned long val = (grab) ? 1 : 0; 219 XChangeProperty(QX11Info::display(), winId(), atom, XA_INTEGER, 32, PropModeReplace, reinterpret_cast<unsigned char*>(&val), 1); 220 #endif 221 } 222 223 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 224 void LauncherWindow::sendTouchEvent() 225 { 226 if (touchPoints.isEmpty()) 227 return; 228 229 QEvent::Type type = QEvent::TouchUpdate; 230 if (touchPoints.size() == 1) { 231 if (touchPoints[0].state() == Qt::TouchPointReleased) 232 type = QEvent::TouchEnd; 233 else if (touchPoints[0].state() == Qt::TouchPointPressed) 234 type = QEvent::TouchBegin; 235 } 236 237 QTouchEvent touchEv(type); 238 touchEv.setTouchPoints(touchPoints); 239 QCoreApplication::sendEvent(page(), &touchEv); 240 241 // After sending the event, remove all touchpoints that were released 242 if (touchPoints[0].state() == Qt::TouchPointReleased) 243 touchPoints.removeAt(0); 244 if (touchPoints.size() > 1 && touchPoints[1].state() == Qt::TouchPointReleased) 245 touchPoints.removeAt(1); 246 } 247 248 bool LauncherWindow::eventFilter(QObject* obj, QEvent* event) 249 { 250 if (!touchMocking || obj != m_view) 251 return QObject::eventFilter(obj, event); 252 253 if (event->type() == QEvent::MouseButtonPress 254 || event->type() == QEvent::MouseButtonRelease 255 || event->type() == QEvent::MouseButtonDblClick 256 || event->type() == QEvent::MouseMove) { 257 258 QMouseEvent* ev = static_cast<QMouseEvent*>(event); 259 if (ev->type() == QEvent::MouseMove 260 && !(ev->buttons() & Qt::LeftButton)) 261 return false; 262 263 QTouchEvent::TouchPoint touchPoint; 264 touchPoint.setState(Qt::TouchPointMoved); 265 if ((ev->type() == QEvent::MouseButtonPress 266 || ev->type() == QEvent::MouseButtonDblClick)) 267 touchPoint.setState(Qt::TouchPointPressed); 268 else if (ev->type() == QEvent::MouseButtonRelease) 269 touchPoint.setState(Qt::TouchPointReleased); 270 271 touchPoint.setId(0); 272 touchPoint.setScreenPos(ev->globalPos()); 273 touchPoint.setPos(ev->pos()); 274 touchPoint.setPressure(1); 275 276 // If the point already exists, update it. Otherwise create it. 277 if (touchPoints.size() > 0 && !touchPoints[0].id()) 278 touchPoints[0] = touchPoint; 279 else if (touchPoints.size() > 1 && !touchPoints[1].id()) 280 touchPoints[1] = touchPoint; 281 else 282 touchPoints.append(touchPoint); 283 284 sendTouchEvent(); 285 } else if (event->type() == QEvent::KeyPress 286 && static_cast<QKeyEvent*>(event)->key() == Qt::Key_F 287 && static_cast<QKeyEvent*>(event)->modifiers() == Qt::ControlModifier) { 288 289 // If the keyboard point is already pressed, release it. 290 // Otherwise create it and append to touchPoints. 291 if (touchPoints.size() > 0 && touchPoints[0].id() == 1) { 292 touchPoints[0].setState(Qt::TouchPointReleased); 293 sendTouchEvent(); 294 } else if (touchPoints.size() > 1 && touchPoints[1].id() == 1) { 295 touchPoints[1].setState(Qt::TouchPointReleased); 296 sendTouchEvent(); 297 } else { 298 QTouchEvent::TouchPoint touchPoint; 299 touchPoint.setState(Qt::TouchPointPressed); 300 touchPoint.setId(1); 301 touchPoint.setScreenPos(QCursor::pos()); 302 touchPoint.setPos(m_view->mapFromGlobal(QCursor::pos())); 303 touchPoint.setPressure(1); 304 touchPoints.append(touchPoint); 305 sendTouchEvent(); 306 307 // After sending the event, change the touchpoint state to stationary 308 touchPoints.last().setState(Qt::TouchPointStationary); 309 } 310 } 311 return false; 312 } 313 #endif // QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 314 315 void LauncherWindow::loadStarted() 316 { 317 m_view->setFocus(Qt::OtherFocusReason); 318 } 319 320 void LauncherWindow::loadFinished() 321 { 322 QUrl url = page()->mainFrame()->url(); 323 setAddressUrl(url.toString()); 324 addCompleterEntry(url); 325 } 326 327 void LauncherWindow::showLinkHover(const QString &link, const QString &toolTip) 328 { 329 #ifndef Q_WS_MAEMO_5 330 statusBar()->showMessage(link); 331 #endif 332 #ifndef QT_NO_TOOLTIP 333 if (!toolTip.isEmpty()) 334 QToolTip::showText(QCursor::pos(), toolTip); 335 #endif 336 } 337 338 void LauncherWindow::zoomIn() 339 { 340 int i = zoomLevels.indexOf(currentZoom); 341 Q_ASSERT(i >= 0); 342 if (i < zoomLevels.count() - 1) 343 currentZoom = zoomLevels[i + 1]; 344 345 page()->mainFrame()->setZoomFactor(qreal(currentZoom) / 100.0); 346 } 347 348 void LauncherWindow::zoomOut() 349 { 350 int i = zoomLevels.indexOf(currentZoom); 351 Q_ASSERT(i >= 0); 352 if (i > 0) 353 currentZoom = zoomLevels[i - 1]; 354 355 page()->mainFrame()->setZoomFactor(qreal(currentZoom) / 100.0); 356 } 357 358 void LauncherWindow::resetZoom() 359 { 360 currentZoom = 100; 361 page()->mainFrame()->setZoomFactor(1.0); 362 } 363 364 void LauncherWindow::toggleZoomTextOnly(bool b) 365 { 366 page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b); 367 } 368 369 void LauncherWindow::print() 370 { 371 #if !defined(QT_NO_PRINTER) 372 QPrintPreviewDialog dlg(this); 373 connect(&dlg, SIGNAL(paintRequested(QPrinter*)), 374 m_view, SLOT(print(QPrinter*))); 375 dlg.exec(); 376 #endif 377 } 378 379 void LauncherWindow::screenshot() 380 { 381 QPixmap pixmap = QPixmap::grabWidget(m_view); 382 QLabel* label = new QLabel; 383 label->setAttribute(Qt::WA_DeleteOnClose); 384 label->setWindowTitle("Screenshot - Preview"); 385 label->setPixmap(pixmap); 386 label->show(); 387 388 QString fileName = QFileDialog::getSaveFileName(label, "Screenshot"); 389 if (!fileName.isEmpty()) { 390 pixmap.save(fileName, "png"); 391 label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName)); 392 } 393 } 394 395 void LauncherWindow::setEditable(bool on) 396 { 397 page()->setContentEditable(on); 398 formatMenuAction->setVisible(on); 399 } 400 401 /* 402 void LauncherWindow::dumpPlugins() { 403 QList<QWebPluginInfo> plugins = QWebSettings::pluginDatabase()->plugins(); 404 foreach (const QWebPluginInfo plugin, plugins) { 405 qDebug() << "Plugin:" << plugin.name(); 406 foreach (const QWebPluginInfo::MimeType mime, plugin.mimeTypes()) { 407 qDebug() << " " << mime.name; 408 } 409 } 410 } 411 */ 412 413 void LauncherWindow::dumpHtml() 414 { 415 qDebug() << "HTML: " << page()->mainFrame()->toHtml(); 416 } 417 418 void LauncherWindow::selectElements() 419 { 420 bool ok; 421 QString str = QInputDialog::getText(this, "Select elements", "Choose elements", 422 QLineEdit::Normal, "a", &ok); 423 424 if (ok && !str.isEmpty()) { 425 QWebElementCollection result = page()->mainFrame()->findAllElements(str); 426 foreach (QWebElement e, result) 427 e.setStyleProperty("background-color", "yellow"); 428 #ifndef Q_WS_MAEMO_5 429 statusBar()->showMessage(QString("%1 element(s) selected").arg(result.count()), 5000); 430 #endif 431 } 432 } 433 434 void LauncherWindow::setTouchMocking(bool on) 435 { 436 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 437 touchMocking = on; 438 #endif 439 } 440 441 void LauncherWindow::toggleAcceleratedCompositing(bool toggle) 442 { 443 page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle); 444 } 445 446 void LauncherWindow::initializeView(bool useGraphicsView) 447 { 448 delete m_view; 449 450 QSplitter* splitter = static_cast<QSplitter*>(centralWidget()); 451 452 if (!useGraphicsView) { 453 WebViewTraditional* view = new WebViewTraditional(splitter); 454 view->setPage(page()); 455 m_view = view; 456 } else { 457 WebViewGraphicsBased* view = new WebViewGraphicsBased(splitter); 458 view->setPage(page()); 459 view->setViewportUpdateMode(gViewportUpdateMode); 460 view->setItemCacheMode(gCacheWebView ? QGraphicsItem::DeviceCoordinateCache : QGraphicsItem::NoCache); 461 if (gShowFrameRate) 462 view->enableFrameRateMeasurement(); 463 page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, gUseCompositing); 464 m_view = view; 465 } 466 467 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 468 m_view->installEventFilter(this); 469 touchMocking = false; 470 #endif 471 } 472 473 void LauncherWindow::newWindow(const QString& url) 474 { 475 LauncherWindow* mw = new LauncherWindow(url); 476 mw->show(); 477 } 478 479 void LauncherWindow::setupUI() 480 { 481 QMenu* fileMenu = menuBar()->addMenu("&File"); 482 fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New); 483 fileMenu->addAction(tr("Open File..."), this, SLOT(openFile()), QKeySequence::Open); 484 fileMenu->addAction("Close Window", this, SLOT(close()), QKeySequence::Close); 485 fileMenu->addSeparator(); 486 fileMenu->addAction("Take Screen Shot...", this, SLOT(screenshot())); 487 fileMenu->addAction(tr("Print..."), this, SLOT(print()), QKeySequence::Print); 488 fileMenu->addSeparator(); 489 fileMenu->addAction("Quit", QApplication::instance(), SLOT(closeAllWindows()), QKeySequence(Qt::CTRL | Qt::Key_Q)); 490 491 QMenu* editMenu = menuBar()->addMenu("&Edit"); 492 editMenu->addAction(page()->action(QWebPage::Undo)); 493 editMenu->addAction(page()->action(QWebPage::Redo)); 494 editMenu->addSeparator(); 495 editMenu->addAction(page()->action(QWebPage::Cut)); 496 editMenu->addAction(page()->action(QWebPage::Copy)); 497 editMenu->addAction(page()->action(QWebPage::Paste)); 498 editMenu->addSeparator(); 499 QAction* setEditable = editMenu->addAction("Set Editable", this, SLOT(setEditable(bool))); 500 setEditable->setCheckable(true); 501 502 QMenu* viewMenu = menuBar()->addMenu("&View"); 503 viewMenu->addAction(page()->action(QWebPage::Stop)); 504 viewMenu->addAction(page()->action(QWebPage::Reload)); 505 viewMenu->addSeparator(); 506 QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn())); 507 QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut())); 508 QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom())); 509 QAction* zoomTextOnly = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool))); 510 zoomTextOnly->setCheckable(true); 511 zoomTextOnly->setChecked(false); 512 viewMenu->addSeparator(); 513 viewMenu->addAction("Dump HTML", this, SLOT(dumpHtml())); 514 // viewMenu->addAction("Dump plugins", this, SLOT(dumpPlugins())); 515 516 QMenu* formatMenu = new QMenu("F&ormat", this); 517 formatMenuAction = menuBar()->addMenu(formatMenu); 518 formatMenuAction->setVisible(false); 519 formatMenu->addAction(page()->action(QWebPage::ToggleBold)); 520 formatMenu->addAction(page()->action(QWebPage::ToggleItalic)); 521 formatMenu->addAction(page()->action(QWebPage::ToggleUnderline)); 522 QMenu* writingMenu = formatMenu->addMenu(tr("Writing Direction")); 523 writingMenu->addAction(page()->action(QWebPage::SetTextDirectionDefault)); 524 writingMenu->addAction(page()->action(QWebPage::SetTextDirectionLeftToRight)); 525 writingMenu->addAction(page()->action(QWebPage::SetTextDirectionRightToLeft)); 526 527 zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); 528 zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); 529 resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); 530 531 QMenu* toolsMenu = menuBar()->addMenu("&Develop"); 532 toolsMenu->addAction("Select Elements...", this, SLOT(selectElements())); 533 QAction* showInspectorAction = toolsMenu->addAction("Show Web Inspector", inspector, SLOT(setVisible(bool)), QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I)); 534 showInspectorAction->setCheckable(true); 535 showInspectorAction->connect(inspector, SIGNAL(visibleChanged(bool)), SLOT(setChecked(bool))); 536 537 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0) 538 QAction* touchMockAction = toolsMenu->addAction("Toggle multitouch mocking", this, SLOT(setTouchMocking(bool))); 539 touchMockAction->setCheckable(true); 540 touchMockAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_T)); 541 #endif 542 543 QAction* toggleAcceleratedCompositing = toolsMenu->addAction("Toggle Accelerated Compositing", this, SLOT(toggleAcceleratedCompositing(bool))); 544 toggleAcceleratedCompositing->setCheckable(true); 545 toggleAcceleratedCompositing->setChecked(false); 546 547 QAction* toggleGraphicsView = toolsMenu->addAction("Toggle use of QGraphicsView", this, SLOT(initializeView(bool))); 548 toggleGraphicsView->setCheckable(true); 549 toggleGraphicsView->setChecked(false); 550 } 551 552 QWebPage* WebPage::createWindow(QWebPage::WebWindowType type) 553 { 554 LauncherWindow* mw = new LauncherWindow; 555 if (type == WebModalDialog) 556 mw->setWindowModality(Qt::ApplicationModal); 557 mw->show(); 558 return mw->page(); 559 } 560 561 QObject* WebPage::createPlugin(const QString &classId, const QUrl&, const QStringList&, const QStringList&) 562 { 563 if (classId == "alien_QLabel") { 564 QLabel* l = new QLabel; 565 l->winId(); 566 return l; 567 } 568 569 #ifndef QT_NO_UITOOLS 570 QUiLoader loader; 571 return loader.createWidget(classId, view()); 572 #else 573 Q_UNUSED(classId); 574 return 0; 575 #endif 576 } 577 578 579 int launcherMain(const QApplication& app) 580 { 581 #ifndef NDEBUG 582 int retVal = app.exec(); 583 qt_drt_garbageCollector_collect(); 584 QWebSettings::clearMemoryCaches(); 585 return retVal; 586 #else 587 return app.exec(); 588 #endif 589 } 590 591 class LauncherApplication : public QApplication { 592 Q_OBJECT 593 594 public: 595 LauncherApplication(int& argc, char** argv); 596 QStringList urls() const { return m_urls; } 597 bool isRobotized() const { return m_isRobotized; } 598 599 private: 600 void handleUserOptions(); 601 void applyDefaultSettings(); 602 603 private: 604 bool m_isRobotized; 605 QStringList m_urls; 606 }; 607 608 void LauncherApplication::applyDefaultSettings() 609 { 610 QWebSettings::setMaximumPagesInCache(4); 611 612 QWebSettings::setObjectCacheCapacities((16*1024*1024) / 8, (16*1024*1024) / 8, 16*1024*1024); 613 614 QWebSettings::globalSettings()->setAttribute(QWebSettings::PluginsEnabled, true); 615 QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); 616 QWebSettings::enablePersistentStorage(); 617 } 618 619 LauncherApplication::LauncherApplication(int& argc, char** argv) 620 : QApplication(argc, argv) 621 , m_isRobotized(false) 622 { 623 // To allow QWebInspector's configuration persistence 624 setOrganizationName("Nokia"); 625 setApplicationName("QtLauncher"); 626 setApplicationVersion("0.1"); 627 628 applyDefaultSettings(); 629 630 handleUserOptions(); 631 } 632 633 static void requiresGraphicsView(const QString& option) 634 { 635 if (gUseGraphicsView) 636 return; 637 appQuit(1, QString("%1 only works in combination with the -graphicsbased option").arg(option)); 638 } 639 640 void LauncherApplication::handleUserOptions() 641 { 642 QStringList args = arguments(); 643 QFileInfo program(args.at(0)); 644 QString programName("QtLauncher"); 645 if (program.exists()) 646 programName = program.baseName(); 647 648 QList<QString> updateModes(enumToKeys(QGraphicsView::staticMetaObject, 649 "ViewportUpdateMode", "ViewportUpdate")); 650 651 if (args.contains("-help")) { 652 qDebug() << "Usage:" << programName.toLatin1().data() 653 << "[-graphicsbased]" 654 << "[-compositing]" 655 << QString("[-viewport-update-mode %1]").arg(formatKeys(updateModes)).toLatin1().data() 656 << "[-cache-webview]" 657 << "[-show-fps]" 658 << "[-r list]" 659 << "URLs"; 660 appQuit(0); 661 } 662 663 if (args.contains("-graphicsbased")) 664 gUseGraphicsView = true; 665 666 if (args.contains("-compositing")) { 667 requiresGraphicsView("-compositing"); 668 gUseCompositing = true; 669 } 670 671 if (args.contains("-show-fps")) { 672 requiresGraphicsView("-show-fps"); 673 gShowFrameRate = true; 674 } 675 676 if (args.contains("-cache-webview")) { 677 requiresGraphicsView("-cache-webview"); 678 gCacheWebView = true; 679 } 680 681 QString arg1("-viewport-update-mode"); 682 int modeIndex = args.indexOf(arg1); 683 if (modeIndex != -1) { 684 requiresGraphicsView(arg1); 685 686 QString mode = takeOptionValue(&args, modeIndex); 687 if (mode.isEmpty()) 688 appQuit(1, QString("%1 needs a value of one of [%2]").arg(arg1).arg(formatKeys(updateModes))); 689 int idx = updateModes.indexOf(mode); 690 if (idx == -1) 691 appQuit(1, QString("%1 value has to be one of [%2]").arg(arg1).arg(formatKeys(updateModes))); 692 693 gViewportUpdateMode = static_cast<QGraphicsView::ViewportUpdateMode>(idx); 694 } 695 696 int robotIndex = args.indexOf("-r"); 697 if (robotIndex != -1) { 698 QString listFile = takeOptionValue(&args, robotIndex); 699 if (listFile.isEmpty()) 700 appQuit(1, "-r needs a list file to start in robotized mode"); 701 if (!QFile::exists(listFile)) 702 appQuit(1, "The list file supplied to -r does not exist."); 703 704 m_isRobotized = true; 705 m_urls = QStringList(listFile); 706 return; 707 } 708 709 int lastArg = args.lastIndexOf(QRegExp("^-.*")); 710 m_urls = (lastArg != -1) ? args.mid(++lastArg) : args.mid(1); 711 } 712 713 714 int main(int argc, char **argv) 715 { 716 LauncherApplication app(argc, argv); 717 718 if (app.isRobotized()) { 719 LauncherWindow* window = new LauncherWindow(); 720 UrlLoader loader(window->page()->mainFrame(), app.urls().at(0)); 721 QObject::connect(window->page()->mainFrame(), SIGNAL(loadFinished(bool)), &loader, SLOT(loadNext())); 722 loader.loadNext(); 723 window->show(); 724 return launcherMain(app); 725 } 726 727 QStringList urls = app.urls(); 728 729 if (urls.isEmpty()) { 730 QString defaultUrl = QString("file://%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html")); 731 if (QDir(defaultUrl).exists()) 732 urls.append(defaultUrl); 733 else 734 urls.append(""); 735 } 736 737 LauncherWindow* window = 0; 738 foreach (QString url, urls) { 739 if (!window) 740 window = new LauncherWindow(url); 741 else 742 window->newWindow(url); 743 } 744 745 window->show(); 746 return launcherMain(app); 747 } 748 749 #include "main.moc" 750