diff options
Diffstat (limited to 'tools/qmlviewer/main.cpp')
-rw-r--r-- | tools/qmlviewer/main.cpp | 597 |
1 files changed, 597 insertions, 0 deletions
diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp new file mode 100644 index 0000000000..b2c7f4f730 --- /dev/null +++ b/tools/qmlviewer/main.cpp @@ -0,0 +1,597 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarative.h" +#include "qmlruntime.h" +#include "qdeclarativeengine.h" +#include "loggerwidget.h" +#include <QWidget> +#include <QDir> +#include <QApplication> +#include <QTranslator> +#include <QDebug> +#include <QMessageBox> +#include <QAtomicInt> +#include "qdeclarativetester.h" +#include <private/qdeclarativedebughelper_p.h> + +QT_USE_NAMESPACE + +QtMsgHandler systemMsgOutput = 0; + +static QDeclarativeViewer *openFile(const QString &fileName); +static void showViewer(QDeclarativeViewer *viewer); + +QString warnings; +void exitApp(int i) +{ +#ifdef Q_OS_WIN + // Debugging output is not visible by default on Windows - + // therefore show modal dialog with errors instead. + if (!warnings.isEmpty()) { + QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings); + } +#endif + exit(i); +} + +QWeakPointer<LoggerWidget> logger; +static QAtomicInt recursiveLock(0); + +#if defined (Q_OS_SYMBIAN) +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#endif + +void myMessageOutput(QtMsgType type, const char *msg) +{ + QString strMsg = QString::fromLatin1(msg); + + if (!QCoreApplication::closingDown()) { + if (!logger.isNull()) { + if (recursiveLock.testAndSetOrdered(0, 1)) { + QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg)); + recursiveLock = 0; + } + } else { + warnings += strMsg; + warnings += QLatin1Char('\n'); + } + } +#if defined (Q_OS_SYMBIAN) + static int fd = -1; + if (fd == -1) + fd = ::open("E:\\qml.log", O_WRONLY | O_CREAT); + + ::write(fd, msg, strlen(msg)); + ::write(fd, "\n", 1); + ::fsync(fd); + switch (type) { + case QtFatalMsg: + abort(); + } +#endif + + if (systemMsgOutput) { + systemMsgOutput(type, msg); + } else { // Unix + fprintf(stderr, "%s\n", msg); + fflush(stderr); + } +} + +static QDeclarativeViewer* globalViewer = 0; + +// The qml file that is shown if the user didn't specify a QML file +QString initialFile = "qrc:/startup/startup.qml"; + +void usage() +{ + qWarning("Usage: qmlviewer [options] <filename>"); + qWarning(" "); + qWarning(" options:"); + qWarning(" -v, -version ............................. display version"); + qWarning(" -frameless ............................... run with no window frame"); + qWarning(" -maximized................................ run maximized"); + qWarning(" -fullscreen............................... run fullscreen"); + qWarning(" -stayontop................................ keep viewer window on top"); + qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content"); + qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view (default)"); + qWarning(" -qmlbrowser .............................. use a QML-based file browser"); + qWarning(" -warnings [show|hide]..................... show warnings in a separate log window"); + qWarning(" -recordfile <output> ..................... set video recording file"); + qWarning(" - ImageMagick 'convert' for GIF)"); + qWarning(" - png file for raw frames"); + qWarning(" - 'ffmpeg' for other formats"); + qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode"); + qWarning(" -recordrate <fps> ........................ set recording frame rate"); + qWarning(" -record arg .............................. add a recording process argument"); + qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop"); + qWarning(" -devicekeys .............................. use numeric keys (see F1)"); + qWarning(" -dragthreshold <size> .................... set mouse drag threshold size"); + qWarning(" -netcache <size> ......................... set disk cache to size bytes"); + qWarning(" -translation <translationfile> ........... set the language to run in"); + qWarning(" -I <directory> ........................... prepend to the module import search path,"); + qWarning(" display path if <directory> is empty"); + qWarning(" -P <directory> ........................... prepend to the plugin search path"); +#if defined(Q_WS_MAC) + qWarning(" -no-opengl ............................... don't use a QGLWidget for the viewport"); +#else + qWarning(" -opengl .................................. use a QGLWidget for the viewport"); +#endif + qWarning(" -script <path> ........................... set the script to use"); + qWarning(" -scriptopts <options>|help ............... set the script options to use"); + + qWarning(" "); + qWarning(" Press F1 for interactive help"); + + exitApp(1); +} + +void scriptOptsUsage() +{ + qWarning("Usage: qmlviewer -scriptopts <option>[,<option>...] ..."); + qWarning(" options:"); + qWarning(" record ................................... record a new script"); + qWarning(" play ..................................... playback an existing script"); + qWarning(" testimages ............................... record images or compare images on playback"); + qWarning(" testerror ................................ test 'error' property of root item on playback"); + qWarning(" testskip ................................ test 'skip' property of root item on playback"); + qWarning(" snapshot ................................. file being recorded is static,"); + qWarning(" only one frame will be recorded or tested"); + qWarning(" exitoncomplete ........................... cleanly exit the viewer on script completion"); + qWarning(" exitonfailure ............................ immediately exit the viewer on script failure"); + qWarning(" saveonexit ............................... save recording on viewer exit"); + qWarning(" "); + qWarning(" One of record, play or both must be specified."); + + exitApp(1); +} + +enum WarningsConfig { ShowWarnings, HideWarnings, DefaultWarnings }; + +struct ViewerOptions +{ + ViewerOptions() + : frameless(false), + fps(0.0), + autorecord_from(0), + autorecord_to(0), + dither("none"), + runScript(false), + devkeys(false), + cache(0), + useGL(false), + fullScreen(false), + stayOnTop(false), + maximized(false), + useNativeFileBrowser(true), + experimentalGestures(false), + warningsConfig(DefaultWarnings), + sizeToView(true) + { +#if defined(Q_OS_SYMBIAN) + maximized = true; + useNativeFileBrowser = false; +#endif + +#if defined(Q_WS_MAC) + useGL = true; +#endif + } + + bool frameless; + double fps; + int autorecord_from; + int autorecord_to; + QString dither; + QString recordfile; + QStringList recordargs; + QStringList imports; + QStringList plugins; + QString script; + QString scriptopts; + bool runScript; + bool devkeys; + int cache; + QString translationFile; + bool useGL; + bool fullScreen; + bool stayOnTop; + bool maximized; + bool useNativeFileBrowser; + bool experimentalGestures; + + WarningsConfig warningsConfig; + bool sizeToView; + + QDeclarativeViewer::ScriptOptions scriptOptions; +}; + +static ViewerOptions opts; +static QStringList fileNames; + +class Application : public QApplication +{ + Q_OBJECT +public: + Application(int &argc, char **&argv) + : QApplication(argc, argv) + {} + +protected: + bool event(QEvent *ev) + { + if (ev->type() != QEvent::FileOpen) + return QApplication::event(ev); + + QFileOpenEvent *fev = static_cast<QFileOpenEvent *>(ev); + + globalViewer->open(fev->file()); + if (!globalViewer->isVisible()) + showViewer(globalViewer); + + return true; + } + +private Q_SLOTS: + void showInitialViewer() + { + QApplication::processEvents(); + + QDeclarativeViewer *viewer = globalViewer; + if (!viewer) + return; + if (viewer->currentFile().isEmpty()) { + if(opts.useNativeFileBrowser) + viewer->open(initialFile); + else + viewer->openFile(); + } + if (!viewer->isVisible()) + showViewer(viewer); + } +}; + +static void parseScriptOptions() +{ + QStringList options = + opts.scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts); + + QDeclarativeViewer::ScriptOptions scriptOptions = 0; + for (int i = 0; i < options.count(); ++i) { + const QString &option = options.at(i); + if (option == QLatin1String("help")) { + scriptOptsUsage(); + } else if (option == QLatin1String("play")) { + scriptOptions |= QDeclarativeViewer::Play; + } else if (option == QLatin1String("record")) { + scriptOptions |= QDeclarativeViewer::Record; + } else if (option == QLatin1String("testimages")) { + scriptOptions |= QDeclarativeViewer::TestImages; + } else if (option == QLatin1String("testerror")) { + scriptOptions |= QDeclarativeViewer::TestErrorProperty; + } else if (option == QLatin1String("testskip")) { + scriptOptions |= QDeclarativeViewer::TestSkipProperty; + } else if (option == QLatin1String("exitoncomplete")) { + scriptOptions |= QDeclarativeViewer::ExitOnComplete; + } else if (option == QLatin1String("exitonfailure")) { + scriptOptions |= QDeclarativeViewer::ExitOnFailure; + } else if (option == QLatin1String("saveonexit")) { + scriptOptions |= QDeclarativeViewer::SaveOnExit; + } else if (option == QLatin1String("snapshot")) { + scriptOptions |= QDeclarativeViewer::Snapshot; + } else { + scriptOptsUsage(); + } + } + + opts.scriptOptions = scriptOptions; +} + +static void parseCommandLineOptions(const QStringList &arguments) +{ + for (int i = 1; i < arguments.count(); ++i) { + bool lastArg = (i == arguments.count() - 1); + QString arg = arguments.at(i); + if (arg == "-frameless") { + opts.frameless = true; + } else if (arg == "-maximized") { + opts.maximized = true; + } else if (arg == "-fullscreen") { + opts.fullScreen = true; + } else if (arg == "-stayontop") { + opts.stayOnTop = true; + } else if (arg == "-netcache") { + if (lastArg) usage(); + opts.cache = arguments.at(++i).toInt(); + } else if (arg == "-recordrate") { + if (lastArg) usage(); + opts.fps = arguments.at(++i).toDouble(); + } else if (arg == "-recordfile") { + if (lastArg) usage(); + opts.recordfile = arguments.at(++i); + } else if (arg == "-record") { + if (lastArg) usage(); + opts.recordargs << arguments.at(++i); + } else if (arg == "-recorddither") { + if (lastArg) usage(); + opts.dither = arguments.at(++i); + } else if (arg == "-autorecord") { + if (lastArg) usage(); + QString range = arguments.at(++i); + int dash = range.indexOf('-'); + if (dash > 0) + opts.autorecord_from = range.left(dash).toInt(); + opts.autorecord_to = range.mid(dash+1).toInt(); + } else if (arg == "-devicekeys") { + opts.devkeys = true; + } else if (arg == "-dragthreshold") { + if (lastArg) usage(); + qApp->setStartDragDistance(arguments.at(++i).toInt()); + } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) { + qWarning("Qt QML Viewer version %s", QT_VERSION_STR); + exitApp(0); + } else if (arg == "-translation") { + if (lastArg) usage(); + opts.translationFile = arguments.at(++i); +#if defined(Q_WS_MAC) + } else if (arg == "-no-opengl") { + opts.useGL = false; +#else + } else if (arg == "-opengl") { + opts.useGL = true; +#endif + } else if (arg == "-qmlbrowser") { + opts.useNativeFileBrowser = false; + } else if (arg == "-warnings") { + if (lastArg) usage(); + QString warningsStr = arguments.at(++i); + if (warningsStr == QLatin1String("show")) { + opts.warningsConfig = ShowWarnings; + } else if (warningsStr == QLatin1String("hide")) { + opts.warningsConfig = HideWarnings; + } else { + usage(); + } + } else if (arg == "-I" || arg == "-L") { + if (arg == "-L") + qWarning("-L option provided for compatibility only, use -I instead"); + if (lastArg) { + QDeclarativeEngine tmpEngine; + QString paths = tmpEngine.importPathList().join(QLatin1String(":")); + qWarning("Current search path: %s", paths.toLocal8Bit().constData()); + exitApp(0); + } + opts.imports << arguments.at(++i); + } else if (arg == "-P") { + if (lastArg) usage(); + opts.plugins << arguments.at(++i); + } else if (arg == "-script") { + if (lastArg) usage(); + opts.script = arguments.at(++i); + } else if (arg == "-scriptopts") { + if (lastArg) usage(); + opts.scriptopts = arguments.at(++i); + } else if (arg == "-savescript") { + if (lastArg) usage(); + opts.script = arguments.at(++i); + opts.runScript = false; + } else if (arg == "-playscript") { + if (lastArg) usage(); + opts.script = arguments.at(++i); + opts.runScript = true; + } else if (arg == "-sizeviewtorootobject") { + opts.sizeToView = false; + } else if (arg == "-sizerootobjecttoview") { + opts.sizeToView = true; + } else if (arg == "-experimentalgestures") { + opts.experimentalGestures = true; + } else if (!arg.startsWith('-')) { + fileNames.append(arg); + } else if (true || arg == "-help") { + usage(); + } + } + + if (!opts.scriptopts.isEmpty()) { + + parseScriptOptions(); + + if (opts.script.isEmpty()) + usage(); + + if (!(opts.scriptOptions & QDeclarativeViewer::Record) && !(opts.scriptOptions & QDeclarativeViewer::Play)) + scriptOptsUsage(); + } else if (!opts.script.isEmpty()) { + usage(); + } + +} + +static QDeclarativeViewer *createViewer() +{ + Qt::WFlags wflags = (opts.frameless ? Qt::FramelessWindowHint : Qt::Widget); + if (opts.stayOnTop) + wflags |= Qt::WindowStaysOnTopHint; + + QDeclarativeViewer *viewer = new QDeclarativeViewer(0, wflags); + viewer->setAttribute(Qt::WA_DeleteOnClose, true); + viewer->setUseGL(opts.useGL); + + if (!opts.scriptopts.isEmpty()) { + viewer->setScriptOptions(opts.scriptOptions); + viewer->setScript(opts.script); + } + + logger = viewer->warningsWidget(); + if (opts.warningsConfig == ShowWarnings) { + logger.data()->setDefaultVisibility(LoggerWidget::ShowWarnings); + logger.data()->show(); + } else if (opts.warningsConfig == HideWarnings){ + logger.data()->setDefaultVisibility(LoggerWidget::HideWarnings); + } + + if (opts.experimentalGestures) + viewer->enableExperimentalGestures(); + + foreach (QString lib, opts.imports) + viewer->addLibraryPath(lib); + + foreach (QString plugin, opts.plugins) + viewer->addPluginPath(plugin); + + viewer->setNetworkCacheSize(opts.cache); + viewer->setRecordFile(opts.recordfile); + viewer->setSizeToView(opts.sizeToView); + if (opts.fps > 0) + viewer->setRecordRate(opts.fps); + if (opts.autorecord_to) + viewer->setAutoRecord(opts.autorecord_from, opts.autorecord_to); + if (opts.devkeys) + viewer->setDeviceKeys(true); + viewer->setRecordDither(opts.dither); + if (opts.recordargs.count()) + viewer->setRecordArgs(opts.recordargs); + + viewer->setUseNativeFileBrowser(opts.useNativeFileBrowser); + + return viewer; +} + +void showViewer(QDeclarativeViewer *viewer) +{ + if (opts.fullScreen) + viewer->showFullScreen(); + else if (opts.maximized) + viewer->showMaximized(); + else + viewer->show(); + viewer->raise(); +} + +QDeclarativeViewer *openFile(const QString &fileName) +{ + QDeclarativeViewer *viewer = globalViewer; + + viewer->open(fileName); + showViewer(viewer); + + return viewer; +} + +int main(int argc, char ** argv) +{ + systemMsgOutput = qInstallMsgHandler(myMessageOutput); + +#if defined (Q_WS_X11) || defined (Q_WS_MAC) + //### default to using raster graphics backend for now + bool gsSpecified = false; + for (int i = 0; i < argc; ++i) { + QString arg = argv[i]; + if (arg == "-graphicssystem") { + gsSpecified = true; + break; + } + } + + if (!gsSpecified) + QApplication::setGraphicsSystem("raster"); +#endif + + QDeclarativeDebugHelper::enableDebugging(); + + Application app(argc, argv); + app.setApplicationName("QtQmlViewer"); + app.setOrganizationName("Nokia"); + app.setOrganizationDomain("nokia.com"); + + QDeclarativeViewer::registerTypes(); + QDeclarativeTester::registerTypes(); + + parseCommandLineOptions(app.arguments()); + + QTranslator qmlTranslator; + if (!opts.translationFile.isEmpty()) { + if (qmlTranslator.load(opts.translationFile)) { + app.installTranslator(&qmlTranslator); + } else { + qWarning() << "Could not load the translation file" << opts.translationFile; + } + } + + if (opts.fullScreen && opts.maximized) + qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen."; + + if (fileNames.isEmpty()) { + QFile qmlapp(QLatin1String("qmlapp")); + if (qmlapp.exists() && qmlapp.open(QFile::ReadOnly)) { + QString content = QString::fromUtf8(qmlapp.readAll()); + qmlapp.close(); + + int newline = content.indexOf(QLatin1Char('\n')); + if (newline >= 0) + fileNames += content.left(newline); + else + fileNames += content; + } + } + + globalViewer = createViewer(); + + if (fileNames.isEmpty()) { + // show the initial viewer delayed. + // This prevents an initial viewer popping up while there + // are FileOpen events coming through the event queue + QTimer::singleShot(1, &app, SLOT(showInitialViewer())); + } else { + foreach (const QString &fileName, fileNames) + openFile(fileName); + } + + QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); + + return app.exec(); +} + +#include "main.moc" |