diff options
Diffstat (limited to 'Tools/MiniBrowser')
-rw-r--r-- | Tools/MiniBrowser/DerivedSources.pro | 7 | ||||
-rw-r--r-- | Tools/MiniBrowser/mac/BrowserWindowController.m | 9 | ||||
-rw-r--r-- | Tools/MiniBrowser/mac/WebBundle/WebBundleMain.m | 2 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/BrowserView.cpp | 5 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/BrowserView.h | 1 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/BrowserWindow.cpp | 259 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/BrowserWindow.h | 34 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/MiniBrowser.pro | 14 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/MiniBrowserApplication.cpp | 95 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/MiniBrowserApplication.h | 68 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/UrlLoader.cpp | 129 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/UrlLoader.h | 71 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/main.cpp | 44 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/utils.cpp | 86 | ||||
-rw-r--r-- | Tools/MiniBrowser/qt/utils.h | 53 |
15 files changed, 796 insertions, 81 deletions
diff --git a/Tools/MiniBrowser/DerivedSources.pro b/Tools/MiniBrowser/DerivedSources.pro index 3ca89ad..8674beb 100644 --- a/Tools/MiniBrowser/DerivedSources.pro +++ b/Tools/MiniBrowser/DerivedSources.pro @@ -7,12 +7,13 @@ TARGET = dummy QMAKE_EXTRA_TARGETS += generated_files +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../.. SRC_ROOT_DIR = $$replace(PWD, "/Tools/MiniBrowser", "") -!exists($$OUTPUT_DIR/Tools/MiniBrowser/qt):system($$QMAKE_MKDIR $$OUTPUT_DIR/Tools/MiniBrowser/qt) +!exists($$OUTPUT_DIR/MiniBrowser/qt): system($$QMAKE_MKDIR $$OUTPUT_DIR/MiniBrowser/qt) ualist_copier.input = $$SRC_ROOT_DIR/Tools/QtTestBrowser/useragentlist.txt -ualist_copier.output = $$OUTPUT_DIR/Tools/MiniBrowser/qt/useragentlist.txt +ualist_copier.output = $$OUTPUT_DIR/MiniBrowser/qt/useragentlist.txt ualist_copier.tempNames = $$ualist_copier.input $$ualist_copier.output ualist_copier.commands = $$QMAKE_COPY $$replace(ualist_copier.tempNames, "/", $$QMAKE_DIR_SEP) ualist_copier.depends = $$ualist_copier.input @@ -24,7 +25,7 @@ QMAKE_EXTRA_TARGETS += ualist_copier # polluting the source tree. qrc_copier.input = $$SRC_ROOT_DIR/Tools/MiniBrowser/MiniBrowser.qrc -qrc_copier.output = $$OUTPUT_DIR/Tools/MiniBrowser/qt/MiniBrowser.qrc +qrc_copier.output = $$OUTPUT_DIR/MiniBrowser/qt/MiniBrowser.qrc qrc_copier.tempNames = $$qrc_copier.input $$qrc_copier.output qrc_copier.commands = $$QMAKE_COPY $$replace(qrc_copier.tempNames, "/", $$QMAKE_DIR_SEP) qrc_copier.depends = ualist_copier $$qrc_copier.input diff --git a/Tools/MiniBrowser/mac/BrowserWindowController.m b/Tools/MiniBrowser/mac/BrowserWindowController.m index 3a1ffbd..fd6f2e0 100644 --- a/Tools/MiniBrowser/mac/BrowserWindowController.m +++ b/Tools/MiniBrowser/mac/BrowserWindowController.m @@ -351,26 +351,26 @@ static void processDidExit(WKPageRef page, const void *clientInfo) LOG(@"processDidExit"); } -static void didChangeBackForwardList(WKPageRef page, const void *clientInfo) +static void didChangeBackForwardList(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void *clientInfo) { [(BrowserWindowController *)clientInfo validateToolbar]; } // MARK: Policy Client Callbacks -static void decidePolicyForNavigationAction(WKPageRef page, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void *clientInfo) +static void decidePolicyForNavigationAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) { LOG(@"decidePolicyForNavigationAction"); WKFramePolicyListenerUse(listener); } -static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void *clientInfo) +static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKStringRef frameName, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) { LOG(@"decidePolicyForNewWindowAction"); WKFramePolicyListenerUse(listener); } -static void decidePolicyForMIMEType(WKPageRef page, WKStringRef MIMEType, WKURLRef url, WKFrameRef frame, WKFramePolicyListenerRef listener, const void *clientInfo) +static void decidePolicyForMIMEType(WKPageRef page, WKFrameRef frame, WKStringRef MIMEType, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo) { WKFramePolicyListenerUse(listener); } @@ -645,6 +645,7 @@ static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParameters 0, // drawFooter 0, // printFrame 0, // showModal + 0, // didCompleteRubberBandForMainFrame }; WKPageSetPageUIClient(_webView.pageRef, &uiClient); } diff --git a/Tools/MiniBrowser/mac/WebBundle/WebBundleMain.m b/Tools/MiniBrowser/mac/WebBundle/WebBundleMain.m index 90db033..fcc6923 100644 --- a/Tools/MiniBrowser/mac/WebBundle/WebBundleMain.m +++ b/Tools/MiniBrowser/mac/WebBundle/WebBundleMain.m @@ -64,7 +64,7 @@ void didCreatePage(WKBundleRef bundle, WKBundlePageRef page, const void* clientI memset(&client, 0, sizeof(client)); client.didClearWindowObjectForFrame = didClearWindowObjectForFrame; - WKBundlePageSetLoaderClient(page, &client); + WKBundlePageSetPageLoaderClient(page, &client); } void willDestroyPage(WKBundleRef bundle, WKBundlePageRef page, const void* clientInfo) diff --git a/Tools/MiniBrowser/qt/BrowserView.cpp b/Tools/MiniBrowser/qt/BrowserView.cpp index 6118f79..7d6426e 100644 --- a/Tools/MiniBrowser/qt/BrowserView.cpp +++ b/Tools/MiniBrowser/qt/BrowserView.cpp @@ -33,17 +33,14 @@ BrowserView::BrowserView(QGraphicsWKView::BackingStoreType backingStoreType, QWKContext* context, QWidget* parent) : QGraphicsView(parent) , m_item(0) - , m_context(context ? context : new QWKContext(this)) { - m_item = new QGraphicsWKView(m_context, backingStoreType, 0); + m_item = new QGraphicsWKView(context, backingStoreType, 0); setScene(new QGraphicsScene(this)); scene()->addItem(m_item); setFrameShape(QFrame::NoFrame); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - connect(m_item, SIGNAL(titleChanged(QString)), this, SLOT(setWindowTitle(QString))); } void BrowserView::resizeEvent(QResizeEvent* event) diff --git a/Tools/MiniBrowser/qt/BrowserView.h b/Tools/MiniBrowser/qt/BrowserView.h index e19cc59..593006e 100644 --- a/Tools/MiniBrowser/qt/BrowserView.h +++ b/Tools/MiniBrowser/qt/BrowserView.h @@ -48,7 +48,6 @@ protected: private: QGraphicsWKView* m_item; - QWKContext* m_context; }; #endif diff --git a/Tools/MiniBrowser/qt/BrowserWindow.cpp b/Tools/MiniBrowser/qt/BrowserWindow.cpp index c63c9d6..0405e9e 100644 --- a/Tools/MiniBrowser/qt/BrowserWindow.cpp +++ b/Tools/MiniBrowser/qt/BrowserWindow.cpp @@ -28,34 +28,92 @@ #include "BrowserWindow.h" +#include "qwkpreferences.h" + static QWKPage* newPageFunction(QWKPage* page) { BrowserWindow* window = new BrowserWindow(page->context()); return window->page(); } -QGraphicsWKView::BackingStoreType BrowserWindow::backingStoreTypeForNewWindow = QGraphicsWKView::Simple; +QVector<qreal> BrowserWindow::m_zoomLevels; -BrowserWindow::BrowserWindow(QWKContext* context) +BrowserWindow::BrowserWindow(QWKContext* context, WindowOptions* options) + : m_isZoomTextOnly(false) + , m_currentZoom(1) + , m_context(context) { - setAttribute(Qt::WA_DeleteOnClose); + if (options) + m_windowOptions = *options; + else { + WindowOptions tmpOptions; + m_windowOptions = tmpOptions; + } - m_menu = new QMenuBar(); - m_browser = new BrowserView(backingStoreTypeForNewWindow, context); - m_addressBar = new QLineEdit(); + if (m_windowOptions.useTiledBackingStore) + m_browser = new BrowserView(QGraphicsWKView::Tiled, context); + else + m_browser = new BrowserView(QGraphicsWKView::Simple, context); - m_menu->addAction("New Window", this, SLOT(newWindow())); - m_menu->addAction("Change User Agent", this, SLOT(showUserAgentDialog())); + setAttribute(Qt::WA_DeleteOnClose); - m_menu->addSeparator(); - m_menu->addAction("Quit", this, SLOT(close())); + connect(m_browser->view(), SIGNAL(loadProgress(int)), SLOT(loadProgress(int))); + connect(m_browser->view(), SIGNAL(titleChanged(const QString&)), SLOT(setWindowTitle(const QString&))); + connect(m_browser->view(), SIGNAL(urlChanged(const QUrl&)), SLOT(urlChanged(const QUrl&))); + this->setCentralWidget(m_browser); m_browser->setFocus(Qt::OtherFocusReason); + QMenu* fileMenu = menuBar()->addMenu("&File"); + fileMenu->addAction("New Window", this, SLOT(newWindow()), QKeySequence::New); + fileMenu->addAction("Open File", this, SLOT(openFile()), QKeySequence::Open); + fileMenu->addSeparator(); + fileMenu->addAction("Quit", this, SLOT(close())); + + QMenu* viewMenu = menuBar()->addMenu("&View"); + viewMenu->addAction(page()->action(QWKPage::Stop)); + viewMenu->addAction(page()->action(QWKPage::Reload)); + viewMenu->addSeparator(); + QAction* zoomIn = viewMenu->addAction("Zoom &In", this, SLOT(zoomIn())); + QAction* zoomOut = viewMenu->addAction("Zoom &Out", this, SLOT(zoomOut())); + QAction* resetZoom = viewMenu->addAction("Reset Zoom", this, SLOT(resetZoom())); + QAction* zoomText = viewMenu->addAction("Zoom Text Only", this, SLOT(toggleZoomTextOnly(bool))); + zoomText->setCheckable(true); + zoomText->setChecked(false); + viewMenu->addSeparator(); + viewMenu->addAction("Take Screen Shot...", this, SLOT(screenshot())); + + zoomIn->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Plus)); + zoomOut->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_Minus)); + resetZoom->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0)); + + QMenu* windowMenu = menuBar()->addMenu("&Window"); + QAction* toggleFullScreen = windowMenu->addAction("Toggle FullScreen", this, SIGNAL(enteredFullScreenMode(bool))); + toggleFullScreen->setShortcut(Qt::Key_F11); + toggleFullScreen->setCheckable(true); + toggleFullScreen->setChecked(false); + // When exit fullscreen mode by clicking on the exit area (bottom right corner) we must + // uncheck the Toggle FullScreen action. + toggleFullScreen->connect(this, SIGNAL(enteredFullScreenMode(bool)), SLOT(setChecked(bool))); + connect(this, SIGNAL(enteredFullScreenMode(bool)), this, SLOT(toggleFullScreenMode(bool))); + + QMenu* toolsMenu = menuBar()->addMenu("&Develop"); + QAction* toggleFrameFlattening = toolsMenu->addAction("Toggle Frame Flattening", this, SLOT(toggleFrameFlattening(bool))); + toggleFrameFlattening->setCheckable(true); + toggleFrameFlattening->setChecked(false); + toolsMenu->addSeparator(); + toolsMenu->addAction("Change User Agent", this, SLOT(showUserAgentDialog())); + + QMenu* settingsMenu = menuBar()->addMenu("&Settings"); + QAction* toggleAutoLoadImages = settingsMenu->addAction("Disable Auto Load Images", this, SLOT(toggleAutoLoadImages(bool))); + toggleAutoLoadImages->setCheckable(true); + toggleAutoLoadImages->setChecked(false); + QAction* toggleDisableJavaScript = settingsMenu->addAction("Disable JavaScript", this, SLOT(toggleDisableJavaScript(bool))); + toggleDisableJavaScript->setCheckable(true); + toggleDisableJavaScript->setChecked(false); + + m_addressBar = new QLineEdit(); connect(m_addressBar, SIGNAL(returnPressed()), SLOT(changeLocation())); - connect(m_browser->view(), SIGNAL(loadProgress(int)), SLOT(loadProgress(int))); - connect(m_browser->view(), SIGNAL(titleChanged(const QString&)), SLOT(titleChanged(const QString&))); - connect(m_browser->view(), SIGNAL(urlChanged(const QUrl&)), SLOT(urlChanged(const QUrl&))); QToolBar* bar = addToolBar("Navigation"); bar->addAction(page()->action(QWKPage::Back)); @@ -64,17 +122,19 @@ BrowserWindow::BrowserWindow(QWKContext* context) bar->addAction(page()->action(QWKPage::Stop)); bar->addWidget(m_addressBar); - this->setMenuBar(m_menu); - this->setCentralWidget(m_browser); - - m_browser->setFocus(Qt::OtherFocusReason); - QShortcut* selectAddressBar = new QShortcut(Qt::CTRL | Qt::Key_L, this); connect(selectAddressBar, SIGNAL(activated()), this, SLOT(openLocation())); page()->setCreateNewPageFunction(newPageFunction); - resize(960, 640); + // the zoom values are chosen to be like in Mozilla Firefox 3 + if (!m_zoomLevels.count()) { + m_zoomLevels << 0.3 << 0.5 << 0.67 << 0.8 << 0.9; + m_zoomLevels << 1; + m_zoomLevels << 1.1 << 1.2 << 1.33 << 1.5 << 1.7 << 2 << 2.4 << 3; + } + + resize(800, 600); show(); } @@ -91,7 +151,14 @@ QWKPage* BrowserWindow::page() BrowserWindow* BrowserWindow::newWindow(const QString& url) { - BrowserWindow* window = new BrowserWindow; + BrowserWindow* window; + if (m_windowOptions.useSeparateWebProcessPerWindow) { + QWKContext* context = new QWKContext(); + window = new BrowserWindow(context); + context->setParent(window); + } else + window = new BrowserWindow(m_context); + window->load(url); return window; } @@ -127,35 +194,113 @@ void BrowserWindow::loadProgress(int progress) m_addressBar->setPalette(pallete); } -void BrowserWindow::titleChanged(const QString& title) -{ - setWindowTitle(title); -} - void BrowserWindow::urlChanged(const QUrl& url) { m_addressBar->setText(url.toString()); } -void BrowserWindow::updateUserAgentList() +void BrowserWindow::openFile() { - QFile file(":/useragentlist.txt"); +#ifndef QT_NO_FILEDIALOG + static const QString filter("HTML Files (*.htm *.html *.xhtml);;Text Files (*.txt);;Image Files (*.gif *.jpg *.png);;SVG Files (*.svg);;All Files (*)"); + + QFileDialog fileDialog(this, tr("Open"), QString(), filter); + fileDialog.setAcceptMode(QFileDialog::AcceptOpen); + fileDialog.setFileMode(QFileDialog::ExistingFile); + fileDialog.setOptions(QFileDialog::ReadOnly); + + if (fileDialog.exec()) { + QString selectedFile = fileDialog.selectedFiles()[0]; + if (!selectedFile.isEmpty()) + load(selectedFile); + } +#endif +} - if (file.open(QIODevice::ReadOnly)) { - while (!file.atEnd()) { - QString agent = file.readLine().trimmed(); - if (!m_userAgentList.contains(agent)) - m_userAgentList << agent; - } - file.close(); +void BrowserWindow::screenshot() +{ + QPixmap pixmap = QPixmap::grabWidget(m_browser); + QLabel* label = 0; +#if !defined(Q_OS_SYMBIAN) + label = new QLabel; + label->setAttribute(Qt::WA_DeleteOnClose); + label->setWindowTitle("Screenshot - Preview"); + label->setPixmap(pixmap); + label->show(); +#endif + +#ifndef QT_NO_FILEDIALOG + QString fileName = QFileDialog::getSaveFileName(label, "Screenshot", QString(), QString("PNG File (.png)")); + if (!fileName.isEmpty()) { + QRegExp rx("*.png"); + rx.setCaseSensitivity(Qt::CaseInsensitive); + rx.setPatternSyntax(QRegExp::Wildcard); + + if (!rx.exactMatch(fileName)) + fileName += ".png"; + + pixmap.save(fileName, "png"); + if (label) + label->setWindowTitle(QString("Screenshot - Saved at %1").arg(fileName)); } +#endif +} - Q_ASSERT(!m_userAgentList.isEmpty()); - QWKPage* wkPage = page(); - if (!(wkPage->customUserAgent().isEmpty() || m_userAgentList.contains(wkPage->customUserAgent()))) - m_userAgentList << wkPage->customUserAgent(); +void BrowserWindow::zoomIn() +{ + if (m_isZoomTextOnly) + m_currentZoom = page()->textZoomFactor(); + else + m_currentZoom = page()->pageZoomFactor(); + + int i = m_zoomLevels.indexOf(m_currentZoom); + Q_ASSERT(i >= 0); + if (i < m_zoomLevels.count() - 1) + m_currentZoom = m_zoomLevels[i + 1]; + + applyZoom(); } +void BrowserWindow::zoomOut() +{ + if (m_isZoomTextOnly) + m_currentZoom = page()->textZoomFactor(); + else + m_currentZoom = page()->pageZoomFactor(); + + int i = m_zoomLevels.indexOf(m_currentZoom); + Q_ASSERT(i >= 0); + if (i > 0) + m_currentZoom = m_zoomLevels[i - 1]; + + applyZoom(); +} + +void BrowserWindow::resetZoom() +{ + m_currentZoom = 1; + applyZoom(); +} + +void BrowserWindow::toggleZoomTextOnly(bool b) +{ + m_isZoomTextOnly = b; +} + +void BrowserWindow::toggleFullScreenMode(bool enable) +{ + if (enable) + setWindowState(Qt::WindowFullScreen); + else + setWindowState(Qt::WindowNoState); +} + +void BrowserWindow::toggleFrameFlattening(bool toggle) +{ + page()->preferences()->setAttribute(QWKPreferences::FrameFlatteningEnabled, toggle); +} + + void BrowserWindow::showUserAgentDialog() { updateUserAgentList(); @@ -185,9 +330,45 @@ void BrowserWindow::showUserAgentDialog() page()->setCustomUserAgent(combo->currentText()); } +void BrowserWindow::toggleDisableJavaScript(bool enable) +{ + page()->preferences()->setAttribute(QWKPreferences::JavascriptEnabled, !enable); +} + +void BrowserWindow::toggleAutoLoadImages(bool enable) +{ + page()->preferences()->setAttribute(QWKPreferences::AutoLoadImages, !enable); +} + +void BrowserWindow::updateUserAgentList() +{ + QFile file(":/useragentlist.txt"); + + if (file.open(QIODevice::ReadOnly)) { + while (!file.atEnd()) { + QString agent = file.readLine().trimmed(); + if (!m_userAgentList.contains(agent)) + m_userAgentList << agent; + } + file.close(); + } + + Q_ASSERT(!m_userAgentList.isEmpty()); + QWKPage* wkPage = page(); + if (!(wkPage->customUserAgent().isEmpty() || m_userAgentList.contains(wkPage->customUserAgent()))) + m_userAgentList << wkPage->customUserAgent(); +} + +void BrowserWindow::applyZoom() +{ + if (m_isZoomTextOnly) + page()->setTextZoomFactor(m_currentZoom); + else + page()->setPageZoomFactor(m_currentZoom); +} + BrowserWindow::~BrowserWindow() { delete m_addressBar; delete m_browser; - delete m_menu; } diff --git a/Tools/MiniBrowser/qt/BrowserWindow.h b/Tools/MiniBrowser/qt/BrowserWindow.h index f984309..c79b2d0 100644 --- a/Tools/MiniBrowser/qt/BrowserWindow.h +++ b/Tools/MiniBrowser/qt/BrowserWindow.h @@ -30,38 +30,60 @@ #define BrowserWindow_h #include "BrowserView.h" + +#include "MiniBrowserApplication.h" #include <QStringList> #include <QtGui> -#include <qgraphicswkview.h> class BrowserWindow : public QMainWindow { Q_OBJECT public: - BrowserWindow(QWKContext* = 0); + BrowserWindow(QWKContext*, WindowOptions* = 0); ~BrowserWindow(); void load(const QString& url); QWKPage* page(); - static QGraphicsWKView::BackingStoreType backingStoreTypeForNewWindow; - public slots: BrowserWindow* newWindow(const QString& url = "about:blank"); void openLocation(); +signals: + void enteredFullScreenMode(bool on); + protected slots: void changeLocation(); void loadProgress(int progress); - void titleChanged(const QString&); void urlChanged(const QUrl&); + void openFile(); + + void zoomIn(); + void zoomOut(); + void resetZoom(); + void toggleZoomTextOnly(bool on); + void screenshot(); + + void toggleFullScreenMode(bool enable); + + void toggleFrameFlattening(bool); void showUserAgentDialog(); + void toggleAutoLoadImages(bool); + void toggleDisableJavaScript(bool); + private: void updateUserAgentList(); + void applyZoom(); + + static QVector<qreal> m_zoomLevels; + bool m_isZoomTextOnly; + qreal m_currentZoom; + + QWKContext* m_context; + WindowOptions m_windowOptions; BrowserView* m_browser; - QMenuBar* m_menu; QLineEdit* m_addressBar; QStringList m_userAgentList; }; diff --git a/Tools/MiniBrowser/qt/MiniBrowser.pro b/Tools/MiniBrowser/qt/MiniBrowser.pro index c297207..cefa678 100644 --- a/Tools/MiniBrowser/qt/MiniBrowser.pro +++ b/Tools/MiniBrowser/qt/MiniBrowser.pro @@ -2,18 +2,22 @@ TEMPLATE = app TARGET = MiniBrowser SOURCES += \ - main.cpp \ BrowserView.cpp \ BrowserWindow.cpp \ + main.cpp \ + MiniBrowserApplication.cpp \ + UrlLoader.cpp \ + utils.cpp \ HEADERS += \ BrowserView.h \ BrowserWindow.h \ - -CONFIG += uitools + MiniBrowserApplication.h \ + UrlLoader.h \ + utils.h \ isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../.. -include(../../../WebKit.pri) +include(../../../Source/WebKit.pri) INCLUDEPATH += \ $$PWD/../../../Source/WebKit2/ \ @@ -55,4 +59,4 @@ contains(QT_CONFIG, opengl) { # We copy the resource file to the build directory. # The copier is defined in Tools/MiniBrowser/DerivedSources.pro. RESOURCES += \ - $$OUTPUT_DIR/Tools/MiniBrowser/qt/MiniBrowser.qrc + $$OUTPUT_DIR/MiniBrowser/qt/MiniBrowser.qrc diff --git a/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp b/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp new file mode 100644 index 0000000..4ed7895 --- /dev/null +++ b/Tools/MiniBrowser/qt/MiniBrowserApplication.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2010 University of Szeged + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "MiniBrowserApplication.h" + +#include "utils.h" +#include <QRegExp> + +MiniBrowserApplication::MiniBrowserApplication(int& argc, char** argv) + : QApplication(argc, argv, QApplication::GuiServer) + , m_windowOptions() + , m_isRobotized(false) + , m_robotTimeoutSeconds(0) + , m_robotExtraTimeSeconds(0) +{ + setOrganizationName("Nokia"); + setApplicationName("QtMiniBrowser"); + setApplicationVersion("0.1"); + + handleUserOptions(); +} + +void MiniBrowserApplication::handleUserOptions() +{ + QStringList args = arguments(); + QFileInfo program(args.at(0)); + QString programName("MiniBrowser"); + if (program.exists()) + programName = program.baseName(); + + if (args.contains("-help")) { + qDebug() << "Usage:" << programName.toLatin1().data() + << "[-r list]" + << "[-robot-timeout seconds]" + << "[-robot-extra-time seconds]" + << "[-tiled-backing-store]" + << "[-separate-web-process-per-window]" + << "URLs"; + appQuit(0); + } + + int robotIndex = args.indexOf("-r"); + if (robotIndex != -1) { + QString listFile = takeOptionValue(&args, robotIndex); + if (listFile.isEmpty()) + appQuit(1, "-r needs a list file to start in robotized mode"); + if (!QFile::exists(listFile)) + appQuit(1, "The list file supplied to -r does not exist."); + + m_isRobotized = true; + m_urls = QStringList(listFile); + } else { + int lastArg = args.lastIndexOf(QRegExp("^-.*")); + m_urls = (lastArg != -1) ? args.mid(++lastArg) : args.mid(1); + } + + int robotTimeoutIndex = args.indexOf("-robot-timeout"); + if (robotTimeoutIndex != -1) + m_robotTimeoutSeconds = takeOptionValue(&args, robotTimeoutIndex).toInt(); + + int robotExtraTimeIndex = args.indexOf("-robot-extra-time"); + if (robotExtraTimeIndex != -1) + m_robotExtraTimeSeconds = takeOptionValue(&args, robotExtraTimeIndex).toInt(); + + if (args.contains("-tiled-backing-store")) + m_windowOptions.useTiledBackingStore = true; + + if (args.contains("-separate-web-process-per-window")) + m_windowOptions.useSeparateWebProcessPerWindow = true; +} diff --git a/Tools/MiniBrowser/qt/MiniBrowserApplication.h b/Tools/MiniBrowser/qt/MiniBrowserApplication.h new file mode 100644 index 0000000..2039764 --- /dev/null +++ b/Tools/MiniBrowser/qt/MiniBrowserApplication.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2010 University of Szeged + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MiniBrowserApplication_h +#define MiniBrowserApplication_h + +#include <QStringList> +#include <QtGui> + +struct WindowOptions { + WindowOptions() + : useTiledBackingStore(false) + , useSeparateWebProcessPerWindow(false) + { + } + + bool useTiledBackingStore; + bool useSeparateWebProcessPerWindow; +}; + +class MiniBrowserApplication : public QApplication { + Q_OBJECT + +public: + MiniBrowserApplication(int& argc, char** argv); + QStringList urls() const { return m_urls; } + bool isRobotized() const { return m_isRobotized; } + int robotTimeout() const { return m_robotTimeoutSeconds; } + int robotExtraTime() const { return m_robotExtraTimeSeconds; } + + WindowOptions m_windowOptions; + +private: + void handleUserOptions(); + +private: + bool m_isRobotized; + int m_robotTimeoutSeconds; + int m_robotExtraTimeSeconds; + QStringList m_urls; +}; + +#endif diff --git a/Tools/MiniBrowser/qt/UrlLoader.cpp b/Tools/MiniBrowser/qt/UrlLoader.cpp new file mode 100644 index 0000000..600d477 --- /dev/null +++ b/Tools/MiniBrowser/qt/UrlLoader.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009 University of Szeged + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "UrlLoader.h" + +#include <QDebug> +#include <QFile> + +UrlLoader::UrlLoader(BrowserWindow* browserWindow, const QString& inputFileName, int timeoutSeconds, int extraTimeSeconds) + : m_browserWindow(browserWindow) + , m_stdOut(stdout) + , m_loaded(0) + , m_numFramesLoading(0) +{ + m_checkIfFinishedTimer.setInterval(200); + m_checkIfFinishedTimer.setSingleShot(true); + connect(&m_checkIfFinishedTimer, SIGNAL(timeout()), this, SLOT(checkIfFinished())); + // loadStarted and loadFinished on QWebPage is emitted for each frame/sub-frame + connect(m_browserWindow->page(), SIGNAL(loadStarted()), this, SLOT(frameLoadStarted())); + connect(m_browserWindow->page(), SIGNAL(loadFinished(bool)), this, SLOT(frameLoadFinished())); + + if (timeoutSeconds) { + m_timeoutTimer.setInterval(timeoutSeconds * 1000); + m_timeoutTimer.setSingleShot(true); + connect(m_browserWindow, SIGNAL(loadStarted()), &m_timeoutTimer, SLOT(start())); + connect(&m_timeoutTimer, SIGNAL(timeout()), this, SLOT(loadNext())); + } + if (extraTimeSeconds) { + m_extraTimeTimer.setInterval(extraTimeSeconds * 1000); + m_extraTimeTimer.setSingleShot(true); + connect(this, SIGNAL(pageLoadFinished()), &m_extraTimeTimer, SLOT(start())); + connect(&m_extraTimeTimer, SIGNAL(timeout()), this, SLOT(loadNext())); + } else + connect(this, SIGNAL(pageLoadFinished()), this, SLOT(loadNext())); + loadUrlList(inputFileName); +} + +void UrlLoader::loadNext() +{ + m_timeoutTimer.stop(); + m_extraTimeTimer.stop(); + m_checkIfFinishedTimer.stop(); + m_numFramesLoading = 0; + QString qstr; + if (getUrl(qstr)) { + QUrl url(qstr, QUrl::StrictMode); + if (url.isValid()) { + m_stdOut << "Loading " << qstr << " ......" << ++m_loaded << endl; + m_browserWindow->load(url.toString()); + } else + loadNext(); + } else + disconnect(m_browserWindow, 0, this, 0); +} + +void UrlLoader::checkIfFinished() +{ + if (!m_numFramesLoading) + emit pageLoadFinished(); +} + +void UrlLoader::frameLoadStarted() +{ + ++m_numFramesLoading; + m_checkIfFinishedTimer.stop(); +} + +void UrlLoader::frameLoadFinished() +{ + Q_ASSERT(m_numFramesLoading > 0); + --m_numFramesLoading; + // Once our frame has finished loading, wait a moment to call loadNext for cases + // where a sub-frame starts loading or another frame is loaded through JavaScript. + m_checkIfFinishedTimer.start(); +} + +void UrlLoader::loadUrlList(const QString& inputFileName) +{ + QFile inputFile(inputFileName); + if (inputFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream stream(&inputFile); + QString line; + while (true) { + line = stream.readLine(); + if (line.isNull()) + break; + m_urls.append(line); + } + } else { + qDebug() << "Can't open list file"; + exit(0); + } + m_index = 0; + inputFile.close(); +} + +bool UrlLoader::getUrl(QString& qstr) +{ + if (m_index == m_urls.size()) + return false; + + qstr = m_urls[m_index++]; + return true; +} diff --git a/Tools/MiniBrowser/qt/UrlLoader.h b/Tools/MiniBrowser/qt/UrlLoader.h new file mode 100644 index 0000000..01e67c3 --- /dev/null +++ b/Tools/MiniBrowser/qt/UrlLoader.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2009 University of Szeged + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UrlLoader_h +#define UrlLoader_h + +#include "BrowserWindow.h" + +#include <QTextStream> +#include <QTimer> +#include <QVector> + +class UrlLoader : public QObject { + Q_OBJECT + +public: + UrlLoader(BrowserWindow*, const QString&, int, int); + +public slots: + void loadNext(); + +private slots: + void checkIfFinished(); + void frameLoadStarted(); + void frameLoadFinished(); + +signals: + void pageLoadFinished(); + +private: + void loadUrlList(const QString& inputFileName); + bool getUrl(QString& qstr); + +private: + QVector<QString> m_urls; + int m_index; + BrowserWindow* m_browserWindow; + QTextStream m_stdOut; + int m_loaded; + QTimer m_timeoutTimer; + QTimer m_extraTimeTimer; + QTimer m_checkIfFinishedTimer; + int m_numFramesLoading; +}; + +#endif diff --git a/Tools/MiniBrowser/qt/main.cpp b/Tools/MiniBrowser/qt/main.cpp index 8c987c5..8f4c1ea 100644 --- a/Tools/MiniBrowser/qt/main.cpp +++ b/Tools/MiniBrowser/qt/main.cpp @@ -27,38 +27,46 @@ */ #include "BrowserWindow.h" + +#include "MiniBrowserApplication.h" +#include "UrlLoader.h" #include <QLatin1String> #include <QRegExp> #include <qgraphicswkview.h> #include <QtGui> -int main(int argc, char** argv) { - QApplication app(argc, argv); - - QStringList args = QApplication::arguments(); - args.removeAt(0); +int main(int argc, char** argv) +{ + MiniBrowserApplication app(argc, argv); - QGraphicsWKView::BackingStoreType backingStoreTypeToUse = QGraphicsWKView::Simple; - int indexOfTiledOption; - if ((indexOfTiledOption = args.indexOf(QRegExp(QLatin1String("-tiled")))) != -1) { - backingStoreTypeToUse = QGraphicsWKView::Tiled; - args.removeAt(indexOfTiledOption); + if (app.isRobotized()) { + QWKContext* context = new QWKContext; + BrowserWindow* window = new BrowserWindow(context, &app.m_windowOptions); + UrlLoader loader(window, app.urls().at(0), app.robotTimeout(), app.robotExtraTime()); + loader.loadNext(); + window->show(); + return app.exec(); } - if (args.isEmpty()) { + QStringList urls = app.urls(); + + if (urls.isEmpty()) { QString defaultUrl = QString("file://%1/%2").arg(QDir::homePath()).arg(QLatin1String("index.html")); if (QDir(defaultUrl).exists()) - args.append(defaultUrl); + urls.append(defaultUrl); else - args.append("http://www.google.com"); + urls.append("http://www.google.com"); } - BrowserWindow::backingStoreTypeForNewWindow = backingStoreTypeToUse; - BrowserWindow* window = new BrowserWindow; - window->load(args[0]); + QWKContext* context = new QWKContext; + BrowserWindow* window = new BrowserWindow(context, &app.m_windowOptions); + if (app.m_windowOptions.useSeparateWebProcessPerWindow) + context->setParent(window); + + window->load(urls.at(0)); - for (int i = 1; i < args.size(); ++i) - window->newWindow(args[i]); + for (int i = 1; i < urls.size(); ++i) + window->newWindow(urls.at(i)); app.exec(); diff --git a/Tools/MiniBrowser/qt/utils.cpp b/Tools/MiniBrowser/qt/utils.cpp new file mode 100644 index 0000000..494da71 --- /dev/null +++ b/Tools/MiniBrowser/qt/utils.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011 University of Szeged + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "utils.h" + +QString takeOptionValue(QStringList* arguments, int index) +{ + QString result; + + if (++index < arguments->count() && !arguments->at(index).startsWith("-")) + result = arguments->takeAt(index); + + return result; +} + +QString formatKeys(QList<QString> keys) +{ + QString result; + for (int i = 0; i < keys.count() - 1; i++) + result.append(keys.at(i) + "|"); + result.append(keys.last()); + return result; +} + +QList<QString> enumToKeys(const QMetaObject o, const QString& name, const QString& strip) +{ + QList<QString> list; + + int enumIndex = o.indexOfEnumerator(name.toLatin1().data()); + QMetaEnum enumerator = o.enumerator(enumIndex); + + if (enumerator.isValid()) { + for (int i = 0; i < enumerator.keyCount(); i++) { + QString key(enumerator.valueToKey(i)); + list.append(key.remove(strip)); + } + } + + return list; +} + +void appQuit(int exitCode, const QString& msg) +{ + if (!msg.isEmpty()) { + if (exitCode > 0) + qDebug("ERROR: %s", msg.toLatin1().data()); + else + qDebug() << msg; + } + exit(exitCode); +} + +QUrl urlFromUserInput(const QString& string) +{ + QString input(string); + QFileInfo fi(input); + if (fi.exists() && fi.isRelative()) + input = fi.absoluteFilePath(); + + return QUrl::fromUserInput(input); +} diff --git a/Tools/MiniBrowser/qt/utils.h b/Tools/MiniBrowser/qt/utils.h new file mode 100644 index 0000000..2ec7af2 --- /dev/null +++ b/Tools/MiniBrowser/qt/utils.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2011 University of Szeged + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef utils_h +#define utils_h + +#include <QtCore> + +#ifndef NO_RETURN +#if defined(__CC_ARM) || defined(__ARMCC__) +#define NO_RETURN __declspec(noreturn) +#elif defined(__GNUC__) +#define NO_RETURN __attribute((__noreturn__)) +#else +#define NO_RETURN +#endif +#endif + +// options handling +QString takeOptionValue(QStringList* arguments, int index); +QString formatKeys(QList<QString> keys); +QList<QString> enumToKeys(const QMetaObject, const QString&, const QString&); + +NO_RETURN void appQuit(int status, const QString& msg = QString()); + +QUrl urlFromUserInput(const QString& input); + +#endif |