1 /*
2 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3 * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
4 * Copyright (C) 2006 George Staikos <staikos@kde.org>
5 * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
6 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
7 * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
8 *
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
28 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <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
LauncherWindow(QString url)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
~LauncherWindow()182 LauncherWindow::~LauncherWindow()
183 {
184 grabZoomKeys(false);
185 }
186
keyPressEvent(QKeyEvent * event)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
grabZoomKeys(bool grab)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)
sendTouchEvent()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
eventFilter(QObject * obj,QEvent * event)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
loadStarted()315 void LauncherWindow::loadStarted()
316 {
317 m_view->setFocus(Qt::OtherFocusReason);
318 }
319
loadFinished()320 void LauncherWindow::loadFinished()
321 {
322 QUrl url = page()->mainFrame()->url();
323 setAddressUrl(url.toString());
324 addCompleterEntry(url);
325 }
326
showLinkHover(const QString & link,const QString & toolTip)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
zoomIn()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
zoomOut()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
resetZoom()358 void LauncherWindow::resetZoom()
359 {
360 currentZoom = 100;
361 page()->mainFrame()->setZoomFactor(1.0);
362 }
363
toggleZoomTextOnly(bool b)364 void LauncherWindow::toggleZoomTextOnly(bool b)
365 {
366 page()->settings()->setAttribute(QWebSettings::ZoomTextOnly, b);
367 }
368
print()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
screenshot()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
setEditable(bool on)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
dumpHtml()413 void LauncherWindow::dumpHtml()
414 {
415 qDebug() << "HTML: " << page()->mainFrame()->toHtml();
416 }
417
selectElements()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
setTouchMocking(bool on)434 void LauncherWindow::setTouchMocking(bool on)
435 {
436 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
437 touchMocking = on;
438 #endif
439 }
440
toggleAcceleratedCompositing(bool toggle)441 void LauncherWindow::toggleAcceleratedCompositing(bool toggle)
442 {
443 page()->settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, toggle);
444 }
445
initializeView(bool useGraphicsView)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
newWindow(const QString & url)473 void LauncherWindow::newWindow(const QString& url)
474 {
475 LauncherWindow* mw = new LauncherWindow(url);
476 mw->show();
477 }
478
setupUI()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
createWindow(QWebPage::WebWindowType type)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
createPlugin(const QString & classId,const QUrl &,const QStringList &,const QStringList &)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
launcherMain(const QApplication & app)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);
urls() const596 QStringList urls() const { return m_urls; }
isRobotized() const597 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
applyDefaultSettings()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
LauncherApplication(int & argc,char ** argv)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
requiresGraphicsView(const QString & option)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
handleUserOptions()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
main(int argc,char ** argv)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