summaryrefslogtreecommitdiffstats
path: root/tools/qmlviewer
diff options
context:
space:
mode:
authorMichael Brasser <michael.brasser@nokia.com>2009-04-30 04:58:56 (GMT)
committerMichael Brasser <michael.brasser@nokia.com>2009-04-30 04:58:56 (GMT)
commit72afedd7fad133b390cc63fd04e3cf0cee757e2e (patch)
treed1312ea6a560299d0014869f36b39cba86428699 /tools/qmlviewer
parent28936246e547234f727a923d2542d92f766fb2e0 (diff)
downloadQt-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.cpp135
-rw-r--r--tools/qmlviewer/qmlviewer.cpp366
-rw-r--r--tools/qmlviewer/qmlviewer.h72
-rw-r--r--tools/qmlviewer/qmlviewer.pro12
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 &parameters, 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 &parameters, 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