summaryrefslogtreecommitdiffstats
path: root/tools/qml
diff options
context:
space:
mode:
Diffstat (limited to 'tools/qml')
-rw-r--r--tools/qml/content/Browser.qml243
-rw-r--r--tools/qml/content/images/folder.pngbin0 -> 1841 bytes
-rw-r--r--tools/qml/content/images/titlebar.pngbin0 -> 1436 bytes
-rw-r--r--tools/qml/content/images/titlebar.sci5
-rw-r--r--tools/qml/content/images/up.pngbin0 -> 662 bytes
-rw-r--r--tools/qml/deviceorientation.cpp75
-rw-r--r--tools/qml/deviceorientation.h73
-rw-r--r--tools/qml/deviceorientation_maemo.cpp139
-rw-r--r--tools/qml/main.cpp356
-rw-r--r--tools/qml/proxysettings.cpp110
-rw-r--r--tools/qml/proxysettings.h71
-rw-r--r--tools/qml/proxysettings.ui115
-rw-r--r--tools/qml/qdeclarativefolderlistmodel.cpp420
-rw-r--r--tools/qml/qdeclarativefolderlistmodel.h127
-rw-r--r--tools/qml/qfxtester.cpp381
-rw-r--r--tools/qml/qfxtester.h286
-rw-r--r--tools/qml/qml.pro58
-rw-r--r--tools/qml/qmlruntime.cpp1468
-rw-r--r--tools/qml/qmlruntime.h195
-rw-r--r--tools/qml/qmlruntime.qrc9
-rw-r--r--tools/qml/recopts.ui513
21 files changed, 4644 insertions, 0 deletions
diff --git a/tools/qml/content/Browser.qml b/tools/qml/content/Browser.qml
new file mode 100644
index 0000000..35120bc
--- /dev/null
+++ b/tools/qml/content/Browser.qml
@@ -0,0 +1,243 @@
+import Qt 4.6
+
+Rectangle {
+ id: root
+ property bool keyPressed: false
+ property var folders: folders1
+ property var view: view1
+ width: 320
+ height: 480
+ color: palette.window
+
+ FolderListModel {
+ id: folders1
+ nameFilters: [ "*.qml" ]
+ folder: qmlViewerFolder
+ }
+ FolderListModel {
+ id: folders2
+ nameFilters: [ "*.qml" ]
+ folder: qmlViewerFolder
+ }
+
+ SystemPalette { id: palette }
+
+ Script {
+ function down(path) {
+ if (folders == folders1) {
+ view = view2
+ folders = folders2;
+ view1.state = "exitLeft";
+ } else {
+ view = view1
+ folders = folders1;
+ view2.state = "exitLeft";
+ }
+ view.x = root.width;
+ view.state = "current";
+ view.focus = true;
+ folders.folder = path;
+ }
+ function up() {
+ var path = folders.parentFolder;
+ if (folders == folders1) {
+ view = view2
+ folders = folders2;
+ view1.state = "exitRight";
+ } else {
+ view = view1
+ folders = folders1;
+ view2.state = "exitRight";
+ }
+ view.x = -root.width;
+ view.state = "current";
+ view.focus = true;
+ folders.folder = path;
+ }
+ }
+
+ Component {
+ id: folderDelegate
+ Rectangle {
+ id: wrapper
+ function launch() {
+ if (folders.isFolder(index)) {
+ down(filePath);
+ } else {
+ qmlViewer.launch(filePath);
+ }
+ }
+ width: root.width
+ height: 52
+ color: "transparent"
+ Rectangle {
+ id: highlight; visible: false
+ anchors.fill: parent
+ gradient: Gradient {
+ GradientStop { id: t1; position: 0.0; color: palette.highlight }
+ GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
+ }
+ }
+ Item {
+ width: 48; height: 48
+ Image { source: "images/folder.png"; anchors.centerIn: parent; visible: folders.isFolder(index)}
+ }
+ Text {
+ id: nameText
+ anchors.fill: parent; verticalAlignment: Text.AlignVCenter
+ text: fileName
+ anchors.leftMargin: 54
+ font.pixelSize: 32
+ color: (wrapper.ListView.isCurrentItem && root.keyPressed) ? palette.highlightedText : palette.windowText
+ }
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: parent
+ onClicked: { launch() }
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: mouseRegion.pressed
+ PropertyChanges { target: highlight; visible: true }
+ PropertyChanges { target: nameText; color: palette.highlightedText }
+ }
+ ]
+ }
+ }
+
+ ListView {
+ id: view1
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+ x: 0
+ width: parent.width
+ model: folders1
+ delegate: folderDelegate
+ highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view1.count != 0 }
+ highlightMoveSpeed: 1000
+ pressDelay: 100
+ focus: true
+ state: "current"
+ states: [
+ State {
+ name: "current"
+ PropertyChanges { target: view1; x: 0 }
+ },
+ State {
+ name: "exitLeft"
+ PropertyChanges { target: view1; x: -root.width }
+ },
+ State {
+ name: "exitRight"
+ PropertyChanges { target: view1; x: root.width }
+ }
+ ]
+ transitions: [
+ Transition {
+ to: "current"
+ SequentialAnimation {
+ NumberAnimation { matchProperties: "x"; duration: 250 }
+ }
+ },
+ Transition {
+ NumberAnimation { matchProperties: "x"; duration: 250 }
+ NumberAnimation { matchProperties: "x"; duration: 250 }
+ }
+ ]
+ Keys.onPressed: { root.keyPressed = true; }
+ }
+
+ ListView {
+ id: view2
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+ x: parent.width
+ width: parent.width
+ model: folders2
+ delegate: folderDelegate
+ highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view2.count != 0 }
+ highlightMoveSpeed: 1000
+ pressDelay: 100
+ states: [
+ State {
+ name: "current"
+ PropertyChanges { target: view2; x: 0 }
+ },
+ State {
+ name: "exitLeft"
+ PropertyChanges { target: view2; x: -root.width }
+ },
+ State {
+ name: "exitRight"
+ PropertyChanges { target: view2; x: root.width }
+ }
+ ]
+ transitions: [
+ Transition {
+ to: "current"
+ SequentialAnimation {
+ NumberAnimation { matchProperties: "x"; duration: 250 }
+ }
+ },
+ Transition {
+ NumberAnimation { matchProperties: "x"; duration: 250 }
+ }
+ ]
+ Keys.onPressed: { root.keyPressed = true; }
+ }
+
+ Keys.onPressed: {
+ root.keyPressed = true;
+ if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) {
+ view.currentItem.launch();
+ event.accepted = true;
+ } else if (event.key == Qt.Key_Left) {
+ up();
+ }
+ }
+
+ BorderImage {
+ source: "images/titlebar.sci";
+ width: parent.width;
+ height: 52
+ y: -7
+ id: titleBar
+
+ Rectangle {
+ id: upButton
+ width: 48
+ height: titleBar.height - 7
+ color: "transparent"
+
+ Image { anchors.centerIn: parent; source: "images/up.png" }
+ MouseArea { id: upRegion; anchors.centerIn: parent
+ width: 56
+ height: 56
+ onClicked: if (folders.parentFolder != "") up()
+ }
+ states: [
+ State {
+ name: "pressed"
+ when: upRegion.pressed
+ PropertyChanges { target: upButton; color: palette.highlight }
+ }
+ ]
+ }
+ Rectangle {
+ color: "gray"
+ x: 48
+ width: 1
+ height: 44
+ }
+
+ Text {
+ anchors.left: upButton.right; anchors.right: parent.right; height: parent.height
+ anchors.leftMargin: 4; anchors.rightMargin: 4
+ text: folders.folder
+ color: "white"
+ elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter
+ font.pixelSize: 32
+ }
+ }
+}
diff --git a/tools/qml/content/images/folder.png b/tools/qml/content/images/folder.png
new file mode 100644
index 0000000..e53e2ad
--- /dev/null
+++ b/tools/qml/content/images/folder.png
Binary files differ
diff --git a/tools/qml/content/images/titlebar.png b/tools/qml/content/images/titlebar.png
new file mode 100644
index 0000000..51c9008
--- /dev/null
+++ b/tools/qml/content/images/titlebar.png
Binary files differ
diff --git a/tools/qml/content/images/titlebar.sci b/tools/qml/content/images/titlebar.sci
new file mode 100644
index 0000000..0418d94
--- /dev/null
+++ b/tools/qml/content/images/titlebar.sci
@@ -0,0 +1,5 @@
+border.left: 10
+border.top: 12
+border.bottom: 12
+border.right: 10
+source: titlebar.png
diff --git a/tools/qml/content/images/up.png b/tools/qml/content/images/up.png
new file mode 100644
index 0000000..b05f802
--- /dev/null
+++ b/tools/qml/content/images/up.png
Binary files differ
diff --git a/tools/qml/deviceorientation.cpp b/tools/qml/deviceorientation.cpp
new file mode 100644
index 0000000..e7c70d5
--- /dev/null
+++ b/tools/qml/deviceorientation.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "deviceorientation.h"
+
+QT_USE_NAMESPACE
+
+class DefaultDeviceOrientation : public DeviceOrientation
+{
+ Q_OBJECT
+public:
+ DefaultDeviceOrientation() : DeviceOrientation(), m_orientation(DeviceOrientation::Portrait) {}
+
+ Orientation orientation() const {
+ return m_orientation;
+ }
+
+ void setOrientation(Orientation o) {
+ if (o != m_orientation) {
+ m_orientation = o;
+ emit orientationChanged();
+ }
+ }
+
+ Orientation m_orientation;
+};
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static DefaultDeviceOrientation *o = 0;
+ if (!o)
+ o = new DefaultDeviceOrientation;
+ return o;
+}
+
+#include "deviceorientation.moc"
+
diff --git a/tools/qml/deviceorientation.h b/tools/qml/deviceorientation.h
new file mode 100644
index 0000000..c8125cd
--- /dev/null
+++ b/tools/qml/deviceorientation.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+#ifndef ORIENTATION_H
+#define ORIENTATION_H
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class DeviceOrientationPrivate;
+class DeviceOrientation : public QObject
+{
+ Q_OBJECT
+public:
+ enum Orientation { UnknownOrientation, Portrait, Landscape };
+ virtual Orientation orientation() const = 0;
+ virtual void setOrientation(Orientation) = 0;
+
+ static DeviceOrientation *instance();
+
+signals:
+ void orientationChanged();
+
+protected:
+ DeviceOrientation() {}
+
+private:
+ DeviceOrientationPrivate *d_ptr;
+ friend class DeviceOrientationPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qml/deviceorientation_maemo.cpp b/tools/qml/deviceorientation_maemo.cpp
new file mode 100644
index 0000000..fa2c6e5
--- /dev/null
+++ b/tools/qml/deviceorientation_maemo.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "deviceorientation.h"
+#include <stdio.h>
+#include <stdlib.h>
+
+class MaemoOrientation : public DeviceOrientation
+{
+ Q_OBJECT
+public:
+ MaemoOrientation()
+ : DeviceOrientation(),m_current(Portrait), m_lastSeen(Portrait), m_lastSeenCount(0)
+ {
+ startTimer(100);
+ }
+
+ Orientation orientation() const {
+ return m_current;
+ }
+
+ void setOrientation(Orientation orient) {
+ //XXX maybe better to just ignore
+ if (orient != m_current) {
+ m_current = orient;
+ emit orientationChanged();
+ }
+ }
+
+
+protected:
+ virtual void timerEvent(QTimerEvent *)
+ {
+ Orientation c = get();
+
+ if (c == m_lastSeen) {
+ m_lastSeenCount++;
+ } else {
+ m_lastSeenCount = 0;
+ m_lastSeen = c;
+ }
+
+ if (m_lastSeen != UnknownOrientation && m_lastSeen != m_current && m_lastSeenCount > 4) {
+ m_current = m_lastSeen;
+ emit orientationChanged();
+ printf("%d\n", m_current);
+ }
+ }
+
+signals:
+ void changed();
+
+private:
+ Orientation m_current;
+ Orientation m_lastSeen;
+ int m_lastSeenCount;
+
+ Orientation get()
+ {
+ Orientation o = UnknownOrientation;
+
+ int ax, ay, az;
+
+ read(&ax, &ay, &az);
+
+ if (abs(az) > 850) {
+ o = UnknownOrientation;
+ } else if (ax < -750) {
+ o = Portrait;
+ } else if (ay < -750) {
+ o = Landscape;
+ }
+
+ return o;
+ }
+
+ int read(int *ax,int *ay,int *az)
+ {
+ static const char *accel_filename = "/sys/class/i2c-adapter/i2c-3/3-001d/coord";
+
+ FILE *fd;
+ int rs;
+ fd = fopen(accel_filename, "r");
+ if(fd==NULL){ printf("liqaccel, cannot open for reading\n"); return -1;}
+ rs=fscanf((FILE*) fd,"%i %i %i",ax,ay,az);
+ fclose(fd);
+ if(rs != 3){ printf("liqaccel, cannot read information\n"); return -2;}
+ return 0;
+ }
+};
+
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static MaemoOrientation *o = 0;
+ if (!o)
+ o = new MaemoOrientation;
+ return o;
+}
+
+#include "deviceorientation_maemo.moc"
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
new file mode 100644
index 0000000..9ef02ac
--- /dev/null
+++ b/tools/qml/main.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 <QWidget>
+#include <QDir>
+#include <QApplication>
+#include <QTranslator>
+#include <QDebug>
+#include "qfxtester.h"
+#include "qdeclarativefolderlistmodel.h"
+
+QT_USE_NAMESPACE
+
+#if defined (Q_OS_SYMBIAN)
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+void myMessageOutput(QtMsgType type, const char *msg)
+{
+ 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
+
+void usage()
+{
+ qWarning("Usage: qml [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(" -skin <qvfbskindir> ...................... run with a skin window frame");
+ qWarning(" \"list\" for a list of built-ins");
+ qWarning(" -resizeview .............................. resize the view, not the skin");
+ qWarning(" -qmlbrowser .............................. use a QML-based file browser");
+ 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(" -L <directory> ........................... prepend to the library search path");
+ qWarning(" -opengl .................................. use a QGLWidget for the viewport");
+ 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");
+ exit(1);
+}
+
+void scriptOptsUsage()
+{
+ qWarning("Usage: qml -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(" 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.");
+ exit(1);
+}
+
+int main(int argc, char ** argv)
+{
+#if defined (Q_OS_SYMBIAN)
+ qInstallMsgHandler(myMessageOutput);
+#endif
+
+#if defined (Q_WS_X11)
+ //### 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
+
+ QApplication app(argc, argv);
+ app.setApplicationName("viewer");
+ app.setOrganizationName("Nokia");
+ app.setOrganizationDomain("nokia.com");
+
+ QDeclarativeViewer::registerTypes();
+ QDeclarativeTester::registerTypes();
+ QDeclarativeFolderListModel::registerTypes();
+
+ bool frameless = false;
+ bool resizeview = false;
+ QString fileName;
+ double fps = 0;
+ int autorecord_from = 0;
+ int autorecord_to = 0;
+ QString dither = "none";
+ QString recordfile;
+ QStringList recordargs;
+ QStringList libraries;
+ QString skin;
+ QString script;
+ QString scriptopts;
+ bool runScript = false;
+ bool devkeys = false;
+ int cache = 0;
+ QString translationFile;
+ bool useGL = false;
+ bool fullScreen = false;
+ bool stayOnTop = false;
+ bool maximized = false;
+ bool useNativeFileBrowser = true;
+
+#if defined(Q_OS_SYMBIAN)
+ maximized = true;
+ useNativeFileBrowser = false;
+#endif
+
+ for (int i = 1; i < argc; ++i) {
+ bool lastArg = (i == argc - 1);
+ QString arg = argv[i];
+ if (arg == "-frameless") {
+ frameless = true;
+ } else if (arg == "-maximized") {
+ maximized = true;
+ } else if (arg == "-fullscreen") {
+ fullScreen = true;
+ } else if (arg == "-stayontop") {
+ stayOnTop = true;
+ } else if (arg == "-skin") {
+ if (lastArg) usage();
+ skin = QString(argv[++i]);
+ } else if (arg == "-resizeview") {
+ resizeview = true;
+ } else if (arg == "-netcache") {
+ if (lastArg) usage();
+ cache = QString(argv[++i]).toInt();
+ } else if (arg == "-recordrate") {
+ if (lastArg) usage();
+ fps = QString(argv[++i]).toDouble();
+ } else if (arg == "-recordfile") {
+ if (lastArg) usage();
+ recordfile = QString(argv[++i]);
+ } else if (arg == "-record") {
+ if (lastArg) usage();
+ recordargs << QString(argv[++i]);
+ } else if (arg == "-recorddither") {
+ if (lastArg) usage();
+ dither = QString(argv[++i]);
+ } else if (arg == "-autorecord") {
+ if (lastArg) usage();
+ 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 == "-dragthreshold") {
+ if (lastArg) usage();
+ app.setStartDragDistance(QString(argv[++i]).toInt());
+ } 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 == "-translation") {
+ if (lastArg) usage();
+ translationFile = argv[++i];
+ } else if (arg == "-opengl") {
+ useGL = true;
+ } else if (arg == "-qmlbrowser") {
+ useNativeFileBrowser = false;
+ } else if (arg == "-L") {
+ if (lastArg) usage();
+ libraries << QString(argv[++i]);
+ } else if (arg == "-script") {
+ if (lastArg) usage();
+ script = QString(argv[++i]);
+ } else if (arg == "-scriptopts") {
+ if (lastArg) usage();
+ scriptopts = QString(argv[++i]);
+ } else if (arg == "-savescript") {
+ if (lastArg) usage();
+ script = QString(argv[++i]);
+ runScript = false;
+ } else if (arg == "-playscript") {
+ if (lastArg) usage();
+ script = QString(argv[++i]);
+ runScript = true;
+ } else if (arg[0] != '-') {
+ fileName = arg;
+ } else if (1 || arg == "-help") {
+ usage();
+ }
+ }
+
+ QTranslator qmlTranslator;
+ if (!translationFile.isEmpty()) {
+ qmlTranslator.load(translationFile);
+ app.installTranslator(&qmlTranslator);
+ }
+
+ Qt::WFlags wflags = (frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ if (stayOnTop)
+ wflags |= Qt::WindowStaysOnTopHint;
+
+ QDeclarativeViewer viewer(0, wflags);
+ if (!scriptopts.isEmpty()) {
+ QStringList options =
+ 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("exitoncomplete")) {
+ scriptOptions |= QDeclarativeViewer::ExitOnComplete;
+ } else if (option == QLatin1String("exitonfailure")) {
+ scriptOptions |= QDeclarativeViewer::ExitOnFailure;
+ } else if (option == QLatin1String("saveonexit")) {
+ scriptOptions |= QDeclarativeViewer::SaveOnExit;
+ } else {
+ scriptOptsUsage();
+ }
+ }
+
+ if (script.isEmpty())
+ usage();
+
+ if (!(scriptOptions & QDeclarativeViewer::Record) && !(scriptOptions & QDeclarativeViewer::Play))
+ scriptOptsUsage();
+ viewer.setScriptOptions(scriptOptions);
+ viewer.setScript(script);
+ } else if (!script.isEmpty()) {
+ usage();
+ }
+
+ foreach (QString lib, libraries)
+ viewer.addLibraryPath(lib);
+ viewer.setNetworkCacheSize(cache);
+ viewer.setRecordFile(recordfile);
+ if (resizeview)
+ viewer.setScaleView();
+ if (fps>0)
+ viewer.setRecordRate(fps);
+ if (autorecord_to)
+ viewer.setAutoRecord(autorecord_from,autorecord_to);
+ if (!skin.isEmpty()) {
+ if (skin == "list") {
+ foreach (QString s, viewer.builtinSkins())
+ qWarning(s.toUtf8());
+ exit(0);
+ } else {
+ viewer.setSkin(skin);
+ }
+ }
+ if (devkeys)
+ viewer.setDeviceKeys(true);
+ viewer.setRecordDither(dither);
+ if (recordargs.count())
+ viewer.setRecordArgs(recordargs);
+
+ viewer.setUseNativeFileBrowser(useNativeFileBrowser);
+ if (fullScreen && maximized)
+ qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen.";
+ if (!fileName.isEmpty()) {
+ viewer.open(fileName);
+ fullScreen ? viewer.showFullScreen() : maximized ? viewer.showMaximized() : viewer.show();
+ } else {
+ if (!useNativeFileBrowser)
+ viewer.openFile();
+ fullScreen ? viewer.showFullScreen() : maximized ? viewer.showMaximized() : viewer.show();
+ if (useNativeFileBrowser)
+ viewer.openFile();
+ }
+ viewer.setUseGL(useGL);
+ viewer.raise();
+
+ return app.exec();
+}
diff --git a/tools/qml/proxysettings.cpp b/tools/qml/proxysettings.cpp
new file mode 100644
index 0000000..3255e42
--- /dev/null
+++ b/tools/qml/proxysettings.cpp
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 <QIntValidator>
+#include <QSettings>
+
+#include "proxysettings.h"
+
+QT_BEGIN_NAMESPACE
+
+ProxySettings::ProxySettings (QWidget * parent)
+ : QDialog (parent), Ui::ProxySettings()
+{
+ setupUi (this);
+
+ proxyServerEdit->setInputMask ("000.000.000.000;_");
+ QIntValidator *validator = new QIntValidator (0, 9999, this);
+ proxyPortEdit->setValidator (validator);
+
+ QSettings settings;
+ proxyCheckBox->setChecked (settings.value ("http_proxy/use", 0).toBool ());
+ proxyServerEdit->insert (settings.value ("http_proxy/hostname", "").toString ());
+ proxyPortEdit->insert (settings.value ("http_proxy/port", "80").toString ());
+ usernameEdit->insert (settings.value ("http_proxy/username", "").toString ());
+ passwordEdit->insert (settings.value ("http_proxy/password", "").toString ());
+}
+
+ProxySettings::~ProxySettings()
+{
+}
+
+void ProxySettings::accept ()
+{
+ QSettings settings;
+
+ settings.setValue ("http_proxy/use", proxyCheckBox->isChecked ());
+ settings.setValue ("http_proxy/hostname", proxyServerEdit->text ());
+ settings.setValue ("http_proxy/port", proxyPortEdit->text ());
+ settings.setValue ("http_proxy/username", usernameEdit->text ());
+ settings.setValue ("http_proxy/password", passwordEdit->text ());
+
+ QDialog::accept ();
+}
+
+QNetworkProxy ProxySettings::httpProxy ()
+{
+ QSettings settings;
+ QNetworkProxy proxy;
+
+ bool proxyInUse = settings.value ("http_proxy/use", 0).toBool ();
+ if (proxyInUse) {
+ proxy.setType (QNetworkProxy::HttpProxy);
+ proxy.setHostName (settings.value ("http_proxy/hostname", "").toString ());// "192.168.220.5"
+ proxy.setPort (settings.value ("http_proxy/port", 80).toInt ()); // 8080
+ proxy.setUser (settings.value ("http_proxy/username", "").toString ());
+ proxy.setPassword (settings.value ("http_proxy/password", "").toString ());
+ //QNetworkProxy::setApplicationProxy (proxy);
+ }
+ else {
+ proxy.setType (QNetworkProxy::NoProxy);
+ }
+ return proxy;
+}
+
+bool ProxySettings::httpProxyInUse()
+{
+ QSettings settings;
+ return settings.value ("http_proxy/use", 0).toBool ();
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qml/proxysettings.h b/tools/qml/proxysettings.h
new file mode 100644
index 0000000..325929a
--- /dev/null
+++ b/tools/qml/proxysettings.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+#ifndef PROXYSETTINGS_H
+#define PROXYSETTINGS_H
+
+#include <QDialog>
+#include <QNetworkProxy>
+#include "ui_proxysettings.h"
+
+QT_BEGIN_NAMESPACE
+/**
+*/
+class ProxySettings : public QDialog, public Ui::ProxySettings
+{
+
+Q_OBJECT
+
+public:
+ ProxySettings(QWidget * parent = 0);
+
+ ~ProxySettings();
+
+ static QNetworkProxy httpProxy ();
+ static bool httpProxyInUse ();
+
+public slots:
+ virtual void accept ();
+};
+
+QT_END_NAMESPACE
+
+#endif // PROXYSETTINGS_H
diff --git a/tools/qml/proxysettings.ui b/tools/qml/proxysettings.ui
new file mode 100644
index 0000000..84e39fe
--- /dev/null
+++ b/tools/qml/proxysettings.ui
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ProxySettings</class>
+ <widget class="QDialog" name="ProxySettings">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>318</width>
+ <height>199</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0" colspan="2">
+ <widget class="QCheckBox" name="proxyCheckBox">
+ <property name="text">
+ <string>Use http proxy</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="serverAddressLabel">
+ <property name="text">
+ <string>Server Address:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="proxyServerEdit"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Port:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="proxyPortEdit"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="usernameLabel">
+ <property name="text">
+ <string>Username:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="usernameEdit"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="passwordLabel">
+ <property name="text">
+ <string>Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLineEdit" name="passwordEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0" colspan="2">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ProxySettings</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ProxySettings</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/qml/qdeclarativefolderlistmodel.cpp b/tools/qml/qdeclarativefolderlistmodel.cpp
new file mode 100644
index 0000000..58bf59b
--- /dev/null
+++ b/tools/qml/qdeclarativefolderlistmodel.cpp
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples 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 "qdeclarativefolderlistmodel.h"
+#include <QDirModel>
+#include <QDebug>
+#include <qdeclarativecontext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeFolderListModelPrivate
+{
+public:
+ QDeclarativeFolderListModelPrivate()
+ : sortField(QDeclarativeFolderListModel::Name), sortReversed(false), count(0) {
+ nameFilters << QLatin1String("*");
+ }
+
+ void updateSorting() {
+ QDir::SortFlags flags = 0;
+ switch(sortField) {
+ case QDeclarativeFolderListModel::Unsorted:
+ flags |= QDir::Unsorted;
+ break;
+ case QDeclarativeFolderListModel::Name:
+ flags |= QDir::Name;
+ break;
+ case QDeclarativeFolderListModel::Time:
+ flags |= QDir::Time;
+ break;
+ case QDeclarativeFolderListModel::Size:
+ flags |= QDir::Size;
+ break;
+ case QDeclarativeFolderListModel::Type:
+ flags |= QDir::Type;
+ break;
+ }
+
+ if (sortReversed)
+ flags |= QDir::Reversed;
+
+ model.setSorting(flags);
+ }
+
+ QDirModel model;
+ QUrl folder;
+ QStringList nameFilters;
+ QModelIndex folderIndex;
+ QDeclarativeFolderListModel::SortField sortField;
+ bool sortReversed;
+ int count;
+};
+
+/*!
+ \qmlclass FolderListModel
+ \brief The FolderListModel provides a model of the contents of a folder in a filesystem.
+
+ FolderListModel provides access to the local filesystem. The \e folder property
+ specifies the folder to list.
+
+ Qt uses "/" as a universal directory separator in the same way that "/" is
+ used as a path separator in URLs. If you always use "/" as a directory
+ separator, Qt will translate your paths to conform to the underlying
+ operating system.
+
+ The roles available are:
+ \list
+ \o fileName
+ \o filePath
+ \endlist
+
+ Additionally a file entry can be differentiated from a folder entry
+ via the \l isFolder() method.
+*/
+
+QDeclarativeFolderListModel::QDeclarativeFolderListModel(QObject *parent)
+ : QListModelInterface(parent)
+{
+ d = new QDeclarativeFolderListModelPrivate;
+ d->model.setFilter(QDir::AllDirs | QDir::Files | QDir::Drives | QDir::NoDotAndDotDot);
+ connect(&d->model, SIGNAL(rowsInserted(const QModelIndex&,int,int))
+ , this, SLOT(inserted(const QModelIndex&,int,int)));
+ connect(&d->model, SIGNAL(rowsRemoved(const QModelIndex&,int,int))
+ , this, SLOT(removed(const QModelIndex&,int,int)));
+ connect(&d->model, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&))
+ , this, SLOT(dataChanged(const QModelIndex&,const QModelIndex&)));
+ connect(&d->model, SIGNAL(modelReset()), this, SLOT(refresh()));
+ connect(&d->model, SIGNAL(layoutChanged()), this, SLOT(refresh()));
+}
+
+QDeclarativeFolderListModel::~QDeclarativeFolderListModel()
+{
+ delete d;
+}
+
+QHash<int,QVariant> QDeclarativeFolderListModel::data(int index, const QList<int> &roles) const
+{
+ Q_UNUSED(roles);
+ QHash<int,QVariant> folderData;
+ QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex);
+ if (modelIndex.isValid()) {
+ folderData[QDirModel::FileNameRole] = d->model.data(modelIndex, QDirModel::FileNameRole);
+ folderData[QDirModel::FilePathRole] = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString());
+ }
+
+ return folderData;
+}
+
+QVariant QDeclarativeFolderListModel::data(int index, int role) const
+{
+ QVariant rv;
+ QModelIndex modelIndex = d->model.index(index, 0, d->folderIndex);
+ if (modelIndex.isValid()) {
+ if (role == QDirModel::FileNameRole)
+ rv = d->model.data(modelIndex, QDirModel::FileNameRole);
+ else if (role == QDirModel::FilePathRole)
+ rv = QUrl::fromLocalFile(d->model.data(modelIndex, QDirModel::FilePathRole).toString());
+ }
+
+ return rv;
+}
+
+int QDeclarativeFolderListModel::count() const
+{
+ return d->count;
+}
+
+QList<int> QDeclarativeFolderListModel::roles() const
+{
+ QList<int> r;
+ r << QDirModel::FileNameRole;
+ r << QDirModel::FilePathRole;
+ return r;
+}
+
+QString QDeclarativeFolderListModel::toString(int role) const
+{
+ switch (role) {
+ case QDirModel::FileNameRole:
+ return QLatin1String("fileName");
+ case QDirModel::FilePathRole:
+ return QLatin1String("filePath");
+ }
+
+ return QString();
+}
+
+/*!
+ \qmlproperty string FolderListModel::folder
+
+ The \a folder property holds the folder the model is currently providing.
+
+ It is a URL, but must be a file: or qrc: URL (or relative to such a URL).
+*/
+QUrl QDeclarativeFolderListModel::folder() const
+{
+ return d->folder;
+}
+
+void QDeclarativeFolderListModel::setFolder(const QUrl &folder)
+{
+ if (folder == d->folder)
+ return;
+ QModelIndex index = d->model.index(folder.toLocalFile());
+ if (index.isValid() && d->model.isDir(index)) {
+ d->folder = folder;
+ QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
+ emit folderChanged();
+ }
+}
+
+QUrl QDeclarativeFolderListModel::parentFolder() const
+{
+ QUrl r;
+ QString localFile = d->folder.toLocalFile();
+ if (!localFile.isEmpty()) {
+ QDir dir(localFile);
+#if defined(Q_OS_SYMBIAN)
+ if (dir.isRoot())
+ dir.setPath("");
+ else
+#endif
+ dir.cdUp();
+ r = d->folder;
+ r.setPath(dir.path());
+ } else {
+ int pos = d->folder.path().lastIndexOf(QLatin1Char('/'));
+ if (pos == -1)
+ return QUrl();
+ r = d->folder;
+ r.setPath(d->folder.path().left(pos));
+ }
+ return r;
+}
+
+/*!
+ \qmlproperty list<string> FolderListModel::nameFilters
+
+ The \a nameFilters property contains a list of filename filters.
+ The filters may include the ? and * wildcards.
+
+ The example below filters on PNG and JPEG files:
+
+ \code
+ FolderListModel {
+ nameFilters: [ "*.png", "*.jpg" ]
+ }
+ \endcode
+*/
+QStringList QDeclarativeFolderListModel::nameFilters() const
+{
+ return d->nameFilters;
+}
+
+void QDeclarativeFolderListModel::setNameFilters(const QStringList &filters)
+{
+ d->nameFilters = filters;
+ d->model.setNameFilters(d->nameFilters);
+}
+
+void QDeclarativeFolderListModel::componentComplete()
+{
+ if (!d->folder.isValid() || !QDir().exists(d->folder.toLocalFile()))
+ setFolder(QUrl(QLatin1String("file://")+QDir::currentPath()));
+
+ if (!d->folderIndex.isValid())
+ QMetaObject::invokeMethod(this, "refresh", Qt::QueuedConnection);
+}
+
+QDeclarativeFolderListModel::SortField QDeclarativeFolderListModel::sortField() const
+{
+ return d->sortField;
+}
+
+void QDeclarativeFolderListModel::setSortField(SortField field)
+{
+ if (field != d->sortField) {
+ d->sortField = field;
+ d->updateSorting();
+ }
+}
+
+bool QDeclarativeFolderListModel::sortReversed() const
+{
+ return d->sortReversed;
+}
+
+void QDeclarativeFolderListModel::setSortReversed(bool rev)
+{
+ if (rev != d->sortReversed) {
+ d->sortReversed = rev;
+ d->updateSorting();
+ }
+}
+
+/*!
+ \qmlmethod bool FolderListModel::isFolder(int index)
+
+ Returns true if the entry \a index is a folder; otherwise
+ returns false.
+*/
+bool QDeclarativeFolderListModel::isFolder(int index) const
+{
+ if (index != -1) {
+ QModelIndex idx = d->model.index(index, 0, d->folderIndex);
+ if (idx.isValid())
+ return d->model.isDir(idx);
+ }
+ return false;
+}
+
+void QDeclarativeFolderListModel::refresh()
+{
+ d->folderIndex = QModelIndex();
+ if (d->count) {
+ int tmpCount = d->count;
+ d->count = 0;
+ emit itemsRemoved(0, tmpCount);
+ }
+ d->folderIndex = d->model.index(d->folder.toLocalFile());
+ d->count = d->model.rowCount(d->folderIndex);
+ if (d->count) {
+ emit itemsInserted(0, d->count);
+ }
+}
+
+void QDeclarativeFolderListModel::inserted(const QModelIndex &index, int start, int end)
+{
+ if (index == d->folderIndex) {
+ d->count = d->model.rowCount(d->folderIndex);
+ emit itemsInserted(start, end - start + 1);
+ }
+}
+
+void QDeclarativeFolderListModel::removed(const QModelIndex &index, int start, int end)
+{
+ if (index == d->folderIndex) {
+ d->count = d->model.rowCount(d->folderIndex);
+ emit itemsRemoved(start, end - start + 1);
+ }
+}
+
+void QDeclarativeFolderListModel::dataChanged(const QModelIndex &start, const QModelIndex &end)
+{
+ qDebug() << "data changed";
+ if (start.parent() == d->folderIndex)
+ emit itemsChanged(start.row(), end.row() - start.row() + 1, roles());
+}
+
+/*!
+ \qmlproperty bool FolderListModel::showDirs
+
+ If true (the default), directories are included in the model.
+
+ Note that the nameFilters are ignored for directories.
+*/
+bool QDeclarativeFolderListModel::showDirs() const
+{
+ return d->model.filter() & QDir::AllDirs;
+}
+
+void QDeclarativeFolderListModel::setShowDirs(bool on)
+{
+ if (!(d->model.filter() & QDir::AllDirs) == !on)
+ return;
+ if (on)
+ d->model.setFilter(d->model.filter() | QDir::AllDirs | QDir::Drives);
+ else
+ d->model.setFilter(d->model.filter() & ~(QDir::AllDirs | QDir::Drives));
+}
+
+/*!
+ \qmlproperty bool FolderListModel::showDotAndDotDot
+
+ If true, the "." and ".." directories are included in the model.
+
+ The default is false.
+*/
+bool QDeclarativeFolderListModel::showDotAndDotDot() const
+{
+ return !(d->model.filter() & QDir::NoDotAndDotDot);
+}
+
+void QDeclarativeFolderListModel::setShowDotAndDotDot(bool on)
+{
+ if (!(d->model.filter() & QDir::NoDotAndDotDot) == on)
+ return;
+ if (on)
+ d->model.setFilter(d->model.filter() & ~QDir::NoDotAndDotDot);
+ else
+ d->model.setFilter(d->model.filter() | QDir::NoDotAndDotDot);
+}
+
+/*!
+ \qmlproperty bool FolderListModel::showOnlyReadable
+
+ If true, only readable files and directories are shown.
+
+ The default is false.
+*/
+bool QDeclarativeFolderListModel::showOnlyReadable() const
+{
+ return d->model.filter() & QDir::Readable;
+}
+
+void QDeclarativeFolderListModel::setShowOnlyReadable(bool on)
+{
+ if (!(d->model.filter() & QDir::Readable) == !on)
+ return;
+ if (on)
+ d->model.setFilter(d->model.filter() | QDir::Readable);
+ else
+ d->model.setFilter(d->model.filter() & ~QDir::Readable);
+}
+
+void QDeclarativeFolderListModel::registerTypes()
+{
+ QML_REGISTER_TYPE(Qt,4,6,FolderListModel,QDeclarativeFolderListModel);
+}
+
+QT_END_NAMESPACE
+
diff --git a/tools/qml/qdeclarativefolderlistmodel.h b/tools/qml/qdeclarativefolderlistmodel.h
new file mode 100644
index 0000000..57b7fe5
--- /dev/null
+++ b/tools/qml/qdeclarativefolderlistmodel.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples 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$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFOLDERLISTMODEL_H
+#define QDECLARATIVEFOLDERLISTMODEL_H
+
+#include <qdeclarative.h>
+#include <QStringList>
+#include <QUrl>
+#include "../../src/declarative/3rdparty/qlistmodelinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeContext;
+class QModelIndex;
+
+class QDeclarativeFolderListModelPrivate;
+class QDeclarativeFolderListModel : public QListModelInterface, public QDeclarativeParserStatus
+{
+ Q_OBJECT
+ Q_INTERFACES(QDeclarativeParserStatus)
+
+ Q_PROPERTY(QUrl folder READ folder WRITE setFolder NOTIFY folderChanged)
+ Q_PROPERTY(QUrl parentFolder READ parentFolder NOTIFY folderChanged)
+ Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters)
+ Q_PROPERTY(SortField sortField READ sortField WRITE setSortField)
+ Q_PROPERTY(bool sortReversed READ sortReversed WRITE setSortReversed)
+ Q_PROPERTY(bool showDirs READ showDirs WRITE setShowDirs)
+ Q_PROPERTY(bool showDotAndDotDot READ showDotAndDotDot WRITE setShowDotAndDotDot)
+ Q_PROPERTY(bool showOnlyReadable READ showOnlyReadable WRITE setShowOnlyReadable)
+
+public:
+ QDeclarativeFolderListModel(QObject *parent = 0);
+ ~QDeclarativeFolderListModel();
+
+ static void registerTypes();
+
+ virtual QHash<int,QVariant> data(int index, const QList<int> &roles = (QList<int>())) const;
+ virtual QVariant data(int index, int role) const;
+ virtual int count() const;
+ virtual QList<int> roles() const;
+ virtual QString toString(int role) const;
+
+ QUrl folder() const;
+ void setFolder(const QUrl &folder);
+
+ QUrl parentFolder() const;
+
+ QStringList nameFilters() const;
+ void setNameFilters(const QStringList &filters);
+
+ virtual void componentComplete();
+
+ Q_INVOKABLE bool isFolder(int index) const;
+
+ enum SortField { Unsorted, Name, Time, Size, Type };
+ SortField sortField() const;
+ void setSortField(SortField field);
+ Q_ENUMS(SortField)
+
+ bool sortReversed() const;
+ void setSortReversed(bool rev);
+
+ bool showDirs() const;
+ void setShowDirs(bool);
+ bool showDotAndDotDot() const;
+ void setShowDotAndDotDot(bool);
+ bool showOnlyReadable() const;
+ void setShowOnlyReadable(bool);
+
+Q_SIGNALS:
+ void folderChanged();
+
+private Q_SLOTS:
+ void refresh();
+ void inserted(const QModelIndex &index, int start, int end);
+ void removed(const QModelIndex &index, int start, int end);
+ void dataChanged(const QModelIndex &start, const QModelIndex &end);
+
+private:
+ Q_DISABLE_COPY(QDeclarativeFolderListModel)
+ QDeclarativeFolderListModelPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeFolderListModel)
+
+#endif // QDECLARATIVEFOLDERLISTMODEL_H
diff --git a/tools/qml/qfxtester.cpp b/tools/qml/qfxtester.cpp
new file mode 100644
index 0000000..638a3c9
--- /dev/null
+++ b/tools/qml/qfxtester.cpp
@@ -0,0 +1,381 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 <qfxtester.h>
+#include <QDebug>
+#include <QApplication>
+#include <qdeclarativeview.h>
+#include <QFile>
+#include <QDeclarativeComponent>
+#include <QDir>
+#include <QCryptographicHash>
+#include <private/qabstractanimation_p.h>
+#include <private/qdeclarativeitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+QDeclarativeTester::QDeclarativeTester(const QString &script, QDeclarativeViewer::ScriptOptions opts,
+ QDeclarativeView *parent)
+: QAbstractAnimation(parent), m_script(script), m_view(parent), filterEvents(true), options(opts),
+ testscript(0), hasCompleted(false), hasFailed(false)
+{
+ parent->viewport()->installEventFilter(this);
+ parent->installEventFilter(this);
+ QUnifiedTimer::instance()->setConsistentTiming(true);
+ if (options & QDeclarativeViewer::Play)
+ this->run();
+ start();
+}
+
+QDeclarativeTester::~QDeclarativeTester()
+{
+ if (!hasFailed &&
+ options & QDeclarativeViewer::Record &&
+ options & QDeclarativeViewer::SaveOnExit)
+ save();
+}
+
+int QDeclarativeTester::duration() const
+{
+ return -1;
+}
+
+void QDeclarativeTester::addMouseEvent(Destination dest, QMouseEvent *me)
+{
+ MouseEvent e(me);
+ e.destination = dest;
+ m_mouseEvents << e;
+}
+
+void QDeclarativeTester::addKeyEvent(Destination dest, QKeyEvent *ke)
+{
+ KeyEvent e(ke);
+ e.destination = dest;
+ m_keyEvents << e;
+}
+
+bool QDeclarativeTester::eventFilter(QObject *o, QEvent *e)
+{
+ if (!filterEvents)
+ return false;
+
+ Destination destination;
+ if (o == m_view) {
+ destination = View;
+ } else if (o == m_view->viewport()) {
+ destination = ViewPort;
+ } else {
+ return false;
+ }
+
+ switch (e->type()) {
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ addKeyEvent(destination, (QKeyEvent *)e);
+ return true;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonDblClick:
+ addMouseEvent(destination, (QMouseEvent *)e);
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+void QDeclarativeTester::executefailure()
+{
+ hasFailed = true;
+
+ if (options & QDeclarativeViewer::ExitOnFailure)
+ exit(-1);
+}
+
+void QDeclarativeTester::imagefailure()
+{
+ hasFailed = true;
+
+ if (options & QDeclarativeViewer::ExitOnFailure)
+ exit(-1);
+}
+
+void QDeclarativeTester::complete()
+{
+ if ((options & QDeclarativeViewer::TestErrorProperty) && !hasFailed) {
+ QString e = m_view->rootObject()->property("error").toString();
+ if (!e.isEmpty()) {
+ qWarning() << "Test failed:" << e;
+ hasFailed = true;
+ }
+ }
+ if (options & QDeclarativeViewer::ExitOnComplete)
+ QApplication::exit(hasFailed?-1:0);
+
+ if (hasCompleted)
+ return;
+ hasCompleted = true;
+
+ if (options & QDeclarativeViewer::Play)
+ qWarning("Script playback complete");
+}
+
+void QDeclarativeTester::run()
+{
+ QDeclarativeComponent c(m_view->engine(), m_script + QLatin1String(".qml"));
+
+ testscript = qobject_cast<QDeclarativeVisualTest *>(c.create());
+ if (testscript) testscript->setParent(this);
+ else { executefailure(); exit(-1); }
+ testscriptidx = 0;
+}
+
+void QDeclarativeTester::save()
+{
+ QString filename = m_script + QLatin1String(".qml");
+ QFileInfo filenameInfo(filename);
+ QDir saveDir = filenameInfo.absoluteDir();
+ saveDir.mkpath(".");
+
+ QFile file(filename);
+ file.open(QIODevice::WriteOnly);
+ QTextStream ts(&file);
+
+ ts << "import Qt.VisualTest 4.6\n\n";
+ ts << "VisualTest {\n";
+
+ int imgCount = 0;
+ QList<KeyEvent> keyevents = m_savedKeyEvents;
+ QList<MouseEvent> mouseevents = m_savedMouseEvents;
+ for (int ii = 0; ii < m_savedFrameEvents.count(); ++ii) {
+ const FrameEvent &fe = m_savedFrameEvents.at(ii);
+ ts << " Frame {\n";
+ ts << " msec: " << fe.msec << "\n";
+ if (!fe.hash.isEmpty()) {
+ ts << " hash: \"" << fe.hash.toHex() << "\"\n";
+ } else if (!fe.image.isNull()) {
+ QString filename = filenameInfo.baseName() + "." + QString::number(imgCount) + ".png";
+ fe.image.save(m_script + "." + QString::number(imgCount) + ".png");
+ imgCount++;
+ ts << " image: \"" << filename << "\"\n";
+ }
+ ts << " }\n";
+
+ while (!mouseevents.isEmpty() &&
+ mouseevents.first().msec == fe.msec) {
+ MouseEvent me = mouseevents.takeFirst();
+
+ ts << " Mouse {\n";
+ ts << " type: " << me.type << "\n";
+ ts << " button: " << me.button << "\n";
+ ts << " buttons: " << me.buttons << "\n";
+ ts << " x: " << me.pos.x() << "; y: " << me.pos.y() << "\n";
+ ts << " modifiers: " << me.modifiers << "\n";
+ if (me.destination == ViewPort)
+ ts << " sendToViewport: true\n";
+ ts << " }\n";
+ }
+
+ while (!keyevents.isEmpty() &&
+ keyevents.first().msec == fe.msec) {
+ KeyEvent ke = keyevents.takeFirst();
+
+ ts << " Key {\n";
+ ts << " type: " << ke.type << "\n";
+ ts << " key: " << ke.key << "\n";
+ ts << " modifiers: " << ke.modifiers << "\n";
+ ts << " text: \"" << ke.text.toUtf8().toHex() << "\"\n";
+ ts << " autorep: " << (ke.autorep?"true":"false") << "\n";
+ ts << " count: " << ke.count << "\n";
+ if (ke.destination == ViewPort)
+ ts << " sendToViewport: true\n";
+ ts << " }\n";
+ }
+ }
+
+ ts << "}\n";
+ file.close();
+}
+
+void QDeclarativeTester::updateCurrentTime(int msec)
+{
+ QDeclarativeItemPrivate::setConsistentTime(msec);
+
+ QImage img(m_view->width(), m_view->height(), QImage::Format_RGB32);
+
+ if (options & QDeclarativeViewer::TestImages) {
+ img.fill(qRgb(255,255,255));
+ QPainter p(&img);
+ m_view->render(&p);
+ }
+
+ FrameEvent fe;
+ fe.msec = msec;
+ if (msec == 0 || !(options & QDeclarativeViewer::TestImages)) {
+ // Skip first frame, skip if not doing images
+ } else if (0 == (m_savedFrameEvents.count() % 60)) {
+ fe.image = img;
+ } else {
+ QCryptographicHash hash(QCryptographicHash::Md5);
+ hash.addData((const char *)img.bits(), img.bytesPerLine() * img.height());
+ fe.hash = hash.result();
+ }
+ m_savedFrameEvents.append(fe);
+
+ // Deliver mouse events
+ filterEvents = false;
+
+ if (!testscript) {
+ for (int ii = 0; ii < m_mouseEvents.count(); ++ii) {
+ MouseEvent &me = m_mouseEvents[ii];
+ me.msec = msec;
+ QMouseEvent event(me.type, me.pos, me.button, me.buttons, me.modifiers);
+
+ if (me.destination == View) {
+ QCoreApplication::sendEvent(m_view, &event);
+ } else {
+ QCoreApplication::sendEvent(m_view->viewport(), &event);
+ }
+ }
+
+ for (int ii = 0; ii < m_keyEvents.count(); ++ii) {
+ KeyEvent &ke = m_keyEvents[ii];
+ ke.msec = msec;
+ QKeyEvent event(ke.type, ke.key, ke.modifiers, ke.text, ke.autorep, ke.count);
+
+ if (ke.destination == View) {
+ QCoreApplication::sendEvent(m_view, &event);
+ } else {
+ QCoreApplication::sendEvent(m_view->viewport(), &event);
+ }
+ }
+ m_savedMouseEvents.append(m_mouseEvents);
+ m_savedKeyEvents.append(m_keyEvents);
+ }
+
+ m_mouseEvents.clear();
+ m_keyEvents.clear();
+
+ // Advance test script
+ while (testscript && testscript->count() > testscriptidx) {
+
+ QObject *event = testscript->event(testscriptidx);
+
+ if (QDeclarativeVisualTestFrame *frame = qobject_cast<QDeclarativeVisualTestFrame *>(event)) {
+ if (frame->msec() < msec) {
+ if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record)) {
+ qWarning() << "QDeclarativeTester: Extra frame. Seen:"
+ << msec << "Expected:" << frame->msec();
+ imagefailure();
+ }
+ } else if (frame->msec() == msec) {
+ if (!frame->hash().isEmpty() && frame->hash().toUtf8() != fe.hash.toHex()) {
+ if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record)) {
+ qWarning() << "QDeclarativeTester: Mismatched frame hash. Seen:"
+ << fe.hash.toHex() << "Expected:"
+ << frame->hash().toUtf8();
+ imagefailure();
+ }
+ }
+ } else if (frame->msec() > msec) {
+ break;
+ }
+
+ if (options & QDeclarativeViewer::TestImages && !(options & QDeclarativeViewer::Record) && !frame->image().isEmpty()) {
+ QImage goodImage(frame->image().toLocalFile());
+ if (goodImage != img) {
+ QString reject(frame->image().toLocalFile() + ".reject.png");
+ qWarning() << "QDeclarativeTester: Image mismatch. Reject saved to:"
+ << reject;
+ img.save(reject);
+ imagefailure();
+ }
+ }
+ } else if (QDeclarativeVisualTestMouse *mouse = qobject_cast<QDeclarativeVisualTestMouse *>(event)) {
+ QPoint pos(mouse->x(), mouse->y());
+ QPoint globalPos = m_view->mapToGlobal(QPoint(0, 0)) + pos;
+ QMouseEvent event((QEvent::Type)mouse->type(), pos, globalPos, (Qt::MouseButton)mouse->button(), (Qt::MouseButtons)mouse->buttons(), (Qt::KeyboardModifiers)mouse->modifiers());
+
+ MouseEvent me(&event);
+ me.msec = msec;
+ if (!mouse->sendToViewport()) {
+ QCoreApplication::sendEvent(m_view, &event);
+ me.destination = View;
+ } else {
+ QCoreApplication::sendEvent(m_view->viewport(), &event);
+ me.destination = ViewPort;
+ }
+ m_savedMouseEvents.append(me);
+ } else if (QDeclarativeVisualTestKey *key = qobject_cast<QDeclarativeVisualTestKey *>(event)) {
+
+ QKeyEvent event((QEvent::Type)key->type(), key->key(), (Qt::KeyboardModifiers)key->modifiers(), QString::fromUtf8(QByteArray::fromHex(key->text().toUtf8())), key->autorep(), key->count());
+
+ KeyEvent ke(&event);
+ ke.msec = msec;
+ if (!key->sendToViewport()) {
+ QCoreApplication::sendEvent(m_view, &event);
+ ke.destination = View;
+ } else {
+ QCoreApplication::sendEvent(m_view->viewport(), &event);
+ ke.destination = ViewPort;
+ }
+ m_savedKeyEvents.append(ke);
+ }
+ testscriptidx++;
+ }
+
+ filterEvents = true;
+
+ if (testscript && testscript->count() <= testscriptidx)
+ complete();
+}
+
+void QDeclarativeTester::registerTypes()
+{
+ QML_REGISTER_TYPE(Qt.VisualTest, 4,6, VisualTest, QDeclarativeVisualTest);
+ QML_REGISTER_TYPE(Qt.VisualTest, 4,6, Frame, QDeclarativeVisualTestFrame);
+ QML_REGISTER_TYPE(Qt.VisualTest, 4,6, Mouse, QDeclarativeVisualTestMouse);
+ QML_REGISTER_TYPE(Qt.VisualTest, 4,6, Key, QDeclarativeVisualTestKey);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qml/qfxtester.h b/tools/qml/qfxtester.h
new file mode 100644
index 0000000..1a9f077
--- /dev/null
+++ b/tools/qml/qfxtester.h
@@ -0,0 +1,286 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+#ifndef QFXTESTER_H
+#define QFXTESTER_H
+
+#include <QEvent>
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include <QImage>
+#include <QUrl>
+#include <qmlruntime.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeVisualTest : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QList<QObject *>* events READ events CONSTANT)
+ Q_CLASSINFO("DefaultProperty", "events")
+public:
+ QDeclarativeVisualTest() {}
+
+ QList<QObject *> *events() { return &m_events; }
+
+ int count() const { return m_events.count(); }
+ QObject *event(int idx) { return m_events.at(idx); }
+
+private:
+ QList<QObject *> m_events;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeVisualTest)
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeVisualTestFrame : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int msec READ msec WRITE setMsec)
+ Q_PROPERTY(QString hash READ hash WRITE setHash)
+ Q_PROPERTY(QUrl image READ image WRITE setImage)
+public:
+ QDeclarativeVisualTestFrame() : m_msec(-1) {}
+
+ int msec() const { return m_msec; }
+ void setMsec(int m) { m_msec = m; }
+
+ QString hash() const { return m_hash; }
+ void setHash(const QString &hash) { m_hash = hash; }
+
+ QUrl image() const { return m_image; }
+ void setImage(const QUrl &image) { m_image = image; }
+
+private:
+ int m_msec;
+ QString m_hash;
+ QUrl m_image;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeVisualTestFrame)
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeVisualTestMouse : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int type READ type WRITE setType)
+ Q_PROPERTY(int button READ button WRITE setButton)
+ Q_PROPERTY(int buttons READ buttons WRITE setButtons)
+ Q_PROPERTY(int x READ x WRITE setX)
+ Q_PROPERTY(int y READ y WRITE setY)
+ Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers)
+ Q_PROPERTY(bool sendToViewport READ sendToViewport WRITE setSendToViewport)
+public:
+ QDeclarativeVisualTestMouse() : m_type(0), m_button(0), m_buttons(0), m_x(0), m_y(0), m_modifiers(0), m_viewport(false) {}
+
+ int type() const { return m_type; }
+ void setType(int t) { m_type = t; }
+
+ int button() const { return m_button; }
+ void setButton(int b) { m_button = b; }
+
+ int buttons() const { return m_buttons; }
+ void setButtons(int b) { m_buttons = b; }
+
+ int x() const { return m_x; }
+ void setX(int x) { m_x = x; }
+
+ int y() const { return m_y; }
+ void setY(int y) { m_y = y; }
+
+ int modifiers() const { return m_modifiers; }
+ void setModifiers(int modifiers) { m_modifiers = modifiers; }
+
+ bool sendToViewport() const { return m_viewport; }
+ void setSendToViewport(bool v) { m_viewport = v; }
+private:
+ int m_type;
+ int m_button;
+ int m_buttons;
+ int m_x;
+ int m_y;
+ int m_modifiers;
+ bool m_viewport;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeVisualTestMouse)
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeVisualTestKey : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int type READ type WRITE setType)
+ Q_PROPERTY(int key READ key WRITE setKey)
+ Q_PROPERTY(int modifiers READ modifiers WRITE setModifiers)
+ Q_PROPERTY(QString text READ text WRITE setText)
+ Q_PROPERTY(bool autorep READ autorep WRITE setAutorep)
+ Q_PROPERTY(int count READ count WRITE setCount)
+ Q_PROPERTY(bool sendToViewport READ sendToViewport WRITE setSendToViewport)
+public:
+ QDeclarativeVisualTestKey() : m_type(0), m_key(0), m_modifiers(0), m_autorep(false), m_count(0), m_viewport(false) {}
+
+ int type() const { return m_type; }
+ void setType(int t) { m_type = t; }
+
+ int key() const { return m_key; }
+ void setKey(int k) { m_key = k; }
+
+ int modifiers() const { return m_modifiers; }
+ void setModifiers(int m) { m_modifiers = m; }
+
+ QString text() const { return m_text; }
+ void setText(const QString &t) { m_text = t; }
+
+ bool autorep() const { return m_autorep; }
+ void setAutorep(bool a) { m_autorep = a; }
+
+ int count() const { return m_count; }
+ void setCount(int c) { m_count = c; }
+
+ bool sendToViewport() const { return m_viewport; }
+ void setSendToViewport(bool v) { m_viewport = v; }
+private:
+ int m_type;
+ int m_key;
+ int m_modifiers;
+ QString m_text;
+ bool m_autorep;
+ int m_count;
+ bool m_viewport;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeVisualTestKey)
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeTester : public QAbstractAnimation
+{
+public:
+ QDeclarativeTester(const QString &script, QDeclarativeViewer::ScriptOptions options, QDeclarativeView *parent);
+ ~QDeclarativeTester();
+
+ static void registerTypes();
+
+ virtual int duration() const;
+
+ void run();
+ void save();
+
+ void executefailure();
+protected:
+ virtual void updateCurrentTime(int msecs);
+ virtual bool eventFilter(QObject *, QEvent *);
+
+private:
+ QString m_script;
+
+ void imagefailure();
+ void complete();
+
+ enum Destination { View, ViewPort };
+ void addKeyEvent(Destination, QKeyEvent *);
+ void addMouseEvent(Destination, QMouseEvent *);
+ QDeclarativeView *m_view;
+
+ struct MouseEvent {
+ MouseEvent(QMouseEvent *e)
+ : type(e->type()), button(e->button()), buttons(e->buttons()),
+ pos(e->pos()), modifiers(e->modifiers()), destination(View) {}
+
+ QEvent::Type type;
+ Qt::MouseButton button;
+ Qt::MouseButtons buttons;
+ QPoint pos;
+ Qt::KeyboardModifiers modifiers;
+ Destination destination;
+
+ int msec;
+ };
+ struct KeyEvent {
+ KeyEvent(QKeyEvent *e)
+ : type(e->type()), key(e->key()), modifiers(e->modifiers()), text(e->text()),
+ autorep(e->isAutoRepeat()), count(e->count()), destination(View) {}
+ QEvent::Type type;
+ int key;
+ Qt::KeyboardModifiers modifiers;
+ QString text;
+ bool autorep;
+ ushort count;
+ Destination destination;
+
+ int msec;
+ };
+ struct FrameEvent {
+ QImage image;
+ QByteArray hash;
+ int msec;
+ };
+ QList<MouseEvent> m_mouseEvents;
+ QList<KeyEvent> m_keyEvents;
+
+ QList<MouseEvent> m_savedMouseEvents;
+ QList<KeyEvent> m_savedKeyEvents;
+ QList<FrameEvent> m_savedFrameEvents;
+ bool filterEvents;
+
+ QDeclarativeViewer::ScriptOptions options;
+ int testscriptidx;
+ QDeclarativeVisualTest *testscript;
+
+ bool hasCompleted;
+ bool hasFailed;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QFXTESTER_H
diff --git a/tools/qml/qml.pro b/tools/qml/qml.pro
new file mode 100644
index 0000000..9c9c398
--- /dev/null
+++ b/tools/qml/qml.pro
@@ -0,0 +1,58 @@
+TEMPLATE = app
+CONFIG += qt \
+ uic
+DESTDIR = ../../bin
+QT += declarative \
+ script \
+ network \
+ sql
+
+contains(QT_CONFIG, opengl) {
+ QT += opengl
+ DEFINES += GL_SUPPORTED
+}
+
+# Input
+HEADERS += qmlruntime.h \
+ proxysettings.h \
+ qfxtester.h \
+ deviceorientation.h \
+ qdeclarativefolderlistmodel.h
+SOURCES += main.cpp \
+ qmlruntime.cpp \
+ proxysettings.cpp \
+ qfxtester.cpp \
+ qdeclarativefolderlistmodel.cpp
+RESOURCES = qmlruntime.qrc
+maemo5 {
+ SOURCES += deviceorientation_maemo.cpp
+} else {
+ SOURCES += deviceorientation.cpp
+}
+FORMS = recopts.ui \
+ proxysettings.ui
+INCLUDEPATH += ../../include/QtDeclarative
+INCLUDEPATH += ../../src/declarative/util
+INCLUDEPATH += ../../src/declarative/graphicsitems
+include(../shared/deviceskin/deviceskin.pri)
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+
+wince* {
+QT += scripttools \
+ xml \
+ xmlpatterns \
+ phonon
+
+ contains(QT_CONFIG, webkit) {
+ QT += webkit
+ }
+}
+symbian {
+# TARGET.UID3 =
+ include($$QT_SOURCE_TREE/examples/symbianpkgrules.pri)
+ TARGET.EPOCHEAPSIZE = 0x20000 0x2000000
+ HEADERS += $$QT_SOURCE_TREE/examples/network/qftp/sym_iap_util.h
+ LIBS += -lesock -lconnmon -linsock
+ TARGET.CAPABILITY = "All -TCB"
+}
diff --git a/tools/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp
new file mode 100644
index 0000000..7da3f5a
--- /dev/null
+++ b/tools/qml/qmlruntime.cpp
@@ -0,0 +1,1468 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 <qdeclarativeview.h>
+
+#ifdef hz
+#undef hz
+#endif
+#include "ui_recopts.h"
+
+#include "qmlruntime.h"
+#include <qdeclarativecontext.h>
+#include <qdeclarativeengine.h>
+#include <qdeclarativenetworkaccessmanagerfactory.h>
+#include "qdeclarative.h"
+#include <private/qperformancelog_p_p.h>
+#include <private/qabstractanimation_p.h>
+#include <QAbstractAnimation>
+#include "deviceskin.h"
+
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 3))
+#include <private/qzipreader_p.h>
+#define QDECLARATIVEVIEWER_ZIP_SUPPORT
+#endif
+
+#include <QSettings>
+#include <QXmlStreamReader>
+#include <QBuffer>
+#include <QNetworkReply>
+#include <QNetworkCookieJar>
+#include <QNetworkDiskCache>
+#include <QNetworkAccessManager>
+#include <QSignalMapper>
+#include <QDeclarativeComponent>
+#include <QWidget>
+#include <QApplication>
+#include <QDir>
+#include <QTextBrowser>
+#include <QFile>
+#include <QFileInfo>
+#include <QVBoxLayout>
+#include <QProgressDialog>
+#include <QProcess>
+#include <QMenuBar>
+#include <QMenu>
+#include <QAction>
+#include <QFileDialog>
+#include <QTimer>
+#include <QGraphicsObject>
+#include <QNetworkProxyFactory>
+#include <QKeyEvent>
+#include <QMutex>
+#include <QMutexLocker>
+#include "proxysettings.h"
+#include "deviceorientation.h"
+
+#ifdef GL_SUPPORTED
+#include <QGLWidget>
+#endif
+
+#include <qfxtester.h>
+
+#if defined (Q_OS_SYMBIAN)
+#define SYMBIAN_NETWORK_INIT
+#endif
+
+#if defined (SYMBIAN_NETWORK_INIT)
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <QTextCodec>
+#include "sym_iap_util.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class Screen : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(Orientation orientation READ orientation NOTIFY orientationChanged)
+ Q_ENUMS(Orientation)
+
+public:
+ Screen(QObject *parent=0) : QObject(parent) {
+ connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()),
+ this, SIGNAL(orientationChanged()));
+ }
+
+ enum Orientation { UnknownOrientation = DeviceOrientation::UnknownOrientation,
+ Portrait = DeviceOrientation::Portrait,
+ Landscape = DeviceOrientation::Landscape };
+ Orientation orientation() const { return Orientation(DeviceOrientation::instance()->orientation()); }
+
+signals:
+ void orientationChanged();
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(Screen)
+
+QT_BEGIN_NAMESPACE
+
+class SizedMenuBar : public QMenuBar
+{
+ Q_OBJECT
+public:
+ SizedMenuBar(QWidget *parent, QWidget *referenceWidget)
+ : QMenuBar(parent), refWidget(referenceWidget)
+ {
+ }
+
+ virtual QSize sizeHint() const
+ {
+ return QSize(refWidget->sizeHint().width(), QMenuBar::sizeHint().height());
+ }
+
+private:
+ QWidget *refWidget;
+};
+
+
+class PreviewDeviceSkin : public DeviceSkin
+{
+ Q_OBJECT
+public:
+ explicit PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent);
+
+ void setPreview(QWidget *formWidget);
+ void setPreviewAndScale(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);
+ QApplication::syncX();
+ }
+
+ QSize standardScreenSize() const { return m_screenSize; }
+
+ QMenu* menu;
+
+private slots:
+ void slotSkinKeyPressEvent(int code, const QString& text, bool autorep);
+ void slotSkinKeyReleaseEvent(int code, const QString& text, bool autorep);
+ void slotPopupMenu();
+
+private:
+ const QSize m_screenSize;
+};
+
+
+PreviewDeviceSkin::PreviewDeviceSkin(const DeviceSkinParameters &parameters, QWidget *parent) :
+ DeviceSkin(parameters, parent),
+ m_screenSize(parameters.screenSize())
+{
+ menu = new QMenu(this);
+ 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::setPreviewAndScale(QWidget *formWidget)
+{
+ setScreenSize(formWidget->sizeHint());
+ 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()
+{
+ menu->exec(QCursor::pos());
+}
+
+static struct { const char *name, *args; } ffmpegprofiles[] = {
+ {"Maximum Quality", "-sameq"},
+ {"High Quality", "-qmax 2"},
+ {"Medium Quality", "-qmax 6"},
+ {"Low Quality", "-qmax 16"},
+ {"Custom ffmpeg arguments", ""},
+ {0,0}
+};
+
+class RecordingDialog : public QDialog, public Ui::RecordingOptions {
+ Q_OBJECT
+
+public:
+ RecordingDialog(QWidget *parent) : QDialog(parent)
+ {
+ setupUi(this);
+ hz->setValidator(new QDoubleValidator(hz));
+ for (int i=0; ffmpegprofiles[i].name; ++i) {
+ profile->addItem(ffmpegprofiles[i].name);
+ }
+ }
+
+ void setArguments(QString a)
+ {
+ int i;
+ for (i=0; ffmpegprofiles[i].args[0]; ++i) {
+ if (ffmpegprofiles[i].args == a) {
+ profile->setCurrentIndex(i);
+ args->setText(QLatin1String(ffmpegprofiles[i].args));
+ return;
+ }
+ }
+ customargs = a;
+ args->setText(a);
+ profile->setCurrentIndex(i);
+ }
+
+ QString arguments() const
+ {
+ int i = profile->currentIndex();
+ return ffmpegprofiles[i].args[0] ? QLatin1String(ffmpegprofiles[i].args) : customargs;
+ }
+
+private slots:
+ void pickProfile(int i)
+ {
+ if (ffmpegprofiles[i].args[0]) {
+ args->setText(QLatin1String(ffmpegprofiles[i].args));
+ } else {
+ args->setText(customargs);
+ }
+ }
+
+ void storeCustomArgs(QString s)
+ {
+ setArguments(s);
+ }
+
+private:
+ QString customargs;
+};
+
+class PersistentCookieJar : public QNetworkCookieJar {
+public:
+ PersistentCookieJar(QObject *parent) : QNetworkCookieJar(parent) { load(); }
+ ~PersistentCookieJar() { save(); }
+
+ virtual QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const
+ {
+ QMutexLocker lock(&mutex);
+ return QNetworkCookieJar::cookiesForUrl(url);
+ }
+
+ virtual bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
+ {
+ QMutexLocker lock(&mutex);
+ return QNetworkCookieJar::setCookiesFromUrl(cookieList, url);
+ }
+
+private:
+ void save()
+ {
+ QMutexLocker lock(&mutex);
+ QList<QNetworkCookie> list = allCookies();
+ QByteArray data;
+ foreach (QNetworkCookie cookie, list) {
+ if (!cookie.isSessionCookie()) {
+ data.append(cookie.toRawForm());
+ data.append("\n");
+ }
+ }
+ QSettings settings("Nokia", "QtQmlViewer");
+ settings.setValue("Cookies",data);
+ }
+
+ void load()
+ {
+ QMutexLocker lock(&mutex);
+ QSettings settings("Nokia", "QtQmlViewer");
+ QByteArray data = settings.value("Cookies").toByteArray();
+ setAllCookies(QNetworkCookie::parseCookies(data));
+ }
+
+ mutable QMutex mutex;
+};
+
+class NetworkAccessManagerFactory : public QDeclarativeNetworkAccessManagerFactory
+{
+public:
+ NetworkAccessManagerFactory() : cookieJar(0), cacheSize(0) {}
+ ~NetworkAccessManagerFactory() {
+ delete cookieJar;
+ }
+
+ QNetworkAccessManager *create(QObject *parent) {
+ QMutexLocker lock(&mutex);
+ QNetworkAccessManager *manager = new QNetworkAccessManager(parent);
+ if (!cookieJar)
+ cookieJar = new PersistentCookieJar(0);
+ manager->setCookieJar(cookieJar);
+ cookieJar->setParent(0);
+ setupProxy(manager);
+ if (cacheSize > 0) {
+ QNetworkDiskCache *cache = new QNetworkDiskCache;
+ cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-duiviewer-network-cache"));
+ cache->setMaximumCacheSize(cacheSize);
+ manager->setCache(cache);
+ } else {
+ manager->setCache(0);
+ }
+ qDebug() << "created new network access manager for" << parent;
+ return manager;
+ }
+
+ void setupProxy(QNetworkAccessManager *nam)
+ {
+ class SystemProxyFactory : public QNetworkProxyFactory
+ {
+ public:
+ virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
+ {
+ QString protocolTag = query.protocolTag();
+ if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) {
+ QList<QNetworkProxy> ret;
+ ret << httpProxy;
+ return ret;
+ }
+ return QNetworkProxyFactory::systemProxyForQuery(query);
+ }
+ void setHttpProxy (QNetworkProxy proxy)
+ {
+ httpProxy = proxy;
+ httpProxyInUse = true;
+ }
+ void unsetHttpProxy ()
+ {
+ httpProxyInUse = false;
+ }
+ private:
+ bool httpProxyInUse;
+ QNetworkProxy httpProxy;
+ };
+
+ SystemProxyFactory *proxyFactory = new SystemProxyFactory;
+ if (ProxySettings::httpProxyInUse())
+ proxyFactory->setHttpProxy(ProxySettings::httpProxy());
+ else
+ proxyFactory->unsetHttpProxy();
+ nam->setProxyFactory(proxyFactory);
+ }
+
+ void setCacheSize(int size) {
+ if (size != cacheSize) {
+ cacheSize = size;
+ }
+ }
+
+ PersistentCookieJar *cookieJar;
+ QMutex mutex;
+ int cacheSize;
+};
+
+
+QString QDeclarativeViewer::getVideoFileName()
+{
+ QString title = convertAvailable || ffmpegAvailable ? tr("Save Video File") : tr("Save PNG Frames");
+ QStringList types;
+ if (ffmpegAvailable) types += tr("Common Video files")+QLatin1String(" (*.avi *.mpeg *.mov)");
+ if (convertAvailable) types += tr("GIF Animation")+QLatin1String(" (*.gif)");
+ types += tr("Individual PNG frames")+QLatin1String(" (*.png)");
+ if (ffmpegAvailable) types += tr("All ffmpeg formats (*.*)");
+ return QFileDialog::getSaveFileName(this, title, "", types.join(";; "));
+}
+
+
+QDeclarativeViewer::QDeclarativeViewer(QWidget *parent, Qt::WindowFlags flags)
+#if defined(Q_OS_SYMBIAN)
+ : QMainWindow(parent, flags)
+#else
+ : QWidget(parent, flags)
+#endif
+ , frame_stream(0), scaleSkin(true), mb(0)
+ , portraitOrientation(0), landscapeOrientation(0)
+ , m_scriptOptions(0), tester(0), useQmlFileBrowser(true)
+{
+ devicemode = false;
+ skin = 0;
+ canvas = 0;
+ record_autotime = 0;
+ record_rate = 50;
+ record_args += QLatin1String("-sameq");
+
+ recdlg = new RecordingDialog(this);
+ connect(recdlg->pickfile, SIGNAL(clicked()), this, SLOT(pickRecordingFile()));
+ senseFfmpeg();
+ senseImageMagick();
+ if (!ffmpegAvailable)
+ recdlg->ffmpegOptions->hide();
+ if (!ffmpegAvailable && !convertAvailable)
+ recdlg->rateOptions->hide();
+ QString warn;
+ if (!ffmpegAvailable) {
+ if (!convertAvailable)
+ warn = tr("ffmpeg and ImageMagick not available - no video output");
+ else
+ warn = tr("ffmpeg not available - GIF and PNG outputs only");
+ recdlg->warning->setText(warn);
+ } else {
+ recdlg->warning->hide();
+ }
+
+ canvas = new QDeclarativeView(this);
+ canvas->setAttribute(Qt::WA_OpaquePaintEvent);
+ canvas->setAttribute(Qt::WA_NoSystemBackground);
+ canvas->setResizeMode((!skin || !scaleSkin) ? QDeclarativeView::SizeRootObjectToView : QDeclarativeView::SizeViewToRootObject);
+ canvas->setFocus();
+
+ QObject::connect(canvas, SIGNAL(sceneResized(QSize)), this, SLOT(sceneResized(QSize)));
+ QObject::connect(canvas, SIGNAL(statusChanged(QDeclarativeView::Status)), this, SLOT(statusChanged()));
+ QObject::connect(canvas->engine(), SIGNAL(quit()), QCoreApplication::instance (), SLOT(quit()));
+
+ if (!(flags & Qt::FramelessWindowHint)) {
+ createMenu(menuBar(),0);
+ setPortrait();
+ }
+
+#if !defined(Q_OS_SYMBIAN)
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ setLayout(layout);
+ if (mb)
+ layout->addWidget(mb);
+ layout->addWidget(canvas);
+#else
+ setCentralWidget(canvas);
+#endif
+
+ namFactory = new NetworkAccessManagerFactory;
+ canvas->engine()->setNetworkAccessManagerFactory(namFactory);
+
+ connect(&autoStartTimer, SIGNAL(triggered()), this, SLOT(autoStartRecording()));
+ connect(&autoStopTimer, SIGNAL(triggered()), this, SLOT(autoStopRecording()));
+ connect(&recordTimer, SIGNAL(triggered()), this, SLOT(recordFrame()));
+ autoStartTimer.setRunning(false);
+ autoStopTimer.setRunning(false);
+ recordTimer.setRunning(false);
+ recordTimer.setRepeating(true);
+}
+
+QDeclarativeViewer::~QDeclarativeViewer()
+{
+ canvas->engine()->setNetworkAccessManagerFactory(0);
+ delete namFactory;
+}
+
+QMenuBar *QDeclarativeViewer::menuBar() const
+{
+#if !defined(Q_OS_SYMBIAN)
+ if (!mb)
+ mb = new SizedMenuBar((QWidget*)this, canvas);
+#else
+ mb = QMainWindow::menuBar();
+#endif
+
+ return mb;
+}
+
+void QDeclarativeViewer::createMenu(QMenuBar *menu, QMenu *flatmenu)
+{
+ QObject *parent = flatmenu ? (QObject*)flatmenu : (QObject*)menu;
+
+ QMenu *fileMenu = flatmenu ? flatmenu : menu->addMenu(tr("&File"));
+
+ QAction *openAction = new QAction(tr("&Open..."), parent);
+ openAction->setShortcut(QKeySequence("Ctrl+O"));
+ connect(openAction, SIGNAL(triggered()), this, SLOT(openFile()));
+ fileMenu->addAction(openAction);
+
+ QAction *reloadAction = new QAction(tr("&Reload"), parent);
+ reloadAction->setShortcut(QKeySequence("Ctrl+R"));
+ connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload()));
+ fileMenu->addAction(reloadAction);
+
+#if defined(Q_OS_SYMBIAN)
+ QAction *networkAction = new QAction(tr("Start &Network"), parent);
+ connect(networkAction, SIGNAL(triggered()), this, SLOT(startNetwork()));
+ fileMenu->addAction(networkAction);
+#endif
+
+#if !defined(Q_OS_SYMBIAN)
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *recordMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Recording"));
+
+ QAction *snapshotAction = new QAction(tr("&Take Snapshot\tF3"), parent);
+ connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot()));
+ recordMenu->addAction(snapshotAction);
+
+ recordAction = new QAction(tr("Start Recording &Video\tF9"), parent);
+ connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection()));
+ recordMenu->addAction(recordAction);
+
+ QAction *recordOptions = new QAction(tr("Video &Options..."), parent);
+ connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions()));
+
+ if (flatmenu)
+ flatmenu->addAction(recordOptions);
+
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *debugMenu = flatmenu ? flatmenu->addMenu(tr("&Debugging")) : menu->addMenu(tr("&Debugging"));
+
+ QAction *slowAction = new QAction(tr("&Slow Down Animations"), parent);
+ slowAction->setShortcut(QKeySequence("Ctrl+."));
+ slowAction->setCheckable(true);
+ connect(slowAction, SIGNAL(triggered(bool)), this, SLOT(setSlowMode(bool)));
+ debugMenu->addAction(slowAction);
+
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *skinMenu = flatmenu ? flatmenu->addMenu(tr("&Skin")) : menu->addMenu(tr("&Skin"));
+
+ QActionGroup *skinActions;
+ QAction *skinAction;
+
+ skinActions = new QActionGroup(parent);
+ skinAction = new QAction(tr("Scale skin"), parent);
+ skinAction->setCheckable(true);
+ skinAction->setChecked(scaleSkin);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ connect(skinAction, SIGNAL(triggered()), this, SLOT(setScaleSkin()));
+ skinAction = new QAction(tr("Resize view"), parent);
+ skinAction->setCheckable(true);
+ skinAction->setChecked(!scaleSkin);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ connect(skinAction, SIGNAL(triggered()), this, SLOT(setScaleView()));
+ skinMenu->addSeparator();
+
+ skinActions = new QActionGroup(parent);
+ QSignalMapper *mapper = new QSignalMapper(parent);
+ skinAction = new QAction(tr("None"), parent);
+ skinAction->setCheckable(true);
+ if (currentSkin.isEmpty())
+ skinAction->setChecked(true);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ mapper->setMapping(skinAction, "");
+ connect(skinAction, SIGNAL(triggered()), mapper, SLOT(map()));
+ skinMenu->addSeparator();
+
+ foreach (QString name, builtinSkins()) {
+ skinAction = new QAction(name, parent);
+ skinActions->addAction(skinAction);
+ skinMenu->addAction(skinAction);
+ skinAction->setCheckable(true);
+ if (":skin/"+name+".skin" == currentSkin)
+ skinAction->setChecked(true);
+ mapper->setMapping(skinAction, name);
+ connect(skinAction, SIGNAL(triggered()), mapper, SLOT(map()));
+ }
+ connect(mapper, SIGNAL(mapped(QString)), this, SLOT(setSkin(QString)));
+
+ if (flatmenu) flatmenu->addSeparator();
+#endif // Q_OS_SYMBIAN
+
+ QMenu *settingsMenu = flatmenu ? flatmenu : menu->addMenu(tr("S&ettings"));
+ QAction *proxyAction = new QAction(tr("Http &proxy..."), parent);
+ connect(proxyAction, SIGNAL(triggered()), this, SLOT(showProxySettings()));
+ settingsMenu->addAction(proxyAction);
+#if !defined(Q_OS_SYMBIAN)
+ if (!flatmenu)
+ settingsMenu->addAction(recordOptions);
+#else
+ QAction *fullscreenAction = new QAction(tr("Full Screen"), parent);
+ fullscreenAction->setCheckable(true);
+ connect(fullscreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
+ settingsMenu->addAction(fullscreenAction);
+#endif
+
+ QMenu *propertiesMenu = settingsMenu->addMenu(tr("Properties"));
+ QActionGroup *orientation = new QActionGroup(parent);
+
+ QAction *toggleOrientation = new QAction(tr("&Toggle Orientation"), parent);
+ toggleOrientation->setCheckable(true);
+ toggleOrientation->setShortcut(QKeySequence("Ctrl+T"));
+ settingsMenu->addAction(toggleOrientation);
+ connect(toggleOrientation, SIGNAL(triggered()), this, SLOT(toggleOrientation()));
+
+ orientation->setExclusive(true);
+ portraitOrientation = new QAction(tr("orientation: Portrait"), parent);
+ portraitOrientation->setCheckable(true);
+ connect(portraitOrientation, SIGNAL(triggered()), this, SLOT(setPortrait()));
+ orientation->addAction(portraitOrientation);
+ propertiesMenu->addAction(portraitOrientation);
+
+ landscapeOrientation = new QAction(tr("orientation: Landscape"), parent);
+ landscapeOrientation->setCheckable(true);
+ connect(landscapeOrientation, SIGNAL(triggered()), this, SLOT(setLandscape()));
+ orientation->addAction(landscapeOrientation);
+ propertiesMenu->addAction(landscapeOrientation);
+
+ if (flatmenu) flatmenu->addSeparator();
+
+ QMenu *helpMenu = flatmenu ? flatmenu : menu->addMenu(tr("&Help"));
+ QAction *aboutAction = new QAction(tr("&About Qt..."), parent);
+ connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+ helpMenu->addAction(aboutAction);
+
+ QAction *quitAction = new QAction(tr("&Quit"), parent);
+ quitAction->setShortcut(QKeySequence("Ctrl+Q"));
+ connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+ fileMenu->addSeparator();
+ fileMenu->addAction(quitAction);
+ if (menu) {
+ menu->setFixedHeight(menu->sizeHint().height());
+ menu->setMinimumWidth(10);
+ }
+}
+
+void QDeclarativeViewer::showProxySettings()
+{
+ ProxySettings settingsDlg (this);
+
+ connect (&settingsDlg, SIGNAL (accepted()), this, SLOT (proxySettingsChanged ()));
+
+ settingsDlg.exec();
+}
+
+void QDeclarativeViewer::proxySettingsChanged()
+{
+ reload ();
+}
+
+void QDeclarativeViewer::setPortrait()
+{
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::Portrait);
+ portraitOrientation->setChecked(true);
+}
+
+void QDeclarativeViewer::setLandscape()
+{
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::Landscape);
+ landscapeOrientation->setChecked(true);
+}
+
+void QDeclarativeViewer::toggleOrientation()
+{
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::instance()->orientation()==DeviceOrientation::Portrait?DeviceOrientation::Landscape:DeviceOrientation::Portrait);
+}
+
+void QDeclarativeViewer::toggleFullScreen()
+{
+ if (isFullScreen())
+ showMaximized();
+ else
+ showFullScreen();
+}
+
+void QDeclarativeViewer::setScaleSkin()
+{
+ if (scaleSkin)
+ return;
+ scaleSkin = true;
+ canvas->setResizeMode((!skin || !scaleSkin) ? QDeclarativeView::SizeRootObjectToView : QDeclarativeView::SizeViewToRootObject);
+ if (skin) {
+ canvas->setFixedSize(canvas->sizeHint());
+ skin->setScreenSize(canvas->sizeHint());
+ }
+}
+
+void QDeclarativeViewer::setScaleView()
+{
+ if (!scaleSkin)
+ return;
+ scaleSkin = false;
+ if (skin) {
+ canvas->setResizeMode((!skin || !scaleSkin) ? QDeclarativeView::SizeRootObjectToView : QDeclarativeView::SizeViewToRootObject);
+ canvas->setMinimumSize(QSize(0,0));
+ canvas->setMaximumSize(QSize(16777215,16777215));
+ canvas->resize(skin->standardScreenSize());
+ skin->setScreenSize(skin->standardScreenSize());
+ }
+}
+
+
+void QDeclarativeViewer::takeSnapShot()
+{
+ static int snapshotcount = 1;
+ QString snapFileName = QString(QLatin1String("snapshot%1.png")).arg(snapshotcount);
+ QPixmap::grabWidget(canvas).save(snapFileName);
+ qDebug() << "Wrote" << snapFileName;
+ ++snapshotcount;
+}
+
+void QDeclarativeViewer::pickRecordingFile()
+{
+ QString fileName = getVideoFileName();
+ if (!fileName.isEmpty())
+ recdlg->file->setText(fileName);
+}
+
+void QDeclarativeViewer::chooseRecordingOptions()
+{
+ // File
+ recdlg->file->setText(record_file);
+
+ // Size
+ recdlg->sizeOriginal->setText(tr("Original (%1x%2)").arg(canvas->width()).arg(canvas->height()));
+ if (recdlg->sizeWidth->value()<=1) {
+ recdlg->sizeWidth->setValue(canvas->width());
+ recdlg->sizeHeight->setValue(canvas->height());
+ }
+
+ // Rate
+ if (record_rate == 24)
+ recdlg->hz24->setChecked(true);
+ else if (record_rate == 25)
+ recdlg->hz25->setChecked(true);
+ else if (record_rate == 50)
+ recdlg->hz50->setChecked(true);
+ else if (record_rate == 60)
+ recdlg->hz60->setChecked(true);
+ else {
+ recdlg->hzCustom->setChecked(true);
+ recdlg->hz->setText(QString::number(record_rate));
+ }
+
+ // Profile
+ recdlg->setArguments(record_args.join(" "));
+ if (recdlg->exec()) {
+ // File
+ record_file = recdlg->file->text();
+ // Size
+ if (recdlg->sizeOriginal->isChecked())
+ record_outsize = QSize();
+ else if (recdlg->size720p->isChecked())
+ record_outsize = QSize(1280,720);
+ else if (recdlg->sizeVGA->isChecked())
+ record_outsize = QSize(640,480);
+ else if (recdlg->sizeQVGA->isChecked())
+ record_outsize = QSize(320,240);
+ else
+ record_outsize = QSize(recdlg->sizeWidth->value(),recdlg->sizeHeight->value());
+ // Rate
+ if (recdlg->hz24->isChecked())
+ record_rate = 24;
+ else if (recdlg->hz25->isChecked())
+ record_rate = 25;
+ else if (recdlg->hz50->isChecked())
+ record_rate = 50;
+ else if (recdlg->hz60->isChecked())
+ record_rate = 60;
+ else {
+ record_rate = recdlg->hz->text().toDouble();
+ }
+ // Profile
+ record_args = recdlg->arguments().split(" ",QString::SkipEmptyParts);
+ }
+}
+
+void QDeclarativeViewer::toggleRecordingWithSelection()
+{
+ if (!recordTimer.isRunning()) {
+ if (record_file.isEmpty()) {
+ QString fileName = getVideoFileName();
+ if (fileName.isEmpty())
+ return;
+ if (!fileName.contains(QRegExp(".[^\\/]*$")))
+ fileName += ".avi";
+ setRecordFile(fileName);
+ }
+ }
+ toggleRecording();
+}
+
+void QDeclarativeViewer::toggleRecording()
+{
+ if (record_file.isEmpty()) {
+ toggleRecordingWithSelection();
+ return;
+ }
+ bool recording = !recordTimer.isRunning();
+ recordAction->setText(recording ? tr("&Stop Recording Video\tF9") : tr("&Start Recording Video\tF9"));
+ setRecording(recording);
+}
+
+void QDeclarativeViewer::setSlowMode(bool enable)
+{
+ QUnifiedTimer::instance()->setSlowModeEnabled(enable);
+}
+
+void QDeclarativeViewer::addLibraryPath(const QString& lib)
+{
+ canvas->engine()->addImportPath(lib);
+}
+
+void QDeclarativeViewer::reload()
+{
+ openQml(currentFileOrUrl);
+}
+
+void QDeclarativeViewer::open(const QString& doc)
+{
+#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
+ if (doc.endsWith(".wgt",Qt::CaseInsensitive)
+ || doc.endsWith(".wgz",Qt::CaseInsensitive)
+ || doc.endsWith(".zip",Qt::CaseInsensitive))
+ openWgt(doc);
+ else
+#endif
+ openQml(doc);
+}
+
+void QDeclarativeViewer::openWgt(const QString& doc)
+{
+#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
+ // XXX This functionality could be migrated to QDeclarativeView once refined
+
+ QUrl url(doc);
+ if (url.isRelative())
+ url = QUrl::fromLocalFile(doc);
+ delete canvas->rootObject();
+ canvas->engine()->clearComponentCache();
+ QNetworkAccessManager * nam = canvas->engine()->networkAccessManager();
+ wgtreply = nam->get(QNetworkRequest(url));
+ connect(wgtreply,SIGNAL(finished()),this,SLOT(unpackWgt()));
+#endif
+}
+
+#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
+static void removeRecursive(const QString& dirname)
+{
+ QDir dir(dirname);
+ QFileInfoList entries(dir.entryInfoList(QDir::Dirs|QDir::Files|QDir::NoDotAndDotDot));
+ for (int i = 0; i < entries.count(); ++i)
+ if (entries[i].isDir())
+ removeRecursive(entries[i].filePath());
+ else
+ dir.remove(entries[i].fileName());
+ QDir().rmdir(dirname);
+}
+#endif
+
+void QDeclarativeViewer::unpackWgt()
+{
+#ifdef QDECLARATIVEVIEWER_ZIP_SUPPORT
+ QByteArray all = wgtreply->readAll();
+ QBuffer buf(&all);
+ buf.open(QIODevice::ReadOnly);
+ QZipReader zip(&buf);
+ /*
+ for (int i=0; i<zip.count(); ++i) {
+ QZipReader::FileInfo info = zip.entryInfoAt(i);
+ qDebug() << "zip:" << info.filePath;
+ }
+ */
+ wgtdir = QDir::tempPath()+QDir::separator()+QLatin1String("qml-wgt");
+ removeRecursive(wgtdir);
+ QDir().mkpath(wgtdir);
+ zip.extractAll(wgtdir);
+
+ QString rootfile;
+
+ if (wgtreply->header(QNetworkRequest::ContentTypeHeader).toString() == "application/widget" || wgtreply->url().path().endsWith(".wgt",Qt::CaseInsensitive)) {
+ // W3C Draft http://www.w3.org/TR/2009/CR-widgets-20091201
+ QFile configfile(wgtdir+QDir::separator()+"config.xml");
+ if (configfile.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader config(&configfile);
+ if (config.readNextStartElement() && config.name() == "widget") {
+ while (config.readNextStartElement()) {
+ if (config.name() == "content") {
+ rootfile = wgtdir + QDir::separator();
+ rootfile += config.attributes().value(QLatin1String("src"));
+ }
+ // XXX process other config
+
+ config.skipCurrentElement();
+ }
+ }
+ } else {
+ qWarning("No config.xml found - non-standard WGT file");
+ }
+ if (rootfile.isEmpty()) {
+ QString def = wgtdir+QDir::separator()+"index.qml";
+ if (QFile::exists(def))
+ rootfile = def;
+ }
+ } else {
+ // Just find index.qml, preferably at the root
+ for (int i=0; i<zip.count(); ++i) {
+ QZipReader::FileInfo info = zip.entryInfoAt(i);
+ if (info.filePath.compare(QLatin1String("index.qml"),Qt::CaseInsensitive)==0)
+ rootfile = wgtdir+QDir::separator()+info.filePath;
+ if (rootfile.isEmpty() && info.filePath.endsWith("/index.qml",Qt::CaseInsensitive))
+ rootfile = wgtdir+QDir::separator()+info.filePath;
+ }
+ }
+
+ openQml(rootfile);
+#endif
+}
+
+void QDeclarativeViewer::openFile()
+{
+ QString cur = canvas->source().toLocalFile();
+ if (useQmlFileBrowser) {
+ openQml("qrc:/content/Browser.qml");
+ } else {
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), cur, tr("QML Files (*.qml)"));
+ if (!fileName.isEmpty()) {
+ QFileInfo fi(fileName);
+ openQml(fi.absoluteFilePath());
+ }
+ }
+}
+
+void QDeclarativeViewer::statusChanged()
+{
+ if (canvas->status() == QDeclarativeView::Error && tester)
+ tester->executefailure();
+
+ if (canvas->status() == QDeclarativeView::Ready)
+ resize(sizeHint());
+}
+
+void QDeclarativeViewer::launch(const QString& file_or_url)
+{
+ QMetaObject::invokeMethod(this, "openQml", Qt::QueuedConnection, Q_ARG(QString, file_or_url));
+}
+
+void QDeclarativeViewer::openQml(const QString& file_or_url)
+{
+ currentFileOrUrl = file_or_url;
+
+ QUrl url;
+ QFileInfo fi(file_or_url);
+ if (fi.exists())
+ url = QUrl::fromLocalFile(fi.absoluteFilePath());
+ else
+ url = QUrl(file_or_url);
+ setWindowTitle(tr("%1 - Qt Declarative UI Viewer").arg(file_or_url));
+
+ if (!m_script.isEmpty())
+ tester = new QDeclarativeTester(m_script, m_scriptOptions, canvas);
+
+ delete canvas->rootObject();
+ canvas->engine()->clearComponentCache();
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("qmlViewer", this);
+#ifdef Q_OS_SYMBIAN
+ ctxt->setContextProperty("qmlViewerFolder", "E:\\"); // Documents on your S60 phone
+#else
+ ctxt->setContextProperty("qmlViewerFolder", QDir::currentPath());
+#endif
+
+ QString fileName = url.toLocalFile();
+ if (!fileName.isEmpty()) {
+ QFileInfo fi(fileName);
+ if (fi.exists()) {
+ if (fi.suffix().toLower() != QLatin1String("qml")) {
+ qWarning() << "qml cannot open non-QML file" << fileName;
+ return;
+ }
+
+ 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();
+ QDeclarativeComponent comp(canvas->engine());
+ comp.setData(data, QUrl());
+ QObject *dummyData = comp.create();
+
+ if(comp.isError()) {
+ QList<QDeclarativeError> errors = comp.errors();
+ foreach (const QDeclarativeError &error, errors) {
+ qWarning() << error;
+ }
+ if (tester) tester->executefailure();
+ }
+
+ if (dummyData) {
+ qWarning() << "Loaded dummy data:" << dir.filePath(qml);
+ qml.truncate(qml.length()-4);
+ ctxt->setContextProperty(qml, dummyData);
+ dummyData->setParent(this);
+ }
+ }
+ } else {
+ qWarning() << "qml cannot find file:" << fileName;
+ return;
+ }
+ }
+
+ QTime t;
+ t.start();
+
+ canvas->setSource(url);
+
+ qWarning() << "Wall startup time:" << t.elapsed();
+
+ if (!skin) {
+ canvas->updateGeometry();
+ if (mb)
+ mb->updateGeometry();
+ if (!isFullScreen() && !isMaximized())
+ resize(sizeHint());
+ } else {
+ if (scaleSkin)
+ canvas->resize(canvas->sizeHint());
+ else {
+ canvas->setFixedSize(skin->standardScreenSize());
+ canvas->resize(skin->standardScreenSize());
+ }
+ }
+
+#ifdef QTOPIA
+ show();
+#endif
+}
+
+void QDeclarativeViewer::startNetwork()
+{
+#if defined(SYMBIAN_NETWORK_INIT)
+ qt_SetDefaultIap();
+#endif
+}
+
+QStringList QDeclarativeViewer::builtinSkins() const
+{
+ QDir dir(":/skins/","*.skin");
+ const QFileInfoList l = dir.entryInfoList();
+ QStringList r;
+ for (QFileInfoList::const_iterator it = l.begin(); it != l.end(); ++it) {
+ r += (*it).baseName();
+ }
+ return r;
+}
+
+void QDeclarativeViewer::setSkin(const QString& skinDirOrName)
+{
+ QString skinDirectory = skinDirOrName;
+
+ if (!QDir(skinDirOrName).exists() && QDir(":/skins/"+skinDirOrName+".skin").exists())
+ skinDirectory = ":/skins/"+skinDirOrName+".skin";
+
+ if (currentSkin == skinDirectory)
+ return;
+
+ currentSkin = skinDirectory;
+
+ // XXX QWidget::setMask does not handle changes well, and we may
+ // XXX have been signalled from an item in a menu we're replacing,
+ // XXX hence some rather convoluted resetting here...
+
+ QString err;
+ if (skin) {
+ skin->hide();
+ skin->deleteLater();
+ }
+
+ canvas->setResizeMode((!skin || !scaleSkin) ? QDeclarativeView::SizeRootObjectToView : QDeclarativeView::SizeViewToRootObject);
+
+ DeviceSkinParameters parameters;
+ if (!skinDirectory.isEmpty() && parameters.read(skinDirectory,DeviceSkinParameters::ReadAll,&err)) {
+ layout()->setEnabled(false);
+ //setMenuBar(0);
+ if (mb)
+ mb->hide();
+ if (!err.isEmpty())
+ qWarning() << err;
+ skin = new PreviewDeviceSkin(parameters,this);
+ canvas->resize(canvas->sizeHint());
+ if (scaleSkin)
+ skin->setPreviewAndScale(canvas);
+ else
+ skin->setPreview(canvas);
+ createMenu(0,skin->menu);
+ skin->show();
+ } else {
+ skin = 0;
+ clearMask();
+ menuBar()->clear();
+ canvas->setParent(this, Qt::SubWindow);
+ createMenu(menuBar(),0);
+ mb->show();
+ setMinimumSize(QSize(0,0));
+ setMaximumSize(QSize(16777215,16777215));
+ canvas->setMinimumSize(QSize(0,0));
+ canvas->setMaximumSize(QSize(16777215,16777215));
+ QRect g = geometry();
+ g.setSize(sizeHint());
+ setParent(0,windowFlags()); // recreate
+ canvas->move(0,menuBar()->sizeHint().height());
+ setGeometry(g);
+ layout()->setEnabled(true);
+ show();
+ }
+ canvas->show();
+}
+
+void QDeclarativeViewer::setAutoRecord(int from, int to)
+{
+ if (from==0) from=1; // ensure resized
+ record_autotime = to-from;
+ autoStartTimer.setInterval(from);
+ autoStartTimer.setRunning(true);
+}
+
+void QDeclarativeViewer::setRecordArgs(const QStringList& a)
+{
+ record_args = a;
+}
+
+void QDeclarativeViewer::setRecordFile(const QString& f)
+{
+ record_file = f;
+}
+
+void QDeclarativeViewer::setRecordRate(int fps)
+{
+ record_rate = fps;
+}
+
+void QDeclarativeViewer::sceneResized(QSize size)
+{
+ if (size.width() > 0 && size.height() > 0) {
+ if (skin && scaleSkin)
+ skin->setScreenSize(size);
+ }
+}
+
+void QDeclarativeViewer::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 - save test script\n"
+ << "F3 - take PNG snapshot\n"
+ << "F4 - show items and state\n"
+ << "F5 - reload QML\n"
+ << "F6 - show object tree\n"
+ << "F7 - show timing\n"
+ << "F8 - show performance (if available)\n"
+ << "F9 - toggle video recording\n"
+ << "F10 - toggle orientation\n"
+ << "device keys: 0=quit, 1..8=F1..F8"
+ ;
+ } else if (event->key() == Qt::Key_F2 || (event->key() == Qt::Key_2 && devicemode)) {
+ if (tester && m_scriptOptions & Record)
+ tester->save();
+ } else if (event->key() == Qt::Key_F3 || (event->key() == Qt::Key_3 && devicemode)) {
+ takeSnapShot();
+ } else if (event->key() == Qt::Key_F5 || (event->key() == Qt::Key_5 && devicemode)) {
+ reload();
+ } else if (event->key() == Qt::Key_F8 || (event->key() == Qt::Key_8 && devicemode)) {
+ QPerformanceLog::displayData();
+ QPerformanceLog::clear();
+ } else if (event->key() == Qt::Key_F9 || (event->key() == Qt::Key_9 && devicemode)) {
+ toggleRecording();
+ } else if (event->key() == Qt::Key_F10) {
+ if (portraitOrientation) {
+ if (portraitOrientation->isChecked())
+ setLandscape();
+ else
+ setPortrait();
+ }
+ }
+
+ QWidget::keyPressEvent(event);
+}
+
+void QDeclarativeViewer::senseImageMagick()
+{
+ QProcess proc;
+ proc.start("convert", QStringList() << "-h");
+ proc.waitForFinished(2000);
+ QString help = proc.readAllStandardOutput();
+ convertAvailable = help.contains("ImageMagick");
+}
+
+void QDeclarativeViewer::senseFfmpeg()
+{
+ QProcess proc;
+ proc.start("ffmpeg", QStringList() << "-h");
+ proc.waitForFinished(2000);
+ QString ffmpegHelp = proc.readAllStandardOutput();
+ ffmpegAvailable = ffmpegHelp.contains("-s ");
+ ffmpegHelp = tr("Video recording uses ffmpeg:")+"\n\n"+ffmpegHelp;
+
+ QDialog *d = new QDialog(recdlg);
+ QVBoxLayout *l = new QVBoxLayout(d);
+ QTextBrowser *b = new QTextBrowser(d);
+ QFont f = b->font();
+ f.setFamily("courier");
+ b->setFont(f);
+ b->setText(ffmpegHelp);
+ l->addWidget(b);
+ d->setLayout(l);
+ ffmpegHelpWindow = d;
+ connect(recdlg->ffmpegHelp,SIGNAL(clicked()), ffmpegHelpWindow, SLOT(show()));
+}
+
+void QDeclarativeViewer::setRecording(bool on)
+{
+ if (on == recordTimer.isRunning())
+ return;
+
+ int period = int(1000/record_rate+0.5);
+ QUnifiedTimer::instance()->setTimingInterval(on ? period:16);
+ QUnifiedTimer::instance()->setConsistentTiming(on);
+ if (on) {
+ canvas->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
+ recordTimer.setInterval(period);
+ recordTimer.setRunning(true);
+ frame_fmt = record_file.right(4).toLower();
+ frame = QImage(canvas->width(),canvas->height(),QImage::Format_RGB32);
+ if (frame_fmt != ".png" && (!convertAvailable || frame_fmt != ".gif")) {
+ // Stream video to ffmpeg
+
+ QProcess *proc = new QProcess(this);
+ connect(proc, SIGNAL(finished(int)), this, SLOT(ffmpegFinished(int)));
+ frame_stream = proc;
+
+ QStringList args;
+ args << "-y";
+ args << "-r" << QString::number(record_rate);
+ args << "-f" << "rawvideo";
+ args << "-pix_fmt" << (frame_fmt == ".gif" ? "rgb24" : "rgb32");
+ args << "-s" << QString("%1x%2").arg(canvas->width()).arg(canvas->height());
+ args << "-i" << "-";
+ if (record_outsize.isValid()) {
+ args << "-s" << QString("%1x%2").arg(record_outsize.width()).arg(record_outsize.height());
+ args << "-aspect" << QString::number(double(canvas->width())/canvas->height());
+ }
+ args += record_args;
+ args << record_file;
+ proc->start("ffmpeg",args);
+
+ } else {
+ // Store frames, save to GIF/PNG
+ frame_stream = 0;
+ }
+ } else {
+ canvas->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
+ recordTimer.setRunning(false);
+ if (frame_stream) {
+ qDebug() << "Saving video...";
+ frame_stream->close();
+ qDebug() << "Wrote" << record_file;
+ } else {
+ QProgressDialog progress(tr("Saving frames..."), tr("Cancel"), 0, frames.count()+10, this);
+ progress.setWindowModality(Qt::WindowModal);
+
+ int frame=0;
+ QStringList inputs;
+ qDebug() << "Saving frames...";
+
+ QString framename;
+ bool png_output = false;
+ if (record_file.right(4).toLower()==".png") {
+ if (record_file.contains('%'))
+ framename = record_file;
+ else
+ framename = record_file.left(record_file.length()-4)+"%04d"+record_file.right(4);
+ png_output = true;
+ } else {
+ framename = "tmp-frame%04d.png";
+ png_output = false;
+ }
+ foreach (QImage* img, frames) {
+ progress.setValue(progress.value()+1);
+ if (progress.wasCanceled())
+ break;
+ QString name;
+ name.sprintf(framename.toLocal8Bit(),frame++);
+ if (record_outsize.isValid())
+ *img = img->scaled(record_outsize,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
+ 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->save(name);
+ inputs << name;
+ delete img;
+ }
+
+ if (!progress.wasCanceled()) {
+ if (png_output) {
+ framename.replace(QRegExp("%\\d*."),"*");
+ qDebug() << "Wrote frames" << framename;
+ inputs.clear(); // don't remove them
+ } else {
+ // ImageMagick and gifsicle for GIF encoding
+ progress.setLabelText(tr("Converting frames to GIF file..."));
+ QStringList args;
+ args << "-delay" << QString::number(period/10);
+ args << inputs;
+ args << record_file;
+ qDebug() << "Converting..." << record_file << "(this may take a while)";
+ if (0!=QProcess::execute("convert", args)) {
+ qWarning() << "Cannot run ImageMagick 'convert' - recorded frames not converted";
+ inputs.clear(); // don't remove them
+ qDebug() << "Wrote frames tmp-frame*.png";
+ } else {
+ if (record_file.right(4).toLower() == ".gif") {
+ qDebug() << "Compressing..." << record_file;
+ if (0!=QProcess::execute("gifsicle", QStringList() << "-O2" << "-o" << record_file << record_file))
+ qWarning() << "Cannot run 'gifsicle' - not compressed";
+ }
+ qDebug() << "Wrote" << record_file;
+ }
+ }
+ }
+
+ progress.setValue(progress.maximum()-1);
+ foreach (QString name, inputs)
+ QFile::remove(name);
+
+ frames.clear();
+ }
+ }
+ qDebug() << "Recording: " << (recordTimer.isRunning()?"ON":"OFF");
+}
+
+void QDeclarativeViewer::ffmpegFinished(int code)
+{
+ qDebug() << "ffmpeg returned" << code << frame_stream->readAllStandardError();
+}
+
+void QDeclarativeViewer::autoStartRecording()
+{
+ setRecording(true);
+ autoStopTimer.setInterval(record_autotime);
+ autoStopTimer.setRunning(true);
+}
+
+void QDeclarativeViewer::autoStopRecording()
+{
+ setRecording(false);
+}
+
+void QDeclarativeViewer::recordFrame()
+{
+ canvas->QWidget::render(&frame);
+ if (frame_stream) {
+ if (frame_fmt == ".gif") {
+ // ffmpeg can't do 32bpp with gif
+ QImage rgb24 = frame.convertToFormat(QImage::Format_RGB888);
+ frame_stream->write((char*)rgb24.bits(),rgb24.numBytes());
+ } else {
+ frame_stream->write((char*)frame.bits(),frame.numBytes());
+ }
+ } else {
+ frames.append(new QImage(frame));
+ }
+}
+
+void QDeclarativeViewer::setDeviceKeys(bool on)
+{
+ devicemode = on;
+}
+
+void QDeclarativeViewer::setNetworkCacheSize(int size)
+{
+ namFactory->setCacheSize(size);
+}
+
+void QDeclarativeViewer::setUseGL(bool useGL)
+{
+#ifdef GL_SUPPORTED
+ if (useGL) {
+ QGLFormat format = QGLFormat::defaultFormat();
+ format.setSampleBuffers(false);
+
+ QGLWidget *glWidget = new QGLWidget(format);
+ glWidget->setAutoFillBackground(false);
+ canvas->setViewport(glWidget);
+ }
+#endif
+}
+
+void QDeclarativeViewer::setUseNativeFileBrowser(bool use)
+{
+ useQmlFileBrowser = !use;
+}
+
+void QDeclarativeViewer::registerTypes()
+{
+ QML_REGISTER_TYPE(QDeclarativeViewer, 1, 0, Screen, Screen);
+}
+
+QT_END_NAMESPACE
+
+#include "qmlruntime.moc"
diff --git a/tools/qml/qmlruntime.h b/tools/qml/qmlruntime.h
new file mode 100644
index 0000000..01777bd
--- /dev/null
+++ b/tools/qml/qmlruntime.h
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEWER_H
+#define QDECLARATIVEVIEWER_H
+
+#include <QMainWindow>
+#include <QMenuBar>
+#include <private/qdeclarativetimer_p.h>
+#include <QTime>
+#include <QList>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeView;
+class PreviewDeviceSkin;
+class QDeclarativeTestEngine;
+class QProcess;
+class RecordingDialog;
+class QDeclarativeTester;
+class QNetworkReply;
+class QNetworkCookieJar;
+class NetworkAccessManagerFactory;
+
+class QDeclarativeViewer
+#if defined(Q_OS_SYMBIAN)
+ : public QMainWindow
+#else
+ : public QWidget
+#endif
+{
+Q_OBJECT
+public:
+ QDeclarativeViewer(QWidget *parent=0, Qt::WindowFlags flags=0);
+ ~QDeclarativeViewer();
+
+ static void registerTypes();
+
+ enum ScriptOption {
+ Play = 0x00000001,
+ Record = 0x00000002,
+ TestImages = 0x00000004,
+ TestErrorProperty = 0x00000008,
+ SaveOnExit = 0x00000010,
+ ExitOnComplete = 0x00000020,
+ ExitOnFailure = 0x00000040
+ };
+ Q_DECLARE_FLAGS(ScriptOptions, ScriptOption)
+ void setScript(const QString &s) { m_script = s; }
+ void setScriptOptions(ScriptOptions opt) { m_scriptOptions = opt; }
+ void setRecordDither(const QString& s) { record_dither = s; }
+ void setRecordRate(int fps);
+ void setRecordFile(const QString&);
+ void setRecordArgs(const QStringList&);
+ void setRecording(bool on);
+ bool isRecording() const { return recordTimer.isRunning(); }
+ void setAutoRecord(int from, int to);
+ void setDeviceKeys(bool);
+ void setNetworkCacheSize(int size);
+ void addLibraryPath(const QString& lib);
+ void setUseGL(bool use);
+ void setUseNativeFileBrowser(bool);
+
+ QStringList builtinSkins() const;
+
+ QMenuBar *menuBar() const;
+
+public slots:
+ void sceneResized(QSize size);
+ void open(const QString&);
+ void openWgt(const QString&);
+ void openQml(const QString&);
+ void openFile();
+ void reload();
+ void takeSnapShot();
+ void toggleRecording();
+ void toggleRecordingWithSelection();
+ void ffmpegFinished(int code);
+ void setSkin(const QString& skinDirectory);
+ void showProxySettings ();
+ void proxySettingsChanged ();
+ void setScaleView();
+ void statusChanged();
+ void setSlowMode(bool);
+ void launch(const QString &);
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+
+ void createMenu(QMenuBar *menu, QMenu *flatmenu);
+
+private slots:
+ void autoStartRecording();
+ void autoStopRecording();
+ void recordFrame();
+ void chooseRecordingOptions();
+ void pickRecordingFile();
+ void setScaleSkin();
+ void setPortrait();
+ void setLandscape();
+ void toggleOrientation();
+ void startNetwork();
+ void toggleFullScreen();
+ void unpackWgt();
+
+private:
+ QString getVideoFileName();
+
+ PreviewDeviceSkin *skin;
+ QSize skinscreensize;
+ QDeclarativeView *canvas;
+ QString currentFileOrUrl;
+ QDeclarativeTimer recordTimer;
+ QString frame_fmt;
+ QImage frame;
+ QList<QImage*> frames;
+ QProcess* frame_stream;
+ QDeclarativeTimer autoStartTimer;
+ QDeclarativeTimer autoStopTimer;
+ QString record_dither;
+ QString record_file;
+ QSize record_outsize;
+ QStringList record_args;
+ int record_rate;
+ int record_autotime;
+ bool devicemode;
+ QAction *recordAction;
+ QString currentSkin;
+ bool scaleSkin;
+ mutable QMenuBar *mb;
+ RecordingDialog *recdlg;
+
+ void senseImageMagick();
+ void senseFfmpeg();
+ QWidget *ffmpegHelpWindow;
+ bool ffmpegAvailable;
+ bool convertAvailable;
+
+ QAction *portraitOrientation;
+ QAction *landscapeOrientation;
+
+ QString m_script;
+ ScriptOptions m_scriptOptions;
+ QDeclarativeTester *tester;
+
+ QNetworkReply *wgtreply;
+ QString wgtdir;
+
+ NetworkAccessManagerFactory *namFactory;
+
+ bool useQmlFileBrowser;
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeViewer::ScriptOptions)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qml/qmlruntime.qrc b/tools/qml/qmlruntime.qrc
new file mode 100644
index 0000000..3a9e608
--- /dev/null
+++ b/tools/qml/qmlruntime.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/" >
+ <file>content/Browser.qml</file>
+ <file>content/images/up.png</file>
+ <file>content/images/folder.png</file>
+ <file>content/images/titlebar.sci</file>
+ <file>content/images/titlebar.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/qml/recopts.ui b/tools/qml/recopts.ui
new file mode 100644
index 0000000..ce2da30
--- /dev/null
+++ b/tools/qml/recopts.ui
@@ -0,0 +1,513 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>RecordingOptions</class>
+ <widget class="QDialog" name="RecordingOptions">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>316</width>
+ <height>436</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Video options</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>File:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="file"/>
+ </item>
+ <item>
+ <widget class="QToolButton" name="pickfile">
+ <property name="text">
+ <string>...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Size</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="sizeOriginal">
+ <property name="text">
+ <string/>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QRadioButton" name="sizeVGA">
+ <property name="text">
+ <string>VGA</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QRadioButton" name="size720p">
+ <property name="text">
+ <string>720p</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QRadioButton" name="sizeQVGA">
+ <property name="text">
+ <string>QVGA</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QRadioButton" name="sizeCustom">
+ <property name="text">
+ <string>Width:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="sizeWidth">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>9999</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Height:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="sizeHeight">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>9999</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="0" column="2">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="rateOptions">
+ <property name="title">
+ <string>Rate</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="0">
+ <widget class="QRadioButton" name="hz60">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>60Hz</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QRadioButton" name="hz50">
+ <property name="text">
+ <string>50Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QRadioButton" name="hz25">
+ <property name="text">
+ <string>25Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="4">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QRadioButton" name="hzCustom">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="hz">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>60</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>100</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="2">
+ <widget class="QRadioButton" name="hz24">
+ <property name="text">
+ <string>24Hz</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="3">
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="1">
+ <spacer name="horizontalSpacer_5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="ffmpegOptions">
+ <property name="title">
+ <string>Profile</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0" colspan="3">
+ <widget class="QComboBox" name="profile"/>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <widget class="QLineEdit" name="args"/>
+ </item>
+ <item row="1" column="2">
+ <widget class="QToolButton" name="ffmpegHelp">
+ <property name="text">
+ <string>Help</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="warning">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>file</tabstop>
+ <tabstop>pickfile</tabstop>
+ <tabstop>sizeOriginal</tabstop>
+ <tabstop>sizeVGA</tabstop>
+ <tabstop>size720p</tabstop>
+ <tabstop>sizeQVGA</tabstop>
+ <tabstop>sizeCustom</tabstop>
+ <tabstop>sizeWidth</tabstop>
+ <tabstop>sizeHeight</tabstop>
+ <tabstop>hz60</tabstop>
+ <tabstop>hz25</tabstop>
+ <tabstop>hz50</tabstop>
+ <tabstop>hz24</tabstop>
+ <tabstop>hzCustom</tabstop>
+ <tabstop>hz</tabstop>
+ <tabstop>profile</tabstop>
+ <tabstop>args</tabstop>
+ <tabstop>ffmpegHelp</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>hzCustom</sender>
+ <signal>clicked()</signal>
+ <receiver>hz</receiver>
+ <slot>setFocus()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>43</x>
+ <y>257</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>129</x>
+ <y>262</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>hz</sender>
+ <signal>textChanged(QString)</signal>
+ <receiver>hzCustom</receiver>
+ <slot>toggle()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>143</x>
+ <y>262</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>43</x>
+ <y>257</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>hz</sender>
+ <signal>selectionChanged()</signal>
+ <receiver>hzCustom</receiver>
+ <slot>toggle()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>143</x>
+ <y>262</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>43</x>
+ <y>257</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>258</x>
+ <y>424</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>60</x>
+ <y>219</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>258</x>
+ <y>424</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>92</x>
+ <y>219</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>profile</sender>
+ <signal>activated(int)</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>pickProfile(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>92</x>
+ <y>329</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>48</x>
+ <y>194</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>args</sender>
+ <signal>textEdited(QString)</signal>
+ <receiver>RecordingOptions</receiver>
+ <slot>storeCustomArgs(QString)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>128</x>
+ <y>357</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>102</x>
+ <y>189</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>sizeWidth</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>sizeCustom</receiver>
+ <slot>toggle()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>108</x>
+ <y>133</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>48</x>
+ <y>133</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>sizeHeight</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>sizeCustom</receiver>
+ <slot>toggle()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>212</x>
+ <y>133</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>64</x>
+ <y>129</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <signal>filePicked(QString)</signal>
+ <signal>argumentsPicked(QString)</signal>
+ <slot>pickFile()</slot>
+ <slot>pickProfile(int)</slot>
+ <slot>storeCustomArgs(QString)</slot>
+ </slots>
+</ui>