diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-04-30 04:58:56 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-04-30 04:58:56 (GMT) |
commit | 72afedd7fad133b390cc63fd04e3cf0cee757e2e (patch) | |
tree | d1312ea6a560299d0014869f36b39cba86428699 /tools/qmlviewer | |
parent | 28936246e547234f727a923d2542d92f766fb2e0 (diff) | |
download | Qt-72afedd7fad133b390cc63fd04e3cf0cee757e2e.zip Qt-72afedd7fad133b390cc63fd04e3cf0cee757e2e.tar.gz Qt-72afedd7fad133b390cc63fd04e3cf0cee757e2e.tar.bz2 |
Rename duiviewer to qmlviewer.
Diffstat (limited to 'tools/qmlviewer')
-rw-r--r-- | tools/qmlviewer/main.cpp | 135 | ||||
-rw-r--r-- | tools/qmlviewer/qmlviewer.cpp | 366 | ||||
-rw-r--r-- | tools/qmlviewer/qmlviewer.h | 72 | ||||
-rw-r--r-- | tools/qmlviewer/qmlviewer.pro | 12 |
4 files changed, 585 insertions, 0 deletions
diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp new file mode 100644 index 0000000..c5676ab --- /dev/null +++ b/tools/qmlviewer/main.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include "qml.h" +#include "qmlviewer.h" +#include <QWidget> +#include <QDir> +#include "qfxtestengine.h" +#include <QApplication> + + +void usage() +{ + qWarning("Usage: qmlviewer [options] <filename>"); + qWarning(" "); + qWarning(" options:"); + qWarning(" -v, -version ............................. display version"); + qWarning(" -frameless ............................... run with no window frame"); + qWarning(" -skin <qvfbskindir> ...................... run with a skin window frame"); + qWarning(" -recorddither ordered|threshold|floyd .... set dither mode used for recording"); + qWarning(" -recordperiod <milliseconds> ............. set time between recording frames"); + qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop automatically"); + qWarning(" -devicekeys .............................. use numeric keys (see F1)"); + qWarning(" -cache ................................... enable a disk cache of remote content"); + qWarning(" -recordtest <directory> .................. record an autotest"); + qWarning(" -runtest <directory> ..................... run a previously recorded test"); + qWarning(" "); + qWarning(" Press F1 for interactive help"); + exit(1); +} + +int main(int argc, char ** argv) +{ + //### default to using raster graphics backend for now + int newargc = argc + 2; + char **newargv; + newargv = new char * [newargc]; + for (int i = 0; i < argc; ++i) { + newargv[i] = argv[i]; + if (!qstrcmp(argv[i], "-graphicssystem")) { + newargc -= 2; + break; + } + } + char system[] = "-graphicssystem"; + newargv[argc] = system; + char raster[] = "raster"; + newargv[argc+1] = raster; + + + QApplication app(newargc, newargv); + app.setApplicationName("viewer"); + + bool frameless = false; + QString fileName; + int period = 0; + int autorecord_from = 0; + int autorecord_to = 0; + QString dither = "threshold"; + QString skin; + bool devkeys = false; + bool cache = false; + QFxTestEngine::TestMode testMode = QFxTestEngine::NoTest; + QString testDir; + + for (int i = 1; i < newargc; ++i) { + QString arg = newargv[i]; + if (arg == "-frameless") { + frameless = true; + } else if (arg == "-skin") { + skin = QString(argv[++i]); + } else if (arg == "-cache") { + cache = true; + } else if (arg == "-recordperiod") { + period = QString(argv[++i]).toInt(); + } else if (arg == "-autorecord") { + QString range = QString(argv[++i]); + int dash = range.indexOf('-'); + if (dash > 0) + autorecord_from = range.left(dash).toInt(); + autorecord_to = range.mid(dash+1).toInt(); + } else if (arg == "-devicekeys") { + devkeys = true; + } else if (arg == "-recordtest") { + testMode = QFxTestEngine::RecordTest; + if(i + 1 >= newargc) + usage(); + testDir = newargv[i + 1]; + ++i; + } else if (arg == "-runtest") { + testMode = QFxTestEngine::PlaybackTest; + if(i + 1 >= newargc) + usage(); + testDir = newargv[i + 1]; + ++i; + } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) { + fprintf(stderr, "Qt Declarative UI Viewer version %s\n", QT_VERSION_STR); + return 0; + } else if (arg[0] != '-') { + fileName = arg; + } else if (1 || arg == "-help") { + usage(); + } + } + + if (fileName.isEmpty()) + usage(); + + QmlViewer viewer(testMode, testDir, 0, frameless ? Qt::FramelessWindowHint : Qt::Widget); + viewer.setCacheEnabled(cache); + viewer.openQml(fileName); + if (period>0) + viewer.setRecordPeriod(period); + if (autorecord_to) + viewer.setAutoRecord(autorecord_from,autorecord_to); + if (QDir(skin).exists()) + viewer.setSkin(skin); + if (devkeys) + viewer.setDeviceKeys(true); + viewer.setRecordDither(dither); + viewer.show(); + + return app.exec(); +} + diff --git a/tools/qmlviewer/qmlviewer.cpp b/tools/qmlviewer/qmlviewer.cpp new file mode 100644 index 0000000..87bebfa --- /dev/null +++ b/tools/qmlviewer/qmlviewer.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#include <qfxview.h> + +#include "qmlbindablevalue.h" +#include "qmlviewer.h" +#include <QtDeclarative/qmlcontext.h> +#include <QtDeclarative/qmlengine.h> +#include "qml.h" +#include "qperformancelog.h" +#include "qfxtestengine.h" +#include "deviceskin.h" + +#include <QNetworkDiskCache> +#include <QNetworkAccessManager> +#include <QmlComponent> +#include <QWidget> +#include <QApplication> +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QVBoxLayout> +#include <QProcess> +#include <QMenu> + +QmlViewer::QmlViewer(QFxTestEngine::TestMode testMode, const QString &testDir, QWidget *parent, Qt::WindowFlags flags) + : QWidget(parent, flags) +{ + testEngine = 0; + devicemode = false; + skin = 0; + canvas = 0; + record_autotime = 0; + record_period = 20; + + int width=240; + int height=320; + setAttribute(Qt::WA_OpaquePaintEvent); + setAttribute(Qt::WA_NoSystemBackground); + + canvas = new QFxView(this); + if(testMode != QFxTestEngine::NoTest) + testEngine = new QFxTestEngine(testMode, testDir, canvas, this); + + QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize))); + canvas->setFixedSize(width, height); + resize(width, height); +} + +void QmlViewer::reload() +{ + openQml(currentFileName); +} + +void QmlViewer::openQml(const QString& fileName) +{ + setWindowTitle(tr("%1 - Qt Declarative UI Viewer").arg(fileName)); + + canvas->reset(); + + currentFileName = fileName; + QUrl url(fileName); + QFileInfo fi(fileName); + if (fi.exists()) { + url = QUrl::fromLocalFile(fi.absoluteFilePath()); + QmlContext *ctxt = canvas->rootContext(); + QDir dir(fi.path()+"/dummydata", "*.qml"); + QStringList list = dir.entryList(); + for (int i = 0; i < list.size(); ++i) { + QString qml = list.at(i); + QFile f(dir.filePath(qml)); + f.open(QIODevice::ReadOnly); + QByteArray data = f.readAll(); + QmlComponent comp(canvas->engine()); + comp.setData(data, QUrl()); + QObject *dummyData = comp.create(); + if (dummyData) { + qWarning() << "Loaded dummy data:" << dir.filePath(qml); + qml.truncate(qml.length()-4); + ctxt->setContextProperty(qml, dummyData); + dummyData->setParent(this); + } + } + } + + canvas->setUrl(url); + + QTime t; + t.start(); + canvas->execute(); + qWarning() << "Wall startup time:" << t.elapsed(); +#ifdef QTOPIA + show(); +#endif +} + +class PreviewDeviceSkin : public DeviceSkin +{ + Q_OBJECT +public: + explicit PreviewDeviceSkin(const DeviceSkinParameters ¶meters, QWidget *parent); + + void setPreview(QWidget *formWidget); + void setScreenSize(const QSize& size) + { + QMatrix fit; + fit = fit.scale(qreal(size.width())/m_screenSize.width(), + qreal(size.height())/m_screenSize.height()); + setTransform(fit); + } + +private slots: + void slotSkinKeyPressEvent(int code, const QString& text, bool autorep); + void slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep); + void slotPopupMenu(); + +private: + void populateContextMenu(QMenu *menu); + const QSize m_screenSize; +}; + + +PreviewDeviceSkin::PreviewDeviceSkin(const DeviceSkinParameters ¶meters, QWidget *parent) : + DeviceSkin(parameters, parent), + m_screenSize(parameters.screenSize()) +{ + connect(this, SIGNAL(skinKeyPressEvent(int,QString,bool)), + this, SLOT(slotSkinKeyPressEvent(int,QString,bool))); + connect(this, SIGNAL(skinKeyReleaseEvent(int,QString,bool)), + this, SLOT(slotSkinKeyReleaseEvent(int,QString,bool))); + connect(this, SIGNAL(popupMenu()), this, SLOT(slotPopupMenu())); +} + +void PreviewDeviceSkin::setPreview(QWidget *formWidget) +{ + formWidget->setFixedSize(m_screenSize); + formWidget->setParent(this, Qt::SubWindow); + formWidget->setAutoFillBackground(true); + setView(formWidget); +} + +void PreviewDeviceSkin::slotSkinKeyPressEvent(int code, const QString& text, bool autorep) +{ + if (QWidget *focusWidget = QApplication::focusWidget()) { + QKeyEvent e(QEvent::KeyPress,code,0,text,autorep); + QApplication::sendEvent(focusWidget, &e); + } + +} + +void PreviewDeviceSkin::slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep) +{ + if (QWidget *focusWidget = QApplication::focusWidget()) { + QKeyEvent e(QEvent::KeyRelease,code,0,text,autorep); + QApplication::sendEvent(focusWidget, &e); + } +} + +void PreviewDeviceSkin::slotPopupMenu() +{ + QMenu menu(this); + populateContextMenu(&menu); + menu.exec(QCursor::pos()); +} + +void PreviewDeviceSkin::populateContextMenu(QMenu *menu) +{ + connect(menu->addAction(tr("&Close")), SIGNAL(triggered()), parentWidget(), SLOT(close())); +} + + +void QmlViewer::setSkin(const QString& skinDirectory) +{ + DeviceSkinParameters parameters; + QString err; + if (parameters.read(skinDirectory,DeviceSkinParameters::ReadAll,&err)) { + delete skin; + if (!err.isEmpty()) + qWarning() << err; + skin = new PreviewDeviceSkin(parameters,this); + skin->setScreenSize(canvas->size()); + canvas->setParent(skin, Qt::SubWindow); + canvas->setAutoFillBackground(true); + skin->setView(canvas); + delete layout(); + + canvas->show(); + } +} + +void QmlViewer::setAutoRecord(int from, int to) +{ + record_autotime = to-from; + if (from) { + autoStartTimer.start(from,this); + } else { + autoTimer.start(); + setRecording(true); + } +} + +void QmlViewer::setRecordPeriod(int ms) +{ + record_period = ms; +} + +void QmlViewer::sceneResized(QSize size) +{ + if (size.width() > 0 && size.height() > 0) { + canvas->setFixedSize(size.width(), size.height()); + if (skin) + skin->setScreenSize(size); + else + resize(size); + } +} + +void QmlViewer::resizeEvent(QResizeEvent *) +{ + if (!skin) + canvas->setFixedSize(width(),height()); +} + +void QmlViewer::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_0 && devicemode) + exit(0); + else if (event->key() == Qt::Key_F1 || (event->key() == Qt::Key_1 && devicemode)) { + qDebug() << "F1 - help\n" + << "F2 - toggle GIF recording\n" + << "F3 - take PNG snapshot\n" + << "F4 - show items and state\n" + << "F5 - reload XML\n" + << "F6 - show object tree\n" + << "F7 - show timing\n" + << "F8 - show performance (if available)\n" + << "device keys: 0=quit, 1..8=F1..F8" + ; + } else if (event->key() == Qt::Key_F2 || (event->key() == Qt::Key_2 && devicemode)) { + setRecording(!recordTimer.isActive()); + } else if (event->key() == Qt::Key_F3 || (event->key() == Qt::Key_3 && devicemode)) { + canvas->asImage().save("snapshot.png"); + qDebug() << "Wrote snapshot.png"; + } else if (event->key() == Qt::Key_F4 || (event->key() == Qt::Key_4 && devicemode)) { + canvas->dumpItems(); + canvas->checkState(); + } else if (event->key() == Qt::Key_F5 || (event->key() == Qt::Key_5 && devicemode)) { + reload(); + } else if (event->key() == Qt::Key_F6 || (event->key() == Qt::Key_6 && devicemode)) { + canvas->dumpRoot(); + } else if (event->key() == Qt::Key_F7 || (event->key() == Qt::Key_7 && devicemode)) { + canvas->dumpTiming(); + } else if (event->key() == Qt::Key_F8 || (event->key() == Qt::Key_8 && devicemode)) { + QPerformanceLog::displayData(); + QPerformanceLog::clear(); + } else if (event->key() == Qt::Key_F9) { + if(testEngine) testEngine->save(); + } else if (event->key() == Qt::Key_F10) { + if(testEngine) testEngine->captureFullFrame(); + } + + QWidget::keyPressEvent(event); +} + +void QmlViewer::setRecording(bool on) +{ + if (on == recordTimer.isActive()) + return; + + if (on) { + recordTimer.start(record_period,this); + } else { + recordTimer.stop(); + int frame=0; + QStringList inputs; + qDebug() << "Saving frames..."; + + foreach (QImage* img, frames) { + QString name; + name.sprintf("tmp-frame%04d.png",frame++); + if (record_dither=="ordered") + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::OrderedDither).save(name); + else if (record_dither=="threshold") + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::ThresholdDither).save(name); + else if (record_dither=="floyd") + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither).save(name); + else + img->convertToFormat(QImage::Format_Indexed8).save(name); + inputs << name; + delete img; + } + QString output="animation.gif"; + + QStringList args; + + args << "-delay" << QString::number(record_period/10); + args << inputs; + args << output; + qDebug() << "Converting..." << output; + if (0!=QProcess::execute("convert", args)) { + qWarning() << "Cannot run ImageMagick 'convert' - not converted to gif"; + inputs.clear(); // don't remove them + qDebug() << "Wrote frames tmp-frame*.png"; + } else { + qDebug() << "Compressing..." << output; + if (0!=QProcess::execute("gifsicle", QStringList() << "-O2" << "-o" << output << output)) + qWarning() << "Cannot run 'gifsicle' - not compressed"; + qDebug() << "Wrote" << output; + } + + foreach (QString name, inputs) + QFile::remove(name); + + frames.clear(); + } + qDebug() << "Recording: " << (recordTimer.isActive()?"ON":"OFF"); +} + +void QmlViewer::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == recordTimer.timerId()) { + frames.append(new QImage(canvas->asImage())); + if (record_autotime && autoTimer.elapsed() >= record_autotime) + setRecording(false); + } else if (event->timerId() == autoStartTimer.timerId()) { + autoTimer.start(); + autoStartTimer.stop(); + setRecording(true); + } else { + QWidget::timerEvent(event); + } +} + +void QmlViewer::setDeviceKeys(bool on) +{ + devicemode = on; +} + +void QmlViewer::setCacheEnabled(bool on) +{ + QNetworkAccessManager * nam = canvas->engine()->networkAccessManager(); + if (on == !!nam->cache()) + return; + if (on) { + // Setup a caching network manager + QNetworkDiskCache *cache = new QNetworkDiskCache; + cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-duiviewer-network-cache")); + cache->setMaximumCacheSize(8000000); + nam->setCache(cache); + } else { + nam->setCache(0); + } +} + +#include "qmlviewer.moc" diff --git a/tools/qmlviewer/qmlviewer.h b/tools/qmlviewer/qmlviewer.h new file mode 100644 index 0000000..0fa879d --- /dev/null +++ b/tools/qmlviewer/qmlviewer.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 1992-$THISYEAR$ $TROLLTECH$. All rights reserved. +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +****************************************************************************/ + +#ifndef QMLVIEWER_H +#define QMLVIEWER_H + +#include <QWidget> +#include <QBasicTimer> +#include <QTime> +#include <qfxtestengine.h> +#include <QList> + + +class QFxView; +class PreviewDeviceSkin; +class QFxTestEngine; + +class QmlViewer : public QWidget +{ +Q_OBJECT +public: + QmlViewer(QFxTestEngine::TestMode = QFxTestEngine::NoTest, const QString &testDir = QString(), QWidget *parent=0, Qt::WindowFlags flags=0); + + void setRecordDither(const QString& s) { record_dither = s; } + void setRecordPeriod(int ms); + int recordPeriod() const { return record_period; } + void setRecording(bool on); + bool isRecording() const { return recordTimer.isActive(); } + void setAutoRecord(int from, int to); + void setSkin(const QString& skinDirectory); + void setDeviceKeys(bool); + void setCacheEnabled(bool); + +public slots: + void sceneResized(QSize size); + void openQml(const QString& fileName); + void reload(); + +protected: + virtual void keyPressEvent(QKeyEvent *); + virtual void timerEvent(QTimerEvent *); + virtual void resizeEvent(QResizeEvent *); + +private: + QString currentFileName; + PreviewDeviceSkin *skin; + QSize skinscreensize; + QFxView *canvas; + void init(QFxTestEngine::TestMode, const QString &, const QString& fileName); + QBasicTimer recordTimer; + QList<QImage*> frames; + QBasicTimer autoStartTimer; + QTime autoTimer; + QString record_dither; + int record_period; + int record_autotime; + bool devicemode; + + QFxTestEngine *testEngine; +}; + +#endif diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro new file mode 100644 index 0000000..08d2d2b --- /dev/null +++ b/tools/qmlviewer/qmlviewer.pro @@ -0,0 +1,12 @@ +DESTDIR = ../../bin +QT += declarative script network sql +# Input +HEADERS += qmlviewer.h +SOURCES += main.cpp qmlviewer.cpp + +include($$QT_SOURCE_TREE/tools/shared/deviceskin/deviceskin.pri) + +target.path=$$[QT_INSTALL_BINS] +INSTALLS += target + +CONFIG += console |