aboutsummaryrefslogtreecommitdiffstats
path: root/tools/qmlviewer
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit885735d011472bcfbb96e688d9e64553d7fe9d4b (patch)
tree734963625eba643bf11bc4870a4c407809a6400a /tools/qmlviewer
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'tools/qmlviewer')
-rw-r--r--tools/qmlviewer/Info_mac.plist49
-rw-r--r--tools/qmlviewer/browser/Browser.qml318
-rw-r--r--tools/qmlviewer/browser/browser.qrc9
-rw-r--r--tools/qmlviewer/browser/images/folder.pngbin0 -> 1841 bytes
-rw-r--r--tools/qmlviewer/browser/images/titlebar.pngbin0 -> 1436 bytes
-rw-r--r--tools/qmlviewer/browser/images/titlebar.sci5
-rw-r--r--tools/qmlviewer/browser/images/up.pngbin0 -> 662 bytes
-rw-r--r--tools/qmlviewer/deviceorientation.cpp80
-rw-r--r--tools/qmlviewer/deviceorientation.h84
-rw-r--r--tools/qmlviewer/deviceorientation_harmattan.cpp161
-rw-r--r--tools/qmlviewer/deviceorientation_maemo5.cpp148
-rw-r--r--tools/qmlviewer/deviceorientation_symbian.cpp192
-rw-r--r--tools/qmlviewer/loggerwidget.cpp230
-rw-r--r--tools/qmlviewer/loggerwidget.h101
-rw-r--r--tools/qmlviewer/main.cpp597
-rw-r--r--tools/qmlviewer/proxysettings.cpp113
-rw-r--r--tools/qmlviewer/proxysettings.h75
-rw-r--r--tools/qmlviewer/proxysettings.ui115
-rw-r--r--tools/qmlviewer/proxysettings_maemo5.ui177
-rw-r--r--tools/qmlviewer/qdeclarativetester.cpp453
-rw-r--r--tools/qmlviewer/qdeclarativetester.h290
-rw-r--r--tools/qmlviewer/qml.icnsbin0 -> 196156 bytes
-rw-r--r--tools/qmlviewer/qml.pri50
-rw-r--r--tools/qmlviewer/qmlruntime.cpp1552
-rw-r--r--tools/qmlviewer/qmlruntime.h204
-rw-r--r--tools/qmlviewer/qmlviewer.pro52
-rw-r--r--tools/qmlviewer/recopts.ui513
-rw-r--r--tools/qmlviewer/recopts_maemo5.ui254
-rw-r--r--tools/qmlviewer/startup/Logo.qml179
-rw-r--r--tools/qmlviewer/startup/qt-back.pngbin0 -> 3549 bytes
-rw-r--r--tools/qmlviewer/startup/qt-blue.jpgbin0 -> 20900 bytes
-rw-r--r--tools/qmlviewer/startup/qt-front.pngbin0 -> 3318 bytes
-rw-r--r--tools/qmlviewer/startup/qt-sketch.jpgbin0 -> 17048 bytes
-rw-r--r--tools/qmlviewer/startup/qt-text.pngbin0 -> 14565 bytes
-rw-r--r--tools/qmlviewer/startup/quick-blur.pngbin0 -> 2826 bytes
-rw-r--r--tools/qmlviewer/startup/quick-regular.pngbin0 -> 1399 bytes
-rw-r--r--tools/qmlviewer/startup/shadow.pngbin0 -> 1592 bytes
-rw-r--r--tools/qmlviewer/startup/startup.qml173
-rw-r--r--tools/qmlviewer/startup/startup.qrc16
-rw-r--r--tools/qmlviewer/startup/white-star.pngbin0 -> 2651 bytes
-rw-r--r--tools/qmlviewer/texteditautoresizer_maemo5.h113
41 files changed, 6303 insertions, 0 deletions
diff --git a/tools/qmlviewer/Info_mac.plist b/tools/qmlviewer/Info_mac.plist
new file mode 100644
index 0000000000..08775479ba
--- /dev/null
+++ b/tools/qmlviewer/Info_mac.plist
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
+<plist version="0.1">
+<dict>
+ <key>CFBundleIconFile</key>
+ <string>@ICON@</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.nokia.qt.qml</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Created by Qt/QMake</string>
+ <key>CFBundleSignature</key>
+ <string>@TYPEINFO@</string>
+ <key>CFBundleExecutable</key>
+ <string>@EXECUTABLE@</string>
+ <key>UTExportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeIdentifier</key>
+ <string>com.nokia.qt.qml</string>
+ <key>UTTypeDescription</key>
+ <string>Qt Markup Language</string>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.plain-text</string>
+ </array>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>qml</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>com.nokia.qt.qml</string>
+ </array>
+ <key>CFBundleTypeRole</key>
+ <string>Viewer</string>
+ </dict>
+ </array>
+</dict>
+</plist>
diff --git a/tools/qmlviewer/browser/Browser.qml b/tools/qmlviewer/browser/Browser.qml
new file mode 100644
index 0000000000..972265b07b
--- /dev/null
+++ b/tools/qmlviewer/browser/Browser.qml
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import Qt.labs.folderlistmodel 1.0
+
+Rectangle {
+ id: root
+ property bool showFocusHighlight: false
+ property variant folders: folders1
+ property variant 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 }
+
+ 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;
+ }
+ function keyPressed(key) {
+ switch (key) {
+ case Qt.Key_Up:
+ case Qt.Key_Down:
+ case Qt.Key_Left:
+ case Qt.Key_Right:
+ root.showFocusHighlight = true;
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ 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
+ color: palette.highlight
+ 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.showFocusHighlight) ? palette.highlightedText : palette.windowText
+ elide: Text.ElideRight
+ }
+ MouseArea {
+ id: mouseRegion
+ anchors.fill: parent
+ onPressed: {
+ root.showFocusHighlight = false;
+ wrapper.ListView.view.currentIndex = index;
+ }
+ onClicked: { if (folders == wrapper.ListView.view.model) 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.showFocusHighlight && view1.count != 0
+ gradient: Gradient {
+ GradientStop { id: t1; position: 0.0; color: palette.highlight }
+ GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
+ }
+ width: view1.currentItem == null ? 0 : view1.currentItem.width
+ }
+ 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 { properties: "x"; duration: 250 }
+ }
+ },
+ Transition {
+ NumberAnimation { properties: "x"; duration: 250 }
+ NumberAnimation { properties: "x"; duration: 250 }
+ }
+ ]
+ Keys.onPressed: root.keyPressed(event.key)
+ }
+
+ 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.showFocusHighlight && view2.count != 0
+ gradient: Gradient {
+ GradientStop { id: t1; position: 0.0; color: palette.highlight }
+ GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) }
+ }
+ width: view1.currentItem == null ? 0 : view1.currentItem.width
+ }
+ 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 { properties: "x"; duration: 250 }
+ }
+ },
+ Transition {
+ NumberAnimation { properties: "x"; duration: 250 }
+ }
+ ]
+ Keys.onPressed: root.keyPressed(event.key)
+ }
+
+ Keys.onPressed: {
+ root.keyPressed(event.key);
+ 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/qmlviewer/browser/browser.qrc b/tools/qmlviewer/browser/browser.qrc
new file mode 100644
index 0000000000..9c688e7521
--- /dev/null
+++ b/tools/qmlviewer/browser/browser.qrc
@@ -0,0 +1,9 @@
+<RCC>
+ <qresource prefix="/browser">
+ <file>Browser.qml</file>
+ <file>images/up.png</file>
+ <file>images/folder.png</file>
+ <file>images/titlebar.sci</file>
+ <file>images/titlebar.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/qmlviewer/browser/images/folder.png b/tools/qmlviewer/browser/images/folder.png
new file mode 100644
index 0000000000..e53e2ad464
--- /dev/null
+++ b/tools/qmlviewer/browser/images/folder.png
Binary files differ
diff --git a/tools/qmlviewer/browser/images/titlebar.png b/tools/qmlviewer/browser/images/titlebar.png
new file mode 100644
index 0000000000..51c90082d0
--- /dev/null
+++ b/tools/qmlviewer/browser/images/titlebar.png
Binary files differ
diff --git a/tools/qmlviewer/browser/images/titlebar.sci b/tools/qmlviewer/browser/images/titlebar.sci
new file mode 100644
index 0000000000..0418d94cd6
--- /dev/null
+++ b/tools/qmlviewer/browser/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/qmlviewer/browser/images/up.png b/tools/qmlviewer/browser/images/up.png
new file mode 100644
index 0000000000..b05f8025d0
--- /dev/null
+++ b/tools/qmlviewer/browser/images/up.png
Binary files differ
diff --git a/tools/qmlviewer/deviceorientation.cpp b/tools/qmlviewer/deviceorientation.cpp
new file mode 100644
index 0000000000..b4459c7c55
--- /dev/null
+++ b/tools/qmlviewer/deviceorientation.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 pauseListening() {
+ }
+ void resumeListening() {
+ }
+
+ 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/qmlviewer/deviceorientation.h b/tools/qmlviewer/deviceorientation.h
new file mode 100644
index 0000000000..a4f9f671dd
--- /dev/null
+++ b/tools/qmlviewer/deviceorientation.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ORIENTATION_H
+#define ORIENTATION_H
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class DeviceOrientationPrivate;
+class DeviceOrientation : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(Orientation)
+public:
+ enum Orientation {
+ UnknownOrientation,
+ Portrait,
+ Landscape,
+ PortraitInverted,
+ LandscapeInverted
+ };
+
+ virtual Orientation orientation() const = 0;
+ virtual void setOrientation(Orientation) = 0;
+
+ virtual void pauseListening() = 0;
+ virtual void resumeListening() = 0;
+
+ static DeviceOrientation *instance();
+
+signals:
+ void orientationChanged();
+
+protected:
+ DeviceOrientation() {}
+
+private:
+ DeviceOrientationPrivate *d_ptr;
+ friend class DeviceOrientationPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qmlviewer/deviceorientation_harmattan.cpp b/tools/qmlviewer/deviceorientation_harmattan.cpp
new file mode 100644
index 0000000000..eb91c30de4
--- /dev/null
+++ b/tools/qmlviewer/deviceorientation_harmattan.cpp
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceorientation.h"
+#include <QtDBus>
+#include <QDebug>
+
+#define ORIENTATION_SERVICE "com.nokia.SensorService"
+#define ORIENTATION_PATH "/org/maemo/contextkit/Screen/TopEdge"
+#define CONTEXT_INTERFACE "org.maemo.contextkit.Property"
+#define CONTEXT_CHANGED "ValueChanged"
+#define CONTEXT_SUBSCRIBE "Subscribe"
+#define CONTEXT_UNSUBSCRIBE "Unsubscribe"
+#define CONTEXT_GET "Get"
+
+
+class HarmattanOrientation : public DeviceOrientation
+{
+ Q_OBJECT
+public:
+ HarmattanOrientation()
+ : o(UnknownOrientation), sensorEnabled(false)
+ {
+ resumeListening();
+ // connect to the orientation change signal
+ bool ok = QDBusConnection::systemBus().connect(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE,
+ CONTEXT_CHANGED,
+ this,
+ SLOT(deviceOrientationChanged(QList<QVariant>,quint64)));
+// qDebug() << "connection OK" << ok;
+ QDBusMessage reply = QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_GET));
+ if (reply.type() != QDBusMessage::ErrorMessage) {
+ QList<QVariant> args;
+ qvariant_cast<QDBusArgument>(reply.arguments().at(0)) >> args;
+ deviceOrientationChanged(args, 0);
+ }
+ }
+
+ ~HarmattanOrientation()
+ {
+ // unsubscribe from the orientation sensor
+ if (sensorEnabled)
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_UNSUBSCRIBE));
+ }
+
+ inline Orientation orientation() const
+ {
+ return o;
+ }
+
+ void setOrientation(Orientation)
+ {
+ }
+
+ void pauseListening() {
+ if (sensorEnabled) {
+ // unsubscribe from the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_UNSUBSCRIBE));
+ sensorEnabled = false;
+ }
+ }
+
+ void resumeListening() {
+ if (!sensorEnabled) {
+ // subscribe to the orientation sensor
+ QDBusMessage reply = QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(ORIENTATION_SERVICE, ORIENTATION_PATH,
+ CONTEXT_INTERFACE, CONTEXT_SUBSCRIBE));
+
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning("Unable to retrieve device orientation: %s", qPrintable(reply.errorMessage()));
+ } else {
+ sensorEnabled = true;
+ }
+ }
+ }
+
+private Q_SLOTS:
+ void deviceOrientationChanged(QList<QVariant> args,quint64)
+ {
+ if (args.count() == 0)
+ return;
+ Orientation newOrientation = toOrientation(args.at(0).toString());
+ if (newOrientation != o) {
+ o = newOrientation;
+ emit orientationChanged();
+ }
+// qDebug() << "orientation" << args.at(0).toString();
+ }
+
+private:
+ static Orientation toOrientation(const QString &nativeOrientation)
+ {
+ if (nativeOrientation == "top")
+ return Landscape;
+ else if (nativeOrientation == "left")
+ return Portrait;
+ else if (nativeOrientation == "bottom")
+ return LandscapeInverted;
+ else if (nativeOrientation == "right")
+ return PortraitInverted;
+ return UnknownOrientation;
+ }
+
+private:
+ Orientation o;
+ bool sensorEnabled;
+};
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static HarmattanOrientation *o = new HarmattanOrientation;
+ return o;
+}
+
+#include "deviceorientation_harmattan.moc"
diff --git a/tools/qmlviewer/deviceorientation_maemo5.cpp b/tools/qmlviewer/deviceorientation_maemo5.cpp
new file mode 100644
index 0000000000..2a04b0892c
--- /dev/null
+++ b/tools/qmlviewer/deviceorientation_maemo5.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceorientation.h"
+#include <QtDBus>
+
+#include <mce/mode-names.h>
+#include <mce/dbus-names.h>
+
+class MaemoOrientation : public DeviceOrientation
+{
+ Q_OBJECT
+public:
+ MaemoOrientation()
+ : o(UnknownOrientation), sensorEnabled(false)
+ {
+ resumeListening();
+ // connect to the orientation change signal
+ QDBusConnection::systemBus().connect(QString(), MCE_SIGNAL_PATH, MCE_SIGNAL_IF,
+ MCE_DEVICE_ORIENTATION_SIG,
+ this,
+ SLOT(deviceOrientationChanged(QString)));
+ }
+
+ ~MaemoOrientation()
+ {
+ // disable the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_ACCELEROMETER_DISABLE_REQ));
+ }
+
+ inline Orientation orientation() const
+ {
+ return o;
+ }
+
+ void setOrientation(Orientation o)
+ {
+ }
+
+ void pauseListening() {
+ if (sensorEnabled) {
+ // disable the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_ACCELEROMETER_DISABLE_REQ));
+ sensorEnabled = false;
+ }
+ }
+
+ void resumeListening() {
+ if (!sensorEnabled) {
+ // enable the orientation sensor
+ QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_ACCELEROMETER_ENABLE_REQ));
+
+ QDBusMessage reply = QDBusConnection::systemBus().call(
+ QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH,
+ MCE_REQUEST_IF, MCE_DEVICE_ORIENTATION_GET));
+
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ qWarning("Unable to retrieve device orientation: %s", qPrintable(reply.errorMessage()));
+ } else {
+ Orientation orientation = toOrientation(reply.arguments().value(0).toString());
+ if (o != orientation) {
+ o = orientation;
+ emit orientationChanged();
+ }
+ sensorEnabled = true;
+ }
+ }
+ }
+
+private Q_SLOTS:
+ void deviceOrientationChanged(const QString &newOrientation)
+ {
+ o = toOrientation(newOrientation);
+
+ emit orientationChanged();
+// printf("%d\n", o);
+ }
+
+private:
+ static Orientation toOrientation(const QString &nativeOrientation)
+ {
+ if (nativeOrientation == MCE_ORIENTATION_LANDSCAPE)
+ return Landscape;
+ else if (nativeOrientation == MCE_ORIENTATION_LANDSCAPE_INVERTED)
+ return LandscapeInverted;
+ else if (nativeOrientation == MCE_ORIENTATION_PORTRAIT)
+ return Portrait;
+ else if (nativeOrientation == MCE_ORIENTATION_PORTRAIT_INVERTED)
+ return PortraitInverted;
+ return UnknownOrientation;
+ }
+
+private:
+ Orientation o;
+ bool sensorEnabled;
+};
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static MaemoOrientation *o = new MaemoOrientation;
+ return o;
+}
+
+#include "deviceorientation_maemo5.moc"
diff --git a/tools/qmlviewer/deviceorientation_symbian.cpp b/tools/qmlviewer/deviceorientation_symbian.cpp
new file mode 100644
index 0000000000..f1f8e6e596
--- /dev/null
+++ b/tools/qmlviewer/deviceorientation_symbian.cpp
@@ -0,0 +1,192 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "deviceorientation.h"
+
+#include <e32base.h>
+#include <sensrvchannelfinder.h>
+#include <sensrvdatalistener.h>
+#include <sensrvchannel.h>
+#include <sensrvorientationsensor.h>
+
+class SymbianOrientation : public DeviceOrientation, public MSensrvDataListener
+{
+ Q_OBJECT
+public:
+ SymbianOrientation()
+ : DeviceOrientation(), m_current(UnknownOrientation), m_sensorChannel(0), m_channelOpen(false)
+ {
+ TRAP_IGNORE(initL());
+ if (!m_sensorChannel)
+ qWarning("No valid sensors found.");
+ }
+
+ ~SymbianOrientation()
+ {
+ if (m_sensorChannel) {
+ m_sensorChannel->StopDataListening();
+ m_sensorChannel->CloseChannel();
+ delete m_sensorChannel;
+ }
+ }
+
+ void initL()
+ {
+ CSensrvChannelFinder *channelFinder = CSensrvChannelFinder::NewLC();
+ RSensrvChannelInfoList channelInfoList;
+ CleanupClosePushL(channelInfoList);
+
+ TSensrvChannelInfo searchConditions;
+ searchConditions.iChannelType = KSensrvChannelTypeIdOrientationData;
+ channelFinder->FindChannelsL(channelInfoList, searchConditions);
+
+ for (int i = 0; i < channelInfoList.Count(); ++i) {
+ TRAPD(error, m_sensorChannel = CSensrvChannel::NewL(channelInfoList[i]));
+ if (!error)
+ TRAP(error, m_sensorChannel->OpenChannelL());
+ if (!error) {
+ TRAP(error, m_sensorChannel->StartDataListeningL(this, 1, 1, 0));
+ m_channelOpen = true;
+ break;
+ }
+ if (error) {
+ delete m_sensorChannel;
+ m_sensorChannel = 0;
+ }
+ }
+
+ channelInfoList.Close();
+ CleanupStack::Pop(&channelInfoList);
+ CleanupStack::PopAndDestroy(channelFinder);
+ }
+
+ Orientation orientation() const
+ {
+ return m_current;
+ }
+
+ void setOrientation(Orientation) { }
+
+private:
+ DeviceOrientation::Orientation m_current;
+ CSensrvChannel *m_sensorChannel;
+ bool m_channelOpen;
+ void pauseListening() {
+ if (m_sensorChannel && m_channelOpen) {
+ m_sensorChannel->StopDataListening();
+ m_sensorChannel->CloseChannel();
+ m_channelOpen = false;
+ }
+ }
+
+ void resumeListening() {
+ if (m_sensorChannel && !m_channelOpen) {
+ TRAPD(error, m_sensorChannel->OpenChannelL());
+ if (!error) {
+ TRAP(error, m_sensorChannel->StartDataListeningL(this, 1, 1, 0));
+ if (!error) {
+ m_channelOpen = true;
+ }
+ }
+ if (error) {
+ delete m_sensorChannel;
+ m_sensorChannel = 0;
+ }
+ }
+ }
+
+ void DataReceived(CSensrvChannel &channel, TInt count, TInt dataLost)
+ {
+ Q_UNUSED(dataLost)
+ if (channel.GetChannelInfo().iChannelType == KSensrvChannelTypeIdOrientationData) {
+ TSensrvOrientationData data;
+ for (int i = 0; i < count; ++i) {
+ TPckgBuf<TSensrvOrientationData> dataBuf;
+ channel.GetData(dataBuf);
+ data = dataBuf();
+ Orientation orientation = UnknownOrientation;
+ switch (data.iDeviceOrientation) {
+ case TSensrvOrientationData::EOrientationDisplayUp:
+ orientation = Portrait;
+ break;
+ case TSensrvOrientationData::EOrientationDisplayRightUp:
+ orientation = Landscape;
+ break;
+ case TSensrvOrientationData::EOrientationDisplayLeftUp:
+ orientation = LandscapeInverted;
+ break;
+ case TSensrvOrientationData::EOrientationDisplayDown:
+ orientation = PortraitInverted;
+ break;
+ case TSensrvOrientationData::EOrientationUndefined:
+ case TSensrvOrientationData::EOrientationDisplayUpwards:
+ case TSensrvOrientationData::EOrientationDisplayDownwards:
+ default:
+ break;
+ }
+
+ if (m_current != orientation && orientation != UnknownOrientation) {
+ m_current = orientation;
+ emit orientationChanged();
+ }
+ }
+ }
+ }
+
+ void DataError(CSensrvChannel& /* channel */, TSensrvErrorSeverity /* error */)
+ {
+ }
+
+ void GetDataListenerInterfaceL(TUid /* interfaceUid */, TAny*& /* interface */)
+ {
+ }
+};
+
+
+DeviceOrientation* DeviceOrientation::instance()
+{
+ static SymbianOrientation *o = 0;
+ if (!o)
+ o = new SymbianOrientation;
+ return o;
+}
+
+#include "deviceorientation_symbian.moc"
diff --git a/tools/qmlviewer/loggerwidget.cpp b/tools/qmlviewer/loggerwidget.cpp
new file mode 100644
index 0000000000..3f2337a622
--- /dev/null
+++ b/tools/qmlviewer/loggerwidget.cpp
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qglobal.h>
+#include <QDebug>
+#include <QSettings>
+#include <QActionGroup>
+#include <QMenu>
+#include <QPlainTextEdit>
+#include <QLabel>
+#include <QVBoxLayout>
+#ifdef Q_WS_MAEMO_5
+# include <QScrollArea>
+# include <QVBoxLayout>
+# include "texteditautoresizer_maemo5.h"
+#endif
+
+#include "loggerwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+LoggerWidget::LoggerWidget(QWidget *parent) :
+ QMainWindow(parent),
+ m_visibilityOrigin(SettingsOrigin)
+{
+ setAttribute(Qt::WA_QuitOnClose, false);
+ setWindowTitle(tr("Warnings"));
+
+ m_plainTextEdit = new QPlainTextEdit();
+
+#if defined(Q_OS_SYMBIAN)
+ QAction* clearAction = new QAction(tr("Clear"), this);
+ clearAction->setSoftKeyRole(QAction::PositiveSoftKey);
+ connect(clearAction, SIGNAL(triggered()), m_plainTextEdit, SLOT(clear()));
+ addAction(clearAction);
+
+ m_plainTextEdit->setReadOnly(true);
+ QAction* backAction = new QAction( tr("Back"), this );
+ backAction->setSoftKeyRole( QAction::NegativeSoftKey );
+ connect(backAction, SIGNAL(triggered()), this, SLOT(hide()));
+ addAction( backAction );
+#endif
+
+#ifdef Q_WS_MAEMO_5
+ new TextEditAutoResizer(m_plainTextEdit);
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+ QScrollArea *area = new QScrollArea();
+ area->setWidget(m_plainTextEdit);
+ area->setWidgetResizable(true);
+ setCentralWidget(area);
+#else
+ setCentralWidget(m_plainTextEdit);
+#endif
+
+ m_noWarningsLabel = new QLabel(m_plainTextEdit);
+ m_noWarningsLabel->setText(tr("(No warnings)"));
+ m_noWarningsLabel->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->addWidget(m_noWarningsLabel);
+ m_plainTextEdit->setLayout(layout);
+ connect(m_plainTextEdit, SIGNAL(textChanged()), this, SLOT(updateNoWarningsLabel()));
+
+ readSettings();
+ setupPreferencesMenu();
+}
+
+void LoggerWidget::append(const QString &msg)
+{
+ m_plainTextEdit->appendPlainText(msg);
+
+ if (!isVisible() && (defaultVisibility() == AutoShowWarnings))
+ setVisible(true);
+}
+
+LoggerWidget::Visibility LoggerWidget::defaultVisibility() const
+{
+ return m_visibility;
+}
+
+void LoggerWidget::setDefaultVisibility(LoggerWidget::Visibility visibility)
+{
+ if (m_visibility == visibility)
+ return;
+
+ m_visibility = visibility;
+ m_visibilityOrigin = CommandLineOrigin;
+
+ m_preferencesMenu->setEnabled(m_visibilityOrigin == SettingsOrigin);
+}
+
+QMenu *LoggerWidget::preferencesMenu()
+{
+ return m_preferencesMenu;
+}
+
+QAction *LoggerWidget::showAction()
+{
+ return m_showWidgetAction;
+}
+
+void LoggerWidget::readSettings()
+{
+ QSettings settings;
+ QString warningsPreferences = settings.value("warnings", "hide").toString();
+ if (warningsPreferences == "show") {
+ m_visibility = ShowWarnings;
+ } else if (warningsPreferences == "hide") {
+ m_visibility = HideWarnings;
+ } else {
+ m_visibility = AutoShowWarnings;
+ }
+}
+
+void LoggerWidget::saveSettings()
+{
+ if (m_visibilityOrigin != SettingsOrigin)
+ return;
+
+ QString value = "autoShow";
+ if (defaultVisibility() == ShowWarnings) {
+ value = "show";
+ } else if (defaultVisibility() == HideWarnings) {
+ value = "hide";
+ }
+
+ QSettings settings;
+ settings.setValue("warnings", value);
+}
+
+void LoggerWidget::warningsPreferenceChanged(QAction *action)
+{
+ Visibility newSetting = static_cast<Visibility>(action->data().toInt());
+ m_visibility = newSetting;
+ saveSettings();
+}
+
+void LoggerWidget::showEvent(QShowEvent *event)
+{
+ QWidget::showEvent(event);
+ emit opened();
+}
+
+void LoggerWidget::closeEvent(QCloseEvent *event)
+{
+ QWidget::closeEvent(event);
+ emit closed();
+}
+
+void LoggerWidget::setupPreferencesMenu()
+{
+ m_preferencesMenu = new QMenu(tr("Warnings"));
+ QActionGroup *warnings = new QActionGroup(m_preferencesMenu);
+ warnings->setExclusive(true);
+
+ connect(warnings, SIGNAL(triggered(QAction*)), this, SLOT(warningsPreferenceChanged(QAction*)));
+
+ QAction *showWarningsPreference = new QAction(tr("Show by default"), m_preferencesMenu);
+ showWarningsPreference->setCheckable(true);
+ showWarningsPreference->setData(LoggerWidget::ShowWarnings);
+ warnings->addAction(showWarningsPreference);
+ m_preferencesMenu->addAction(showWarningsPreference);
+
+ QAction *hideWarningsPreference = new QAction(tr("Hide by default"), m_preferencesMenu);
+ hideWarningsPreference->setCheckable(true);
+ hideWarningsPreference->setData(LoggerWidget::HideWarnings);
+ warnings->addAction(hideWarningsPreference);
+ m_preferencesMenu->addAction(hideWarningsPreference);
+
+ QAction *autoWarningsPreference = new QAction(tr("Show for first warning"), m_preferencesMenu);
+ autoWarningsPreference->setCheckable(true);
+ autoWarningsPreference->setData(LoggerWidget::AutoShowWarnings);
+ warnings->addAction(autoWarningsPreference);
+ m_preferencesMenu->addAction(autoWarningsPreference);
+
+ switch (defaultVisibility()) {
+ case LoggerWidget::ShowWarnings:
+ showWarningsPreference->setChecked(true);
+ break;
+ case LoggerWidget::HideWarnings:
+ hideWarningsPreference->setChecked(true);
+ break;
+ default:
+ autoWarningsPreference->setChecked(true);
+ }
+}
+
+void LoggerWidget::updateNoWarningsLabel()
+{
+ m_noWarningsLabel->setVisible(m_plainTextEdit->toPlainText().length() == 0);
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qmlviewer/loggerwidget.h b/tools/qmlviewer/loggerwidget.h
new file mode 100644
index 0000000000..a3e887107a
--- /dev/null
+++ b/tools/qmlviewer/loggerwidget.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LOGGERWIDGET_H
+#define LOGGERWIDGET_H
+
+#include <QMainWindow>
+#include <QMetaType>
+
+QT_BEGIN_NAMESPACE
+
+class QPlainTextEdit;
+class QLabel;
+class QMenu;
+class QAction;
+
+class LoggerWidget : public QMainWindow {
+ Q_OBJECT
+public:
+ LoggerWidget(QWidget *parent=0);
+
+ enum Visibility { ShowWarnings, HideWarnings, AutoShowWarnings };
+
+ Visibility defaultVisibility() const;
+ void setDefaultVisibility(Visibility visibility);
+
+ QMenu *preferencesMenu();
+ QAction *showAction();
+
+public slots:
+ void append(const QString &msg);
+ void updateNoWarningsLabel();
+
+private slots:
+ void warningsPreferenceChanged(QAction *action);
+ void readSettings();
+ void saveSettings();
+
+protected:
+ void showEvent(QShowEvent *event);
+ void closeEvent(QCloseEvent *event);
+
+signals:
+ void opened();
+ void closed();
+
+private:
+ void setupPreferencesMenu();
+
+ QMenu *m_preferencesMenu;
+ QAction *m_showWidgetAction;
+ QPlainTextEdit *m_plainTextEdit;
+ QLabel *m_noWarningsLabel;
+ enum ConfigOrigin { CommandLineOrigin, SettingsOrigin };
+ ConfigOrigin m_visibilityOrigin;
+ Visibility m_visibility;
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(LoggerWidget::Visibility)
+
+#endif // LOGGERWIDGET_H
diff --git a/tools/qmlviewer/main.cpp b/tools/qmlviewer/main.cpp
new file mode 100644
index 0000000000..b2c7f4f730
--- /dev/null
+++ b/tools/qmlviewer/main.cpp
@@ -0,0 +1,597 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarative.h"
+#include "qmlruntime.h"
+#include "qdeclarativeengine.h"
+#include "loggerwidget.h"
+#include <QWidget>
+#include <QDir>
+#include <QApplication>
+#include <QTranslator>
+#include <QDebug>
+#include <QMessageBox>
+#include <QAtomicInt>
+#include "qdeclarativetester.h"
+#include <private/qdeclarativedebughelper_p.h>
+
+QT_USE_NAMESPACE
+
+QtMsgHandler systemMsgOutput = 0;
+
+static QDeclarativeViewer *openFile(const QString &fileName);
+static void showViewer(QDeclarativeViewer *viewer);
+
+QString warnings;
+void exitApp(int i)
+{
+#ifdef Q_OS_WIN
+ // Debugging output is not visible by default on Windows -
+ // therefore show modal dialog with errors instead.
+ if (!warnings.isEmpty()) {
+ QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings);
+ }
+#endif
+ exit(i);
+}
+
+QWeakPointer<LoggerWidget> logger;
+static QAtomicInt recursiveLock(0);
+
+#if defined (Q_OS_SYMBIAN)
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
+void myMessageOutput(QtMsgType type, const char *msg)
+{
+ QString strMsg = QString::fromLatin1(msg);
+
+ if (!QCoreApplication::closingDown()) {
+ if (!logger.isNull()) {
+ if (recursiveLock.testAndSetOrdered(0, 1)) {
+ QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg));
+ recursiveLock = 0;
+ }
+ } else {
+ warnings += strMsg;
+ warnings += QLatin1Char('\n');
+ }
+ }
+#if defined (Q_OS_SYMBIAN)
+ static int fd = -1;
+ if (fd == -1)
+ fd = ::open("E:\\qml.log", O_WRONLY | O_CREAT);
+
+ ::write(fd, msg, strlen(msg));
+ ::write(fd, "\n", 1);
+ ::fsync(fd);
+ switch (type) {
+ case QtFatalMsg:
+ abort();
+ }
+#endif
+
+ if (systemMsgOutput) {
+ systemMsgOutput(type, msg);
+ } else { // Unix
+ fprintf(stderr, "%s\n", msg);
+ fflush(stderr);
+ }
+}
+
+static QDeclarativeViewer* globalViewer = 0;
+
+// The qml file that is shown if the user didn't specify a QML file
+QString initialFile = "qrc:/startup/startup.qml";
+
+void usage()
+{
+ qWarning("Usage: qmlviewer [options] <filename>");
+ qWarning(" ");
+ qWarning(" options:");
+ qWarning(" -v, -version ............................. display version");
+ qWarning(" -frameless ............................... run with no window frame");
+ qWarning(" -maximized................................ run maximized");
+ qWarning(" -fullscreen............................... run fullscreen");
+ qWarning(" -stayontop................................ keep viewer window on top");
+ qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content");
+ qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view (default)");
+ qWarning(" -qmlbrowser .............................. use a QML-based file browser");
+ qWarning(" -warnings [show|hide]..................... show warnings in a separate log window");
+ qWarning(" -recordfile <output> ..................... set video recording file");
+ qWarning(" - ImageMagick 'convert' for GIF)");
+ qWarning(" - png file for raw frames");
+ qWarning(" - 'ffmpeg' for other formats");
+ qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode");
+ qWarning(" -recordrate <fps> ........................ set recording frame rate");
+ qWarning(" -record arg .............................. add a recording process argument");
+ qWarning(" -autorecord [from-]<tomilliseconds> ...... set recording to start and stop");
+ qWarning(" -devicekeys .............................. use numeric keys (see F1)");
+ qWarning(" -dragthreshold <size> .................... set mouse drag threshold size");
+ qWarning(" -netcache <size> ......................... set disk cache to size bytes");
+ qWarning(" -translation <translationfile> ........... set the language to run in");
+ qWarning(" -I <directory> ........................... prepend to the module import search path,");
+ qWarning(" display path if <directory> is empty");
+ qWarning(" -P <directory> ........................... prepend to the plugin search path");
+#if defined(Q_WS_MAC)
+ qWarning(" -no-opengl ............................... don't use a QGLWidget for the viewport");
+#else
+ qWarning(" -opengl .................................. use a QGLWidget for the viewport");
+#endif
+ qWarning(" -script <path> ........................... set the script to use");
+ qWarning(" -scriptopts <options>|help ............... set the script options to use");
+
+ qWarning(" ");
+ qWarning(" Press F1 for interactive help");
+
+ exitApp(1);
+}
+
+void scriptOptsUsage()
+{
+ qWarning("Usage: qmlviewer -scriptopts <option>[,<option>...] ...");
+ qWarning(" options:");
+ qWarning(" record ................................... record a new script");
+ qWarning(" play ..................................... playback an existing script");
+ qWarning(" testimages ............................... record images or compare images on playback");
+ qWarning(" testerror ................................ test 'error' property of root item on playback");
+ qWarning(" testskip ................................ test 'skip' property of root item on playback");
+ qWarning(" snapshot ................................. file being recorded is static,");
+ qWarning(" only one frame will be recorded or tested");
+ qWarning(" exitoncomplete ........................... cleanly exit the viewer on script completion");
+ qWarning(" exitonfailure ............................ immediately exit the viewer on script failure");
+ qWarning(" saveonexit ............................... save recording on viewer exit");
+ qWarning(" ");
+ qWarning(" One of record, play or both must be specified.");
+
+ exitApp(1);
+}
+
+enum WarningsConfig { ShowWarnings, HideWarnings, DefaultWarnings };
+
+struct ViewerOptions
+{
+ ViewerOptions()
+ : frameless(false),
+ fps(0.0),
+ autorecord_from(0),
+ autorecord_to(0),
+ dither("none"),
+ runScript(false),
+ devkeys(false),
+ cache(0),
+ useGL(false),
+ fullScreen(false),
+ stayOnTop(false),
+ maximized(false),
+ useNativeFileBrowser(true),
+ experimentalGestures(false),
+ warningsConfig(DefaultWarnings),
+ sizeToView(true)
+ {
+#if defined(Q_OS_SYMBIAN)
+ maximized = true;
+ useNativeFileBrowser = false;
+#endif
+
+#if defined(Q_WS_MAC)
+ useGL = true;
+#endif
+ }
+
+ bool frameless;
+ double fps;
+ int autorecord_from;
+ int autorecord_to;
+ QString dither;
+ QString recordfile;
+ QStringList recordargs;
+ QStringList imports;
+ QStringList plugins;
+ QString script;
+ QString scriptopts;
+ bool runScript;
+ bool devkeys;
+ int cache;
+ QString translationFile;
+ bool useGL;
+ bool fullScreen;
+ bool stayOnTop;
+ bool maximized;
+ bool useNativeFileBrowser;
+ bool experimentalGestures;
+
+ WarningsConfig warningsConfig;
+ bool sizeToView;
+
+ QDeclarativeViewer::ScriptOptions scriptOptions;
+};
+
+static ViewerOptions opts;
+static QStringList fileNames;
+
+class Application : public QApplication
+{
+ Q_OBJECT
+public:
+ Application(int &argc, char **&argv)
+ : QApplication(argc, argv)
+ {}
+
+protected:
+ bool event(QEvent *ev)
+ {
+ if (ev->type() != QEvent::FileOpen)
+ return QApplication::event(ev);
+
+ QFileOpenEvent *fev = static_cast<QFileOpenEvent *>(ev);
+
+ globalViewer->open(fev->file());
+ if (!globalViewer->isVisible())
+ showViewer(globalViewer);
+
+ return true;
+ }
+
+private Q_SLOTS:
+ void showInitialViewer()
+ {
+ QApplication::processEvents();
+
+ QDeclarativeViewer *viewer = globalViewer;
+ if (!viewer)
+ return;
+ if (viewer->currentFile().isEmpty()) {
+ if(opts.useNativeFileBrowser)
+ viewer->open(initialFile);
+ else
+ viewer->openFile();
+ }
+ if (!viewer->isVisible())
+ showViewer(viewer);
+ }
+};
+
+static void parseScriptOptions()
+{
+ QStringList options =
+ opts.scriptopts.split(QLatin1Char(','), QString::SkipEmptyParts);
+
+ QDeclarativeViewer::ScriptOptions scriptOptions = 0;
+ for (int i = 0; i < options.count(); ++i) {
+ const QString &option = options.at(i);
+ if (option == QLatin1String("help")) {
+ scriptOptsUsage();
+ } else if (option == QLatin1String("play")) {
+ scriptOptions |= QDeclarativeViewer::Play;
+ } else if (option == QLatin1String("record")) {
+ scriptOptions |= QDeclarativeViewer::Record;
+ } else if (option == QLatin1String("testimages")) {
+ scriptOptions |= QDeclarativeViewer::TestImages;
+ } else if (option == QLatin1String("testerror")) {
+ scriptOptions |= QDeclarativeViewer::TestErrorProperty;
+ } else if (option == QLatin1String("testskip")) {
+ scriptOptions |= QDeclarativeViewer::TestSkipProperty;
+ } else if (option == QLatin1String("exitoncomplete")) {
+ scriptOptions |= QDeclarativeViewer::ExitOnComplete;
+ } else if (option == QLatin1String("exitonfailure")) {
+ scriptOptions |= QDeclarativeViewer::ExitOnFailure;
+ } else if (option == QLatin1String("saveonexit")) {
+ scriptOptions |= QDeclarativeViewer::SaveOnExit;
+ } else if (option == QLatin1String("snapshot")) {
+ scriptOptions |= QDeclarativeViewer::Snapshot;
+ } else {
+ scriptOptsUsage();
+ }
+ }
+
+ opts.scriptOptions = scriptOptions;
+}
+
+static void parseCommandLineOptions(const QStringList &arguments)
+{
+ for (int i = 1; i < arguments.count(); ++i) {
+ bool lastArg = (i == arguments.count() - 1);
+ QString arg = arguments.at(i);
+ if (arg == "-frameless") {
+ opts.frameless = true;
+ } else if (arg == "-maximized") {
+ opts.maximized = true;
+ } else if (arg == "-fullscreen") {
+ opts.fullScreen = true;
+ } else if (arg == "-stayontop") {
+ opts.stayOnTop = true;
+ } else if (arg == "-netcache") {
+ if (lastArg) usage();
+ opts.cache = arguments.at(++i).toInt();
+ } else if (arg == "-recordrate") {
+ if (lastArg) usage();
+ opts.fps = arguments.at(++i).toDouble();
+ } else if (arg == "-recordfile") {
+ if (lastArg) usage();
+ opts.recordfile = arguments.at(++i);
+ } else if (arg == "-record") {
+ if (lastArg) usage();
+ opts.recordargs << arguments.at(++i);
+ } else if (arg == "-recorddither") {
+ if (lastArg) usage();
+ opts.dither = arguments.at(++i);
+ } else if (arg == "-autorecord") {
+ if (lastArg) usage();
+ QString range = arguments.at(++i);
+ int dash = range.indexOf('-');
+ if (dash > 0)
+ opts.autorecord_from = range.left(dash).toInt();
+ opts.autorecord_to = range.mid(dash+1).toInt();
+ } else if (arg == "-devicekeys") {
+ opts.devkeys = true;
+ } else if (arg == "-dragthreshold") {
+ if (lastArg) usage();
+ qApp->setStartDragDistance(arguments.at(++i).toInt());
+ } else if (arg == QLatin1String("-v") || arg == QLatin1String("-version")) {
+ qWarning("Qt QML Viewer version %s", QT_VERSION_STR);
+ exitApp(0);
+ } else if (arg == "-translation") {
+ if (lastArg) usage();
+ opts.translationFile = arguments.at(++i);
+#if defined(Q_WS_MAC)
+ } else if (arg == "-no-opengl") {
+ opts.useGL = false;
+#else
+ } else if (arg == "-opengl") {
+ opts.useGL = true;
+#endif
+ } else if (arg == "-qmlbrowser") {
+ opts.useNativeFileBrowser = false;
+ } else if (arg == "-warnings") {
+ if (lastArg) usage();
+ QString warningsStr = arguments.at(++i);
+ if (warningsStr == QLatin1String("show")) {
+ opts.warningsConfig = ShowWarnings;
+ } else if (warningsStr == QLatin1String("hide")) {
+ opts.warningsConfig = HideWarnings;
+ } else {
+ usage();
+ }
+ } else if (arg == "-I" || arg == "-L") {
+ if (arg == "-L")
+ qWarning("-L option provided for compatibility only, use -I instead");
+ if (lastArg) {
+ QDeclarativeEngine tmpEngine;
+ QString paths = tmpEngine.importPathList().join(QLatin1String(":"));
+ qWarning("Current search path: %s", paths.toLocal8Bit().constData());
+ exitApp(0);
+ }
+ opts.imports << arguments.at(++i);
+ } else if (arg == "-P") {
+ if (lastArg) usage();
+ opts.plugins << arguments.at(++i);
+ } else if (arg == "-script") {
+ if (lastArg) usage();
+ opts.script = arguments.at(++i);
+ } else if (arg == "-scriptopts") {
+ if (lastArg) usage();
+ opts.scriptopts = arguments.at(++i);
+ } else if (arg == "-savescript") {
+ if (lastArg) usage();
+ opts.script = arguments.at(++i);
+ opts.runScript = false;
+ } else if (arg == "-playscript") {
+ if (lastArg) usage();
+ opts.script = arguments.at(++i);
+ opts.runScript = true;
+ } else if (arg == "-sizeviewtorootobject") {
+ opts.sizeToView = false;
+ } else if (arg == "-sizerootobjecttoview") {
+ opts.sizeToView = true;
+ } else if (arg == "-experimentalgestures") {
+ opts.experimentalGestures = true;
+ } else if (!arg.startsWith('-')) {
+ fileNames.append(arg);
+ } else if (true || arg == "-help") {
+ usage();
+ }
+ }
+
+ if (!opts.scriptopts.isEmpty()) {
+
+ parseScriptOptions();
+
+ if (opts.script.isEmpty())
+ usage();
+
+ if (!(opts.scriptOptions & QDeclarativeViewer::Record) && !(opts.scriptOptions & QDeclarativeViewer::Play))
+ scriptOptsUsage();
+ } else if (!opts.script.isEmpty()) {
+ usage();
+ }
+
+}
+
+static QDeclarativeViewer *createViewer()
+{
+ Qt::WFlags wflags = (opts.frameless ? Qt::FramelessWindowHint : Qt::Widget);
+ if (opts.stayOnTop)
+ wflags |= Qt::WindowStaysOnTopHint;
+
+ QDeclarativeViewer *viewer = new QDeclarativeViewer(0, wflags);
+ viewer->setAttribute(Qt::WA_DeleteOnClose, true);
+ viewer->setUseGL(opts.useGL);
+
+ if (!opts.scriptopts.isEmpty()) {
+ viewer->setScriptOptions(opts.scriptOptions);
+ viewer->setScript(opts.script);
+ }
+
+ logger = viewer->warningsWidget();
+ if (opts.warningsConfig == ShowWarnings) {
+ logger.data()->setDefaultVisibility(LoggerWidget::ShowWarnings);
+ logger.data()->show();
+ } else if (opts.warningsConfig == HideWarnings){
+ logger.data()->setDefaultVisibility(LoggerWidget::HideWarnings);
+ }
+
+ if (opts.experimentalGestures)
+ viewer->enableExperimentalGestures();
+
+ foreach (QString lib, opts.imports)
+ viewer->addLibraryPath(lib);
+
+ foreach (QString plugin, opts.plugins)
+ viewer->addPluginPath(plugin);
+
+ viewer->setNetworkCacheSize(opts.cache);
+ viewer->setRecordFile(opts.recordfile);
+ viewer->setSizeToView(opts.sizeToView);
+ if (opts.fps > 0)
+ viewer->setRecordRate(opts.fps);
+ if (opts.autorecord_to)
+ viewer->setAutoRecord(opts.autorecord_from, opts.autorecord_to);
+ if (opts.devkeys)
+ viewer->setDeviceKeys(true);
+ viewer->setRecordDither(opts.dither);
+ if (opts.recordargs.count())
+ viewer->setRecordArgs(opts.recordargs);
+
+ viewer->setUseNativeFileBrowser(opts.useNativeFileBrowser);
+
+ return viewer;
+}
+
+void showViewer(QDeclarativeViewer *viewer)
+{
+ if (opts.fullScreen)
+ viewer->showFullScreen();
+ else if (opts.maximized)
+ viewer->showMaximized();
+ else
+ viewer->show();
+ viewer->raise();
+}
+
+QDeclarativeViewer *openFile(const QString &fileName)
+{
+ QDeclarativeViewer *viewer = globalViewer;
+
+ viewer->open(fileName);
+ showViewer(viewer);
+
+ return viewer;
+}
+
+int main(int argc, char ** argv)
+{
+ systemMsgOutput = qInstallMsgHandler(myMessageOutput);
+
+#if defined (Q_WS_X11) || defined (Q_WS_MAC)
+ //### default to using raster graphics backend for now
+ bool gsSpecified = false;
+ for (int i = 0; i < argc; ++i) {
+ QString arg = argv[i];
+ if (arg == "-graphicssystem") {
+ gsSpecified = true;
+ break;
+ }
+ }
+
+ if (!gsSpecified)
+ QApplication::setGraphicsSystem("raster");
+#endif
+
+ QDeclarativeDebugHelper::enableDebugging();
+
+ Application app(argc, argv);
+ app.setApplicationName("QtQmlViewer");
+ app.setOrganizationName("Nokia");
+ app.setOrganizationDomain("nokia.com");
+
+ QDeclarativeViewer::registerTypes();
+ QDeclarativeTester::registerTypes();
+
+ parseCommandLineOptions(app.arguments());
+
+ QTranslator qmlTranslator;
+ if (!opts.translationFile.isEmpty()) {
+ if (qmlTranslator.load(opts.translationFile)) {
+ app.installTranslator(&qmlTranslator);
+ } else {
+ qWarning() << "Could not load the translation file" << opts.translationFile;
+ }
+ }
+
+ if (opts.fullScreen && opts.maximized)
+ qWarning() << "Both -fullscreen and -maximized specified. Using -fullscreen.";
+
+ if (fileNames.isEmpty()) {
+ QFile qmlapp(QLatin1String("qmlapp"));
+ if (qmlapp.exists() && qmlapp.open(QFile::ReadOnly)) {
+ QString content = QString::fromUtf8(qmlapp.readAll());
+ qmlapp.close();
+
+ int newline = content.indexOf(QLatin1Char('\n'));
+ if (newline >= 0)
+ fileNames += content.left(newline);
+ else
+ fileNames += content;
+ }
+ }
+
+ globalViewer = createViewer();
+
+ if (fileNames.isEmpty()) {
+ // show the initial viewer delayed.
+ // This prevents an initial viewer popping up while there
+ // are FileOpen events coming through the event queue
+ QTimer::singleShot(1, &app, SLOT(showInitialViewer()));
+ } else {
+ foreach (const QString &fileName, fileNames)
+ openFile(fileName);
+ }
+
+ QObject::connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
+
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tools/qmlviewer/proxysettings.cpp b/tools/qmlviewer/proxysettings.cpp
new file mode 100644
index 0000000000..c4dc087263
--- /dev/null
+++ b/tools/qmlviewer/proxysettings.cpp
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QIntValidator>
+#include <QSettings>
+
+#include "proxysettings.h"
+
+QT_BEGIN_NAMESPACE
+
+ProxySettings::ProxySettings (QWidget * parent)
+ : QDialog (parent), Ui::ProxySettings()
+{
+ setupUi (this);
+
+#if !defined Q_WS_MAEMO_5
+ // the onscreen keyboard can't cope with masks
+ proxyServerEdit->setInputMask ("000.000.000.000;_");
+#endif
+ 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/qmlviewer/proxysettings.h b/tools/qmlviewer/proxysettings.h
new file mode 100644
index 0000000000..5f5bb00e43
--- /dev/null
+++ b/tools/qmlviewer/proxysettings.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROXYSETTINGS_H
+#define PROXYSETTINGS_H
+
+#include <QDialog>
+#include <QNetworkProxy>
+#ifdef Q_WS_MAEMO_5
+#include "ui_proxysettings_maemo5.h"
+#else
+#include "ui_proxysettings.h"
+#endif
+
+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/qmlviewer/proxysettings.ui b/tools/qmlviewer/proxysettings.ui
new file mode 100644
index 0000000000..84e39fe03d
--- /dev/null
+++ b/tools/qmlviewer/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/qmlviewer/proxysettings_maemo5.ui b/tools/qmlviewer/proxysettings_maemo5.ui
new file mode 100644
index 0000000000..83f0c2a9de
--- /dev/null
+++ b/tools/qmlviewer/proxysettings_maemo5.ui
@@ -0,0 +1,177 @@
+<?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>449</width>
+ <height>164</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>HTTP Proxy</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>16</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QCheckBox" name="proxyCheckBox">
+ <property name="text">
+ <string>Use HTTP Proxy</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="2">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0" rowspan="2">
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="horizontalSpacing">
+ <number>16</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="serverAddressLabel">
+ <property name="text">
+ <string>Server</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="proxyServerEdit">
+ <property name="placeholderText">
+ <string>Name or IP</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Port</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="proxyPortEdit">
+ <property name="text">
+ <string>8080</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="usernameLabel">
+ <property name="text">
+ <string>Username</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QLineEdit" name="usernameEdit"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="passwordLabel">
+ <property name="text">
+ <string>Password</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="passwordEdit">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>proxyCheckBox</tabstop>
+ <tabstop>proxyServerEdit</tabstop>
+ <tabstop>proxyPortEdit</tabstop>
+ <tabstop>usernameEdit</tabstop>
+ <tabstop>passwordEdit</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ProxySettings</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>318</x>
+ <y>100</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>116</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ProxySettings</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>318</x>
+ <y>100</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>116</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/tools/qmlviewer/qdeclarativetester.cpp b/tools/qmlviewer/qdeclarativetester.cpp
new file mode 100644
index 0000000000..11f81fc169
--- /dev/null
+++ b/tools/qmlviewer/qdeclarativetester.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdeclarativetester.h>
+#include <QDebug>
+#include <QApplication>
+#include <qdeclarativeview.h>
+#include <QFile>
+#include <QDeclarativeComponent>
+#include <QDir>
+#include <QCryptographicHash>
+#include <private/qabstractanimation_p.h>
+#include <QGraphicsObject>
+#ifndef Q_OS_SYMBIAN
+#include <private/qdeclarativeitem_p.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled;
+
+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);
+
+ //Font antialiasing makes tests system-specific, so disable it
+ QFont noAA = QApplication::font();
+ noAA.setStyleStrategy(QFont::NoAntialias);
+ QApplication::setFont(noAA);
+
+ 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){
+ testSkip();
+ exit(hasFailed?-1:0);
+ }
+}
+
+void QDeclarativeTester::testSkip()
+{
+ if (options & QDeclarativeViewer::TestSkipProperty){
+ QString e = m_view->rootObject()->property("skip").toString();
+ if (!e.isEmpty()) {
+ if(hasFailed){
+ qWarning() << "Test failed, but skipping it: " << e;
+ }else{
+ qWarning() << "Test skipped: " << e;
+ }
+ hasFailed = 0;
+ }
+ }
+}
+
+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;
+ }
+ }
+
+
+ testSkip();
+ 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.7\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)
+{
+#ifndef Q_OS_SYMBIAN
+ QDeclarativeItemPrivate::setConsistentTime(msec);
+#endif
+ if (!testscript && msec > 16 && options & QDeclarativeViewer::Snapshot)
+ return;
+
+ QImage img(m_view->width(), m_view->height(), QImage::Format_RGB32);
+
+ if (options & QDeclarativeViewer::TestImages) {
+ img.fill(qRgb(255,255,255));
+
+#ifdef Q_WS_MAC
+ bool oldSmooth = qt_applefontsmoothing_enabled;
+ qt_applefontsmoothing_enabled = false;
+#endif
+ QPainter p(&img);
+#ifdef Q_WS_MAC
+ qt_applefontsmoothing_enabled = oldSmooth;
+#endif
+
+ m_view->render(&p);
+ }
+
+ bool snapshot = msec == 16 && (options & QDeclarativeViewer::Snapshot
+ || (testscript && testscript->count() == 2));
+
+ 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()-1) % 60) || snapshot) {
+ 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(" << m_script << "): 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(" << m_script << "): Mismatched frame hash at" << msec
+ << ". 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 (frame->msec() == 16 && goodImage.size() != img.size()){
+ //Also an image mismatch, but this warning is more informative. Only checked at start though.
+ qWarning() << "QDeclarativeTester(" << m_script << "): Size mismatch. This test must be run at " << goodImage.size();
+ imagefailure();
+ }
+ if (goodImage != img) {
+ QString reject(frame->image().toLocalFile() + ".reject.png");
+ qWarning() << "QDeclarativeTester(" << m_script << "): Image mismatch. Reject saved to:"
+ << reject;
+ img.save(reject);
+ bool doDiff = (goodImage.size() == img.size());
+ if (doDiff) {
+ QImage diffimg(m_view->width(), m_view->height(), QImage::Format_RGB32);
+ diffimg.fill(qRgb(255,255,255));
+ QPainter p(&diffimg);
+ int diffCount = 0;
+ for (int x = 0; x < img.width(); ++x) {
+ for (int y = 0; y < img.height(); ++y) {
+ if (goodImage.pixel(x,y) != img.pixel(x,y)) {
+ ++diffCount;
+ p.drawPoint(x,y);
+ }
+ }
+ }
+ QString diff(frame->image().toLocalFile() + ".diff.png");
+ diffimg.save(diff);
+ qWarning().nospace() << " Diff (" << diffCount << " pixels differed) saved to: " << diff;
+ }
+ 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) {
+ //if (msec == 16) //for a snapshot, leave it up long enough to see
+ // (void)::sleep(1);
+ complete();
+ }
+}
+
+void QDeclarativeTester::registerTypes()
+{
+ qmlRegisterType<QDeclarativeVisualTest>("Qt.VisualTest", 4,7, "VisualTest");
+ qmlRegisterType<QDeclarativeVisualTestFrame>("Qt.VisualTest", 4,7, "Frame");
+ qmlRegisterType<QDeclarativeVisualTestMouse>("Qt.VisualTest", 4,7, "Mouse");
+ qmlRegisterType<QDeclarativeVisualTestKey>("Qt.VisualTest", 4,7, "Key");
+}
+
+QT_END_NAMESPACE
diff --git a/tools/qmlviewer/qdeclarativetester.h b/tools/qmlviewer/qdeclarativetester.h
new file mode 100644
index 0000000000..c7173ab507
--- /dev/null
+++ b/tools/qmlviewer/qdeclarativetester.h
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETESTER_H
+#define QDECLARATIVETESTER_H
+
+#include <QEvent>
+#include <QMouseEvent>
+#include <QKeyEvent>
+#include <QImage>
+#include <QUrl>
+#include <qmlruntime.h>
+#include <qdeclarativelist.h>
+#include <qdeclarative.h>
+#include <QAbstractAnimation>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeVisualTest : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QDeclarativeListProperty<QObject> events READ events CONSTANT)
+ Q_CLASSINFO("DefaultProperty", "events")
+public:
+ QDeclarativeVisualTest() {}
+
+ QDeclarativeListProperty<QObject> events() { return QDeclarativeListProperty<QObject>(this, 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();
+ void testSkip();
+
+ 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 // QDECLARATIVETESTER_H
diff --git a/tools/qmlviewer/qml.icns b/tools/qmlviewer/qml.icns
new file mode 100644
index 0000000000..c76051626a
--- /dev/null
+++ b/tools/qmlviewer/qml.icns
Binary files differ
diff --git a/tools/qmlviewer/qml.pri b/tools/qmlviewer/qml.pri
new file mode 100644
index 0000000000..cfc74af89d
--- /dev/null
+++ b/tools/qmlviewer/qml.pri
@@ -0,0 +1,50 @@
+QT += declarative script network sql
+contains(QT_CONFIG, opengl) {
+ QT += opengl
+ DEFINES += GL_SUPPORTED
+}
+
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/qmlruntime.h \
+ $$PWD/proxysettings.h \
+ $$PWD/qdeclarativetester.h \
+ $$PWD/deviceorientation.h \
+ $$PWD/loggerwidget.h
+SOURCES += $$PWD/qmlruntime.cpp \
+ $$PWD/proxysettings.cpp \
+ $$PWD/qdeclarativetester.cpp \
+ $$PWD/loggerwidget.cpp
+
+RESOURCES = $$PWD/browser/browser.qrc \
+ $$PWD/startup/startup.qrc
+
+symbian {
+ contains(QT_CONFIG, s60) {
+ LIBS += -lavkon -lcone
+ }
+ !contains(S60_VERSION, 3.1):!contains(S60_VERSION, 3.2) {
+ LIBS += -lsensrvclient -lsensrvutil
+ SOURCES += $$PWD/deviceorientation_symbian.cpp
+ } else {
+ SOURCES += $$PWD/deviceorientation.cpp
+ }
+ FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
+} else:maemo5 {
+ QT += dbus
+ HEADERS += $$PWD/texteditautoresizer_maemo5.h
+ SOURCES += $$PWD/deviceorientation_maemo5.cpp
+ FORMS = $$PWD/recopts_maemo5.ui \
+ $$PWD/proxysettings_maemo5.ui
+} else:linux-g++-maemo {
+ QT += dbus
+ SOURCES += $$PWD/deviceorientation_harmattan.cpp
+ FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
+} else {
+ SOURCES += $$PWD/deviceorientation.cpp
+ FORMS = $$PWD/recopts.ui \
+ $$PWD/proxysettings.ui
+}
+
diff --git a/tools/qmlviewer/qmlruntime.cpp b/tools/qmlviewer/qmlruntime.cpp
new file mode 100644
index 0000000000..36915d12bf
--- /dev/null
+++ b/tools/qmlviewer/qmlruntime.cpp
@@ -0,0 +1,1552 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qdeclarativeview.h>
+
+#ifdef hz
+#undef hz
+#endif
+#ifdef Q_WS_MAEMO_5
+# include <QMaemo5ValueButton>
+# include <QMaemo5ListPickSelector>
+# include <QWidgetAction>
+# include <QStringListModel>
+# include "ui_recopts_maemo5.h"
+#else
+# include "ui_recopts.h"
+#endif
+
+#include "qmlruntime.h"
+#include <qdeclarativecontext.h>
+#include <qdeclarativeengine.h>
+#include <qdeclarativenetworkaccessmanagerfactory.h>
+#include "qdeclarative.h"
+#include <QAbstractAnimation>
+#include <private/qabstractanimation_p.h>
+
+#include <QSettings>
+#include <QXmlStreamReader>
+#include <QBuffer>
+#include <QNetworkReply>
+#include <QNetworkCookieJar>
+#include <QNetworkDiskCache>
+#include <QNetworkAccessManager>
+#include <QSignalMapper>
+#include <QDeclarativeComponent>
+#include <QWidget>
+#include <QApplication>
+#include <QTranslator>
+#include <QDir>
+#include <QTextBrowser>
+#include <QFile>
+#include <QFileInfo>
+#include <QVBoxLayout>
+#include <QProgressDialog>
+#include <QProcess>
+#include <QMenuBar>
+#include <QMenu>
+#include <QAction>
+#include <QFileDialog>
+#include <QInputDialog>
+#include <QTimer>
+#include <QGraphicsObject>
+#include <QNetworkProxyFactory>
+#include <QKeyEvent>
+#include <QMutex>
+#include <QMutexLocker>
+#include "proxysettings.h"
+#include "deviceorientation.h"
+
+#ifdef GL_SUPPORTED
+#include <QGLWidget>
+#endif
+
+#if defined(Q_WS_S60)
+#include <aknappui.h> // For locking app orientation
+#endif
+
+#include <qdeclarativetester.h>
+
+QT_BEGIN_NAMESPACE
+
+class DragAndDropView : public QDeclarativeView
+{
+ Q_OBJECT
+public:
+ DragAndDropView(QDeclarativeViewer *parent = 0)
+ : QDeclarativeView(parent)
+ {
+ setAcceptDrops(true);
+ }
+
+ void dragEnterEvent(QDragEnterEvent *event)
+ {
+ const QMimeData *mimeData = event->mimeData();
+ if (mimeData->hasUrls())
+ event->acceptProposedAction();
+ }
+
+ void dragMoveEvent(QDragMoveEvent *event)
+ {
+ event->acceptProposedAction();
+ }
+
+ void dragLeaveEvent(QDragLeaveEvent *event)
+ {
+ event->accept();
+ }
+
+ void dropEvent(QDropEvent *event)
+ {
+ const QMimeData *mimeData = event->mimeData();
+ if (!mimeData->hasUrls())
+ return;
+ const QList<QUrl> urlList = mimeData->urls();
+ foreach (const QUrl &url, urlList) {
+ if (url.scheme() == QLatin1String("file")) {
+ static_cast<QDeclarativeViewer *>(parent())->open(url.toLocalFile());
+ event->accept();
+ return;
+ }
+ }
+ }
+};
+
+class Runtime : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool isActiveWindow READ isActiveWindow NOTIFY isActiveWindowChanged)
+ Q_PROPERTY(DeviceOrientation::Orientation orientation READ orientation NOTIFY orientationChanged)
+
+public:
+ static Runtime* instance()
+ {
+ static Runtime *instance = 0;
+ if (!instance)
+ instance = new Runtime;
+ return instance;
+ }
+
+ bool isActiveWindow() const { return activeWindow; }
+ void setActiveWindow(bool active)
+ {
+ if (active == activeWindow)
+ return;
+ activeWindow = active;
+ emit isActiveWindowChanged();
+ }
+
+ DeviceOrientation::Orientation orientation() const { return DeviceOrientation::instance()->orientation(); }
+
+Q_SIGNALS:
+ void isActiveWindowChanged();
+ void orientationChanged();
+
+private:
+ Runtime(QObject *parent=0) : QObject(parent), activeWindow(false)
+ {
+ connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()),
+ this, SIGNAL(orientationChanged()));
+ }
+
+ bool activeWindow;
+};
+
+
+
+#if defined(Q_WS_MAEMO_5)
+
+class Maemo5PickerAction : public QWidgetAction {
+ Q_OBJECT
+public:
+ Maemo5PickerAction(const QString &text, QActionGroup *actions, QObject *parent)
+ : QWidgetAction(parent), m_text(text), m_actions(actions)
+ { }
+
+ QWidget *createWidget(QWidget *parent)
+ {
+ QMaemo5ValueButton *button = new QMaemo5ValueButton(m_text, parent);
+ button->setValueLayout(QMaemo5ValueButton::ValueUnderTextCentered);
+ QMaemo5ListPickSelector *pick = new QMaemo5ListPickSelector(button);
+ button->setPickSelector(pick);
+ if (m_actions) {
+ QStringList sl;
+ int curIdx = -1, idx = 0;
+ foreach (QAction *a, m_actions->actions()) {
+ sl << a->text();
+ if (a->isChecked())
+ curIdx = idx;
+ idx++;
+ }
+ pick->setModel(new QStringListModel(sl));
+ pick->setCurrentIndex(curIdx);
+ } else {
+ button->setEnabled(false);
+ }
+ connect(pick, SIGNAL(selected(QString)), this, SLOT(emitTriggered()));
+ return button;
+ }
+
+private slots:
+ void emitTriggered()
+ {
+ QMaemo5ListPickSelector *pick = qobject_cast<QMaemo5ListPickSelector *>(sender());
+ if (!pick)
+ return;
+ int idx = pick->currentIndex();
+
+ if (m_actions && idx >= 0 && idx < m_actions->actions().count())
+ m_actions->actions().at(idx)->trigger();
+ }
+
+private:
+ QString m_text;
+ QPointer<QActionGroup> m_actions;
+};
+
+#endif // Q_WS_MAEMO_5
+
+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);
+#ifndef Q_WS_MAEMO_5
+ hz->setValidator(new QDoubleValidator(hz));
+#endif
+ 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;
+ }
+
+ void setOriginalSize(const QSize &s)
+ {
+ QString str = tr("Original (%1x%2)").arg(s.width()).arg(s.height());
+
+#ifdef Q_WS_MAEMO_5
+ sizeCombo->setItemText(0, str);
+#else
+ sizeOriginal->setText(str);
+ if (sizeWidth->value()<=1) {
+ sizeWidth->setValue(s.width());
+ sizeHeight->setValue(s.height());
+ }
+#endif
+ }
+
+ void showffmpegOptions(bool b)
+ {
+#ifdef Q_WS_MAEMO_5
+ profileLabel->setVisible(b);
+ profile->setVisible(b);
+ ffmpegHelp->setVisible(b);
+ args->setVisible(b);
+#else
+ ffmpegOptions->setVisible(b);
+#endif
+ }
+
+ void showRateOptions(bool b)
+ {
+#ifdef Q_WS_MAEMO_5
+ rateLabel->setVisible(b);
+ rateCombo->setVisible(b);
+#else
+ rateOptions->setVisible(b);
+#endif
+ }
+
+ void setVideoRate(int rate)
+ {
+#ifdef Q_WS_MAEMO_5
+ int idx;
+ if (rate >= 60)
+ idx = 0;
+ else if (rate >= 50)
+ idx = 2;
+ else if (rate >= 25)
+ idx = 3;
+ else if (rate >= 24)
+ idx = 4;
+ else if (rate >= 20)
+ idx = 5;
+ else if (rate >= 15)
+ idx = 6;
+ else
+ idx = 7;
+ rateCombo->setCurrentIndex(idx);
+#else
+ if (rate == 24)
+ hz24->setChecked(true);
+ else if (rate == 25)
+ hz25->setChecked(true);
+ else if (rate == 50)
+ hz50->setChecked(true);
+ else if (rate == 60)
+ hz60->setChecked(true);
+ else {
+ hzCustom->setChecked(true);
+ hz->setText(QString::number(rate));
+ }
+#endif
+ }
+
+ int videoRate() const
+ {
+#ifdef Q_WS_MAEMO_5
+ switch (rateCombo->currentIndex()) {
+ case 0: return 60;
+ case 1: return 50;
+ case 2: return 25;
+ case 3: return 24;
+ case 4: return 20;
+ case 5: return 15;
+ case 7: return 10;
+ default: return 60;
+ }
+#else
+ if (hz24->isChecked())
+ return 24;
+ else if (hz25->isChecked())
+ return 25;
+ else if (hz50->isChecked())
+ return 50;
+ else if (hz60->isChecked())
+ return 60;
+ else {
+ return hz->text().toInt();
+ }
+#endif
+ }
+
+ QSize videoSize() const
+ {
+#ifdef Q_WS_MAEMO_5
+ switch (sizeCombo->currentIndex()) {
+ case 0: return QSize();
+ case 1: return QSize(640,480);
+ case 2: return QSize(320,240);
+ case 3: return QSize(1280,720);
+ default: return QSize();
+ }
+#else
+ if (sizeOriginal->isChecked())
+ return QSize();
+ else if (size720p->isChecked())
+ return QSize(1280,720);
+ else if (sizeVGA->isChecked())
+ return QSize(640,480);
+ else if (sizeQVGA->isChecked())
+ return QSize(320,240);
+ else
+ return QSize(sizeWidth->value(), sizeHeight->value());
+#endif
+ }
+
+
+
+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;
+ settings.setValue("Cookies",data);
+ }
+
+ void load()
+ {
+ QMutexLocker lock(&mutex);
+ QSettings settings;
+ QByteArray data = settings.value("Cookies").toByteArray();
+ setAllCookies(QNetworkCookie::parseCookies(data));
+ }
+
+ mutable QMutex mutex;
+};
+
+class SystemProxyFactory : public QNetworkProxyFactory
+{
+public:
+ SystemProxyFactory() : proxyDirty(true), httpProxyInUse(false) {
+ }
+
+ virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query)
+ {
+ if (proxyDirty)
+ setupProxy();
+ QString protocolTag = query.protocolTag();
+ if (httpProxyInUse && (protocolTag == "http" || protocolTag == "https")) {
+ QList<QNetworkProxy> ret;
+ ret << httpProxy;
+ return ret;
+ }
+#ifdef Q_OS_WIN
+ // systemProxyForQuery can take insanely long on Windows (QTBUG-10106)
+ return QNetworkProxyFactory::proxyForQuery(query);
+#else
+ return QNetworkProxyFactory::systemProxyForQuery(query);
+#endif
+ }
+
+ void setupProxy() {
+ // Don't bother locking because we know that the proxy only
+ // changes in response to the settings dialog and that
+ // the view will be reloaded.
+ proxyDirty = false;
+ httpProxyInUse = ProxySettings::httpProxyInUse();
+ if (httpProxyInUse)
+ httpProxy = ProxySettings::httpProxy();
+ }
+
+ void proxyChanged() {
+ proxyDirty = true;
+ }
+
+private:
+ volatile bool proxyDirty;
+ bool httpProxyInUse;
+ QNetworkProxy httpProxy;
+};
+
+class NetworkAccessManagerFactory : public QObject, public QDeclarativeNetworkAccessManagerFactory
+{
+ Q_OBJECT
+public:
+ NetworkAccessManagerFactory() : cacheSize(0) {}
+ ~NetworkAccessManagerFactory() {}
+
+ QNetworkAccessManager *create(QObject *parent);
+
+ void setCacheSize(int size) {
+ if (size != cacheSize) {
+ cacheSize = size;
+ }
+ }
+
+ void proxyChanged() {
+ foreach (QNetworkAccessManager *nam, namList) {
+ static_cast<SystemProxyFactory*>(nam->proxyFactory())->proxyChanged();
+ }
+ }
+
+ static PersistentCookieJar *cookieJar;
+
+private slots:
+ void managerDestroyed(QObject *obj) {
+ namList.removeOne(static_cast<QNetworkAccessManager*>(obj));
+ }
+
+private:
+ QMutex mutex;
+ int cacheSize;
+ QList<QNetworkAccessManager*> namList;
+};
+
+PersistentCookieJar *NetworkAccessManagerFactory::cookieJar = 0;
+
+static void cleanup_cookieJar()
+{
+ delete NetworkAccessManagerFactory::cookieJar;
+ NetworkAccessManagerFactory::cookieJar = 0;
+}
+
+QNetworkAccessManager *NetworkAccessManagerFactory::create(QObject *parent)
+{
+ QMutexLocker lock(&mutex);
+ QNetworkAccessManager *manager = new QNetworkAccessManager(parent);
+ if (!cookieJar) {
+ qAddPostRoutine(cleanup_cookieJar);
+ cookieJar = new PersistentCookieJar(0);
+ }
+ manager->setCookieJar(cookieJar);
+ cookieJar->setParent(0);
+ manager->setProxyFactory(new SystemProxyFactory);
+ if (cacheSize > 0) {
+ QNetworkDiskCache *cache = new QNetworkDiskCache;
+ cache->setCacheDirectory(QDir::tempPath()+QLatin1String("/qml-viewer-network-cache"));
+ cache->setMaximumCacheSize(cacheSize);
+ manager->setCache(cache);
+ } else {
+ manager->setCache(0);
+ }
+ connect(manager, SIGNAL(destroyed(QObject*)), this, SLOT(managerDestroyed(QObject*)));
+ namList.append(manager);
+ return manager;
+}
+
+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)
+ : QMainWindow(parent, flags)
+ , loggerWindow(new LoggerWidget(this))
+ , frame_stream(0)
+ , rotateAction(0)
+ , orientation(0)
+ , showWarningsWindow(0)
+ , m_scriptOptions(0)
+ , tester(0)
+ , useQmlFileBrowser(true)
+ , translator(0)
+{
+ QDeclarativeViewer::registerTypes();
+ setWindowTitle(tr("Qt QML Viewer"));
+#ifdef Q_WS_MAEMO_5
+ setAttribute(Qt::WA_Maemo5StackedWindow);
+// setPalette(QApplication::palette("QLabel"));
+#endif
+
+ devicemode = false;
+ 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->showffmpegOptions(false);
+ if (!ffmpegAvailable && !convertAvailable)
+ recdlg->showRateOptions(false);
+ 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 DragAndDropView(this);
+
+ canvas->setAttribute(Qt::WA_OpaquePaintEvent);
+ canvas->setAttribute(Qt::WA_NoSystemBackground);
+
+ 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()), this, SLOT(close()));
+
+ QObject::connect(warningsWidget(), SIGNAL(opened()), this, SLOT(warningsWidgetOpened()));
+ QObject::connect(warningsWidget(), SIGNAL(closed()), this, SLOT(warningsWidgetClosed()));
+
+ if (!(flags & Qt::FramelessWindowHint)) {
+ createMenu();
+ changeOrientation(orientation->actions().value(0));
+ } else {
+ setMenuBar(0);
+ }
+
+ setCentralWidget(canvas);
+
+ namFactory = new NetworkAccessManagerFactory;
+ canvas->engine()->setNetworkAccessManagerFactory(namFactory);
+
+ connect(&autoStartTimer, SIGNAL(timeout()), this, SLOT(autoStartRecording()));
+ connect(&autoStopTimer, SIGNAL(timeout()), this, SLOT(autoStopRecording()));
+ connect(&recordTimer, SIGNAL(timeout()), this, SLOT(recordFrame()));
+ connect(DeviceOrientation::instance(), SIGNAL(orientationChanged()),
+ this, SLOT(orientationChanged()), Qt::QueuedConnection);
+ autoStartTimer.setSingleShot(true);
+ autoStopTimer.setSingleShot(true);
+ recordTimer.setSingleShot(false);
+
+ QObject::connect(qApp, SIGNAL(aboutToQuit()), this, SLOT(appAboutToQuit()));
+}
+
+QDeclarativeViewer::~QDeclarativeViewer()
+{
+ delete loggerWindow;
+ canvas->engine()->setNetworkAccessManagerFactory(0);
+ delete namFactory;
+}
+
+void QDeclarativeViewer::enableExperimentalGestures()
+{
+#ifndef QT_NO_GESTURES
+ canvas->viewport()->grabGesture(Qt::TapGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
+ canvas->viewport()->grabGesture(Qt::TapAndHoldGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
+ canvas->viewport()->grabGesture(Qt::PanGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
+ canvas->viewport()->grabGesture(Qt::PinchGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
+ canvas->viewport()->grabGesture(Qt::SwipeGesture,Qt::DontStartGestureOnChildren|Qt::ReceivePartialGestures|Qt::IgnoredGesturesPropagateToParent);
+ canvas->viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
+#endif
+}
+
+QDeclarativeView *QDeclarativeViewer::view() const
+{
+ return canvas;
+}
+
+LoggerWidget *QDeclarativeViewer::warningsWidget() const
+{
+ return loggerWindow;
+}
+
+void QDeclarativeViewer::createMenu()
+{
+ QAction *openAction = new QAction(tr("&Open..."), this);
+ openAction->setShortcuts(QKeySequence::Open);
+ connect(openAction, SIGNAL(triggered()), this, SLOT(openFile()));
+
+ QAction *openUrlAction = new QAction(tr("Open &URL..."), this);
+ connect(openUrlAction, SIGNAL(triggered()), this, SLOT(openUrl()));
+
+ QAction *reloadAction = new QAction(tr("&Reload"), this);
+ reloadAction->setShortcuts(QKeySequence::Refresh);
+ connect(reloadAction, SIGNAL(triggered()), this, SLOT(reload()));
+
+ QAction *snapshotAction = new QAction(tr("&Take Snapshot"), this);
+ snapshotAction->setShortcut(QKeySequence("F3"));
+ connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot()));
+
+ recordAction = new QAction(tr("Start Recording &Video"), this);
+ recordAction->setShortcut(QKeySequence("F9"));
+ connect(recordAction, SIGNAL(triggered()), this, SLOT(toggleRecordingWithSelection()));
+
+ QAction *recordOptions = new QAction(tr("Video &Options..."), this);
+ connect(recordOptions, SIGNAL(triggered()), this, SLOT(chooseRecordingOptions()));
+
+ QAction *slowAction = new QAction(tr("&Slow Down Animations"), this);
+ slowAction->setShortcut(QKeySequence("Ctrl+."));
+ slowAction->setCheckable(true);
+ connect(slowAction, SIGNAL(triggered(bool)), this, SLOT(setSlowMode(bool)));
+
+ showWarningsWindow = new QAction(tr("Show Warnings"), this);
+#if !defined(Q_OS_SYMBIAN)
+ showWarningsWindow->setCheckable((true));
+ showWarningsWindow->setChecked(loggerWindow->isVisible());
+#endif
+ connect(showWarningsWindow, SIGNAL(triggered(bool)), this, SLOT(showWarnings(bool)));
+
+ QAction *proxyAction = new QAction(tr("HTTP &Proxy..."), this);
+ connect(proxyAction, SIGNAL(triggered()), this, SLOT(showProxySettings()));
+
+ QAction *fullscreenAction = new QAction(tr("Full Screen"), this);
+ fullscreenAction->setCheckable(true);
+ connect(fullscreenAction, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
+
+ rotateAction = new QAction(tr("Rotate orientation"), this);
+ rotateAction->setShortcut(QKeySequence("Ctrl+T"));
+ connect(rotateAction, SIGNAL(triggered()), this, SLOT(rotateOrientation()));
+
+ orientation = new QActionGroup(this);
+ orientation->setExclusive(true);
+ connect(orientation, SIGNAL(triggered(QAction*)), this, SLOT(changeOrientation(QAction*)));
+
+#if defined(Q_OS_SYMBIAN)
+ QAction *autoOrientationAction = new QAction(tr("Auto-orientation"), this);
+ autoOrientationAction->setCheckable(true);
+#endif
+ QAction *portraitAction = new QAction(tr("Portrait"), this);
+ portraitAction->setCheckable(true);
+ QAction *landscapeAction = new QAction(tr("Landscape"), this);
+ landscapeAction->setCheckable(true);
+#if !defined(Q_OS_SYMBIAN)
+ QAction *portraitInvAction = new QAction(tr("Portrait (inverted)"), this);
+ portraitInvAction->setCheckable(true);
+ QAction *landscapeInvAction = new QAction(tr("Landscape (inverted)"), this);
+ landscapeInvAction->setCheckable(true);
+#endif
+
+ QAction *aboutAction = new QAction(tr("&About Qt..."), this);
+ aboutAction->setMenuRole(QAction::AboutQtRole);
+ connect(aboutAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
+
+#if !defined(Q_OS_SYMBIAN)
+ QAction *closeAction = new QAction(tr("&Close"), this);
+ closeAction->setShortcuts(QKeySequence::Close);
+ connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
+#endif
+
+ QAction *quitAction = new QAction(tr("&Quit"), this);
+ quitAction->setMenuRole(QAction::QuitRole);
+ quitAction->setShortcuts(QKeySequence::Quit);
+ connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
+
+ QMenuBar *menu = menuBar();
+ if (!menu)
+ return;
+
+#if defined(Q_WS_MAEMO_5)
+ menu->addAction(openAction);
+ menu->addAction(openUrlAction);
+ menu->addAction(reloadAction);
+
+ menu->addAction(snapshotAction);
+ menu->addAction(recordAction);
+
+ menu->addAction(recordOptions);
+ menu->addAction(proxyAction);
+
+ menu->addAction(slowAction);
+ menu->addAction(showWarningsWindow);
+
+ orientation->addAction(landscapeAction);
+ orientation->addAction(portraitAction);
+ menu->addAction(new Maemo5PickerAction(tr("Set orientation"), orientation, this));
+ menu->addAction(fullscreenAction);
+ return;
+#endif // Q_WS_MAEMO_5
+
+ QMenu *fileMenu = menu->addMenu(tr("&File"));
+ fileMenu->addAction(openAction);
+ fileMenu->addAction(openUrlAction);
+ fileMenu->addAction(reloadAction);
+#if !defined(Q_OS_SYMBIAN)
+ fileMenu->addSeparator();
+ fileMenu->addAction(closeAction);
+ fileMenu->addAction(quitAction);
+
+ QMenu *recordMenu = menu->addMenu(tr("&Recording"));
+ recordMenu->addAction(snapshotAction);
+ recordMenu->addAction(recordAction);
+#endif // ! Q_OS_SYMBIAN
+
+ QMenu *debugMenu = menu->addMenu(tr("&Debugging"));
+ debugMenu->addAction(slowAction);
+ debugMenu->addAction(showWarningsWindow);
+
+ QMenu *settingsMenu = menu->addMenu(tr("&Settings"));
+ settingsMenu->addAction(proxyAction);
+#if defined(Q_OS_SYMBIAN)
+ settingsMenu->addAction(fullscreenAction);
+#else
+ settingsMenu->addAction(recordOptions);
+ settingsMenu->addMenu(loggerWindow->preferencesMenu());
+#endif // !Q_OS_SYMBIAN
+ settingsMenu->addAction(rotateAction);
+
+ QMenu *propertiesMenu = settingsMenu->addMenu(tr("Properties"));
+
+#if defined(Q_OS_SYMBIAN)
+ orientation->addAction(autoOrientationAction);
+#endif
+ orientation->addAction(portraitAction);
+ orientation->addAction(landscapeAction);
+#if !defined(Q_OS_SYMBIAN)
+ orientation->addAction(portraitInvAction);
+ orientation->addAction(landscapeInvAction);
+#endif
+ propertiesMenu->addActions(orientation->actions());
+
+ QMenu *helpMenu = menu->addMenu(tr("&Help"));
+ helpMenu->addAction(aboutAction);
+}
+
+void QDeclarativeViewer::showProxySettings()
+{
+ ProxySettings settingsDlg (this);
+
+ connect (&settingsDlg, SIGNAL (accepted()), this, SLOT (proxySettingsChanged ()));
+
+ settingsDlg.exec();
+}
+
+void QDeclarativeViewer::proxySettingsChanged()
+{
+ namFactory->proxyChanged();
+ reload ();
+}
+
+void QDeclarativeViewer::rotateOrientation()
+{
+#if defined(Q_WS_S60)
+ CAknAppUi *appUi = static_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi());
+ if (appUi) {
+ CAknAppUi::TAppUiOrientation oldOrientation = appUi->Orientation();
+ QString newOrientation;
+ if (oldOrientation == CAknAppUi::EAppUiOrientationPortrait) {
+ newOrientation = QLatin1String("Landscape");
+ } else {
+ newOrientation = QLatin1String("Portrait");
+ }
+ foreach (QAction *action, orientation->actions()) {
+ if (action->text() == newOrientation) {
+ changeOrientation(action);
+ }
+ }
+ }
+#else
+ QAction *current = orientation->checkedAction();
+ QList<QAction *> actions = orientation->actions();
+ int index = actions.indexOf(current);
+ if (index < 0)
+ return;
+
+ QAction *newOrientation = actions[(index + 1) % actions.count()];
+ changeOrientation(newOrientation);
+#endif
+}
+
+void QDeclarativeViewer::toggleFullScreen()
+{
+ if (isFullScreen())
+ showMaximized();
+ else
+ showFullScreen();
+}
+
+void QDeclarativeViewer::showWarnings(bool show)
+{
+#if defined(Q_OS_SYMBIAN)
+ loggerWindow->showMaximized();
+#else
+ loggerWindow->setVisible(show);
+#endif
+}
+
+void QDeclarativeViewer::warningsWidgetOpened()
+{
+ showWarningsWindow->setChecked(true);
+}
+
+void QDeclarativeViewer::warningsWidgetClosed()
+{
+ showWarningsWindow->setChecked(false);
+}
+
+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->setOriginalSize(canvas->size());
+
+ // Rate
+ recdlg->setVideoRate(record_rate);
+
+
+ // Profile
+ recdlg->setArguments(record_args.join(" "));
+ if (recdlg->exec()) {
+ // File
+ record_file = recdlg->file->text();
+ // Size
+ record_outsize = recdlg->videoSize();
+ // Rate
+ record_rate = recdlg->videoRate();
+ // Profile
+ record_args = recdlg->arguments().split(" ",QString::SkipEmptyParts);
+ }
+}
+
+void QDeclarativeViewer::toggleRecordingWithSelection()
+{
+ if (!recordTimer.isActive()) {
+ 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.isActive();
+ 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::addPluginPath(const QString& plugin)
+{
+ canvas->engine()->addPluginPath(plugin);
+}
+
+void QDeclarativeViewer::reload()
+{
+ launch(currentFileOrUrl);
+}
+
+void QDeclarativeViewer::openFile()
+{
+ QString cur = canvas->source().toLocalFile();
+ if (useQmlFileBrowser) {
+ open("qrc:/browser/Browser.qml");
+ } else {
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open QML file"), cur, tr("QML Files (*.qml)"));
+ if (!fileName.isEmpty()) {
+ QFileInfo fi(fileName);
+ open(fi.absoluteFilePath());
+ }
+ }
+}
+
+void QDeclarativeViewer::openUrl()
+{
+ QString cur = canvas->source().toLocalFile();
+ QString url= QInputDialog::getText(this, tr("Open QML file"), tr("URL of main QML file:"), QLineEdit::Normal, cur);
+ if (!url.isEmpty())
+ open(url);
+}
+
+void QDeclarativeViewer::statusChanged()
+{
+ if (canvas->status() == QDeclarativeView::Error && tester)
+ tester->executefailure();
+
+ if (canvas->status() == QDeclarativeView::Ready) {
+ initialSize = canvas->initialSize();
+ updateSizeHints(true);
+ }
+}
+
+void QDeclarativeViewer::launch(const QString& file_or_url)
+{
+ QMetaObject::invokeMethod(this, "open", Qt::QueuedConnection, Q_ARG(QString, file_or_url));
+}
+
+void QDeclarativeViewer::loadTranslationFile(const QString& directory)
+{
+ if (!translator) {
+ translator = new QTranslator(this);
+ QApplication::installTranslator(translator);
+ }
+
+ translator->load(QLatin1String("qml_" )+QLocale::system().name(), directory + QLatin1String("/i18n"));
+}
+
+void QDeclarativeViewer::loadDummyDataFiles(const QString& directory)
+{
+ QDir dir(directory+"/dummydata", "*.qml");
+ QStringList list = dir.entryList();
+ for (int i = 0; i < list.size(); ++i) {
+ QString qml = list.at(i);
+ QDeclarativeComponent comp(canvas->engine(), dir.filePath(qml));
+ 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);
+ canvas->rootContext()->setContextProperty(qml, dummyData);
+ dummyData->setParent(this);
+ }
+ }
+}
+
+bool QDeclarativeViewer::open(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 QML 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
+
+ ctxt->setContextProperty("runtime", Runtime::instance());
+
+ QString fileName = url.toLocalFile();
+ if (!fileName.isEmpty()) {
+ fi.setFile(fileName);
+ if (fi.exists()) {
+ if (fi.suffix().toLower() != QLatin1String("qml")) {
+ qWarning() << "qml cannot open non-QML file" << fileName;
+ return false;
+ }
+
+ QFileInfo fi(fileName);
+ loadTranslationFile(fi.path());
+ loadDummyDataFiles(fi.path());
+ } else {
+ qWarning() << "qml cannot find file:" << fileName;
+ return false;
+ }
+ }
+
+ QTime t;
+ t.start();
+
+ canvas->setSource(url);
+
+ return true;
+}
+
+void QDeclarativeViewer::setAutoRecord(int from, int to)
+{
+ if (from==0) from=1; // ensure resized
+ record_autotime = to-from;
+ autoStartTimer.setInterval(from);
+ autoStartTimer.start();
+}
+
+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)
+{
+ updateSizeHints();
+}
+
+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"
+ << "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_F9 || (event->key() == Qt::Key_9 && devicemode)) {
+ toggleRecording();
+ } else if (event->key() == Qt::Key_F10) {
+ rotateOrientation();
+ }
+
+ QWidget::keyPressEvent(event);
+}
+
+bool QDeclarativeViewer::event(QEvent *event)
+{
+ if (event->type() == QEvent::WindowActivate) {
+ Runtime::instance()->setActiveWindow(true);
+ DeviceOrientation::instance()->resumeListening();
+ } else if (event->type() == QEvent::WindowDeactivate) {
+ Runtime::instance()->setActiveWindow(false);
+ DeviceOrientation::instance()->pauseListening();
+ }
+ return QWidget::event(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.isActive())
+ 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.start();
+ 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.stop();
+ 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.isActive()?"ON":"OFF");
+}
+
+void QDeclarativeViewer::ffmpegFinished(int code)
+{
+ qDebug() << "ffmpeg returned" << code << frame_stream->readAllStandardError();
+}
+
+void QDeclarativeViewer::appAboutToQuit()
+{
+ // avoid QGLContext errors about invalid contexts on exit
+ canvas->setViewport(0);
+
+ // avoid crashes if messages are received after app has closed
+ delete loggerWindow;
+ loggerWindow = 0;
+ delete tester;
+ tester = 0;
+}
+
+void QDeclarativeViewer::autoStartRecording()
+{
+ setRecording(true);
+ autoStopTimer.setInterval(record_autotime);
+ autoStopTimer.start();
+}
+
+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::changeOrientation(QAction *action)
+{
+ if (!action)
+ return;
+ QString o = action->text();
+ action->setChecked(true);
+#if defined(Q_WS_S60)
+ CAknAppUi *appUi = static_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi());
+ if (appUi) {
+ CAknAppUi::TAppUiOrientation orientation = appUi->Orientation();
+ if (o == QLatin1String("Auto-orientation")) {
+ appUi->SetOrientationL(CAknAppUi::EAppUiOrientationAutomatic);
+ rotateAction->setVisible(false);
+ } else if (o == QLatin1String("Portrait")) {
+ appUi->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait);
+ rotateAction->setVisible(true);
+ } else if (o == QLatin1String("Landscape")) {
+ appUi->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape);
+ rotateAction->setVisible(true);
+ }
+ }
+#else
+ if (o == QLatin1String("Portrait"))
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::Portrait);
+ else if (o == QLatin1String("Landscape"))
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::Landscape);
+ else if (o == QLatin1String("Portrait (inverted)"))
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::PortraitInverted);
+ else if (o == QLatin1String("Landscape (inverted)"))
+ DeviceOrientation::instance()->setOrientation(DeviceOrientation::LandscapeInverted);
+#endif
+}
+
+void QDeclarativeViewer::orientationChanged()
+{
+ updateSizeHints();
+}
+
+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();
+#ifdef Q_WS_MAC
+ format.setSampleBuffers(true);
+#else
+ format.setSampleBuffers(false);
+#endif
+
+ QGLWidget *glWidget = new QGLWidget(format);
+ //### potentially faster, but causes junk to appear if top-level is Item, not Rectangle
+ //glWidget->setAutoFillBackground(false);
+
+ canvas->setViewport(glWidget);
+ }
+#else
+ Q_UNUSED(useGL)
+#endif
+}
+
+void QDeclarativeViewer::setUseNativeFileBrowser(bool use)
+{
+ useQmlFileBrowser = !use;
+}
+
+void QDeclarativeViewer::setSizeToView(bool sizeToView)
+{
+ QDeclarativeView::ResizeMode resizeMode = sizeToView ? QDeclarativeView::SizeRootObjectToView : QDeclarativeView::SizeViewToRootObject;
+ if (resizeMode != canvas->resizeMode()) {
+ canvas->setResizeMode(resizeMode);
+ updateSizeHints();
+ }
+}
+
+void QDeclarativeViewer::updateSizeHints(bool initial)
+{
+ static bool isRecursive = false;
+
+ if (isRecursive)
+ return;
+ isRecursive = true;
+
+ if (initial || (canvas->resizeMode() == QDeclarativeView::SizeViewToRootObject)) {
+ QSize newWindowSize = initial ? initialSize : canvas->sizeHint();
+ //qWarning() << "USH:" << (initial ? "INIT:" : "V2R:") << "setting fixed size " << newWindowSize;
+ if (!isFullScreen() && !isMaximized()) {
+ canvas->setFixedSize(newWindowSize);
+ resize(1, 1);
+ layout()->setSizeConstraint(QLayout::SetFixedSize);
+ layout()->activate();
+ }
+ }
+ //qWarning() << "USH: R2V: setting free size ";
+ layout()->setSizeConstraint(QLayout::SetNoConstraint);
+ layout()->activate();
+ setMinimumSize(minimumSizeHint());
+ setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+ canvas->setMinimumSize(QSize(0,0));
+ canvas->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+
+ isRecursive = false;
+}
+
+void QDeclarativeViewer::registerTypes()
+{
+ static bool registered = false;
+
+ if (!registered) {
+ // registering only for exposing the DeviceOrientation::Orientation enum
+ qmlRegisterUncreatableType<DeviceOrientation>("Qt",4,7,"Orientation","");
+ qmlRegisterUncreatableType<DeviceOrientation>("QtQuick",1,0,"Orientation","");
+ registered = true;
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qmlruntime.moc"
diff --git a/tools/qmlviewer/qmlruntime.h b/tools/qmlviewer/qmlruntime.h
new file mode 100644
index 0000000000..8b821ea730
--- /dev/null
+++ b/tools/qmlviewer/qmlruntime.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEVIEWER_H
+#define QDECLARATIVEVIEWER_H
+
+#include <QMainWindow>
+#include <QTimer>
+#include <QTime>
+#include <QList>
+
+#include "loggerwidget.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeView;
+class PreviewDeviceSkin;
+class QDeclarativeTestEngine;
+class QProcess;
+class RecordingDialog;
+class QDeclarativeTester;
+class QNetworkReply;
+class QNetworkCookieJar;
+class NetworkAccessManagerFactory;
+class QTranslator;
+class QActionGroup;
+class QMenuBar;
+
+class QDeclarativeViewer
+ : public QMainWindow
+{
+ 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,
+ Snapshot = 0x00000080,
+ TestSkipProperty = 0x00000100
+ };
+ 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.isActive(); }
+ void setAutoRecord(int from, int to);
+ void setDeviceKeys(bool);
+ void setNetworkCacheSize(int size);
+ void addLibraryPath(const QString& lib);
+ void addPluginPath(const QString& plugin);
+ void setUseGL(bool use);
+ void setUseNativeFileBrowser(bool);
+ void setSizeToView(bool sizeToView);
+
+ QDeclarativeView *view() const;
+ LoggerWidget *warningsWidget() const;
+ QString currentFile() const { return currentFileOrUrl; }
+
+ void enableExperimentalGestures();
+
+public slots:
+ void sceneResized(QSize size);
+ bool open(const QString&);
+ void openFile();
+ void openUrl();
+ void reload();
+ void takeSnapShot();
+ void toggleRecording();
+ void toggleRecordingWithSelection();
+ void ffmpegFinished(int code);
+ void showProxySettings ();
+ void proxySettingsChanged ();
+ void rotateOrientation();
+ void statusChanged();
+ void setSlowMode(bool);
+ void launch(const QString &);
+
+protected:
+ virtual void keyPressEvent(QKeyEvent *);
+ virtual bool event(QEvent *);
+ void createMenu();
+
+private slots:
+ void appAboutToQuit();
+
+ void autoStartRecording();
+ void autoStopRecording();
+ void recordFrame();
+ void chooseRecordingOptions();
+ void pickRecordingFile();
+ void toggleFullScreen();
+ void changeOrientation(QAction*);
+ void orientationChanged();
+
+ void showWarnings(bool show);
+ void warningsWidgetOpened();
+ void warningsWidgetClosed();
+
+private:
+ void updateSizeHints(bool initial = false);
+
+ QString getVideoFileName();
+
+ LoggerWidget *loggerWindow;
+ QDeclarativeView *canvas;
+ QSize initialSize;
+ QString currentFileOrUrl;
+ QTimer recordTimer;
+ QString frame_fmt;
+ QImage frame;
+ QList<QImage*> frames;
+ QProcess* frame_stream;
+ QTimer autoStartTimer;
+ QTimer autoStopTimer;
+ QString record_dither;
+ QString record_file;
+ QSize record_outsize;
+ QStringList record_args;
+ int record_rate;
+ int record_autotime;
+ bool devicemode;
+ QAction *recordAction;
+ RecordingDialog *recdlg;
+
+ void senseImageMagick();
+ void senseFfmpeg();
+ QWidget *ffmpegHelpWindow;
+ bool ffmpegAvailable;
+ bool convertAvailable;
+
+ QAction *rotateAction;
+ QActionGroup *orientation;
+ QAction *showWarningsWindow;
+
+ QString m_script;
+ ScriptOptions m_scriptOptions;
+ QDeclarativeTester *tester;
+
+ NetworkAccessManagerFactory *namFactory;
+
+ bool useQmlFileBrowser;
+
+ QTranslator *translator;
+ void loadTranslationFile(const QString& directory);
+
+ void loadDummyDataFiles(const QString& directory);
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeViewer::ScriptOptions)
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/tools/qmlviewer/qmlviewer.pro b/tools/qmlviewer/qmlviewer.pro
new file mode 100644
index 0000000000..84ebba828b
--- /dev/null
+++ b/tools/qmlviewer/qmlviewer.pro
@@ -0,0 +1,52 @@
+TEMPLATE = app
+CONFIG += qt uic
+DESTDIR = ../../bin
+
+include(qml.pri)
+
+SOURCES += main.cpp
+
+INCLUDEPATH += ../../include/QtDeclarative
+INCLUDEPATH += ../../src/declarative/util
+INCLUDEPATH += ../../src/declarative/graphicsitems
+
+target.path = $$[QT_INSTALL_BINS]
+INSTALLS += target
+
+wince* {
+ QT += xml
+
+ contains(QT_CONFIG, scripttools) {
+ QT += scripttools
+ }
+ contains(QT_CONFIG, phonon) {
+ QT += phonon
+ }
+ contains(QT_CONFIG, xmlpatterns) {
+ QT += xmlpatterns
+ }
+ contains(QT_CONFIG, webkit) {
+ QT += webkit
+ }
+}
+maemo5 {
+ QT += maemo5
+}
+symbian {
+ TARGET.UID3 = 0x20021317
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+ TARGET.EPOCHEAPSIZE = 0x20000 0x4000000
+ TARGET.CAPABILITY = NetworkServices ReadUserData
+
+ # Deploy plugin for remote debugging
+ qmldebuggingplugin.sources = $$QT_BUILD_TREE/plugins/qmltooling/qmldbg_tcp$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/qmltooling/qmldbg_ost$${QT_LIBINFIX}.dll
+ qmldebuggingplugin.path = c:$$QT_PLUGINS_BASE_DIR/qmltooling
+ DEPLOYMENT += qmldebuggingplugin
+}
+mac {
+ QMAKE_INFO_PLIST=Info_mac.plist
+ TARGET=QMLViewer
+ ICON=qml.icns
+} else {
+ TARGET=qmlviewer
+}
diff --git a/tools/qmlviewer/recopts.ui b/tools/qmlviewer/recopts.ui
new file mode 100644
index 0000000000..ce2da30767
--- /dev/null
+++ b/tools/qmlviewer/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>
diff --git a/tools/qmlviewer/recopts_maemo5.ui b/tools/qmlviewer/recopts_maemo5.ui
new file mode 100644
index 0000000000..3bb5ecabd9
--- /dev/null
+++ b/tools/qmlviewer/recopts_maemo5.ui
@@ -0,0 +1,254 @@
+<?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>469</width>
+ <height>142</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Video options</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" columnstretch="0,2,0">
+ <property name="sizeConstraint">
+ <enum>QLayout::SetMinAndMaxSize</enum>
+ </property>
+ <property name="leftMargin">
+ <number>16</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>16</number>
+ </property>
+ <property name="bottomMargin">
+ <number>8</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>16</number>
+ </property>
+ <property name="verticalSpacing">
+ <number>0</number>
+ </property>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="file"/>
+ </item>
+ <item row="0" column="2" rowspan="3">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>72</width>
+ <height>56</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Size</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="sizeCombo">
+ <item>
+ <property name="text">
+ <string/>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>VGA</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>QVGA</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>720p</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="2" column="0" rowspan="2">
+ <widget class="QLabel" name="rateLabel">
+ <property name="text">
+ <string>Rate</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" rowspan="2">
+ <widget class="QComboBox" name="rateCombo">
+ <item>
+ <property name="text">
+ <string>60 Hz</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>50 Hz</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>25 Hz</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>24 Hz</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>20 Hz</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>15 Hz</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>10 Hz</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLineEdit" name="args"/>
+ </item>
+ <item row="4" column="1">
+ <widget class="QComboBox" name="profile"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="profileLabel">
+ <property name="text">
+ <string>Profile</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0" colspan="2">
+ <widget class="QLabel" name="warning">
+ <property name="text">
+ <string notr="true">warning</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2" rowspan="3">
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QPushButton" name="pickfile">
+ <property name="text">
+ <string>File</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QPushButton" name="ffmpegHelp">
+ <property name="text">
+ <string>Options</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <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>
+ </connections>
+ <slots>
+ <signal>filePicked(QString)</signal>
+ <signal>argumentsPicked(QString)</signal>
+ <slot>pickFile()</slot>
+ <slot>pickProfile(int)</slot>
+ <slot>storeCustomArgs(QString)</slot>
+ </slots>
+</ui>
diff --git a/tools/qmlviewer/startup/Logo.qml b/tools/qmlviewer/startup/Logo.qml
new file mode 100644
index 0000000000..c0b7698f7c
--- /dev/null
+++ b/tools/qmlviewer/startup/Logo.qml
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+Rectangle {
+ id: myApp
+ width: 411
+ height: 411
+ color: "transparent"
+ property alias logoState : myApp.state
+ signal animationFinished
+
+ Item {
+ id: sketchBlueHolder
+ width: sketchLogo.width
+ height: sketchLogo.height
+ Image {
+ id: image1
+ x: -44
+ y: -45
+ smooth: true
+ source: "shadow.png"
+ }
+ Item {
+ clip: true
+ width: sketchLogo.width
+ height: sketchLogo.height
+ Image {
+ id: sketchLogo
+ smooth: true
+ source: "qt-sketch.jpg"
+ }
+ Image {
+ id: blueLogo
+ y: -420
+ smooth: true
+ source: "qt-blue.jpg"
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "showBlueprint"
+ PropertyChanges {
+ target: blueLogo
+ y: 0
+ }
+ PropertyChanges {
+ target: sketchLogo
+ opacity: 0
+ }
+ },
+ State {
+ extend: "showBlueprint"
+ name: "finale"
+ PropertyChanges {
+ target: fullLogo
+ opacity: 1
+ }
+ PropertyChanges {
+ target: backLogo
+ opacity: 1
+ scale: 1
+ }
+ PropertyChanges {
+ target: frontLogo
+ opacity: 1
+ scale: 1
+ }
+ PropertyChanges {
+ target: qtText
+ opacity: 1
+ scale: 1
+ }
+ PropertyChanges {
+ target: sketchBlueHolder
+ opacity: 0
+ scale: 1.4
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ to: "showBlueprint"
+ SequentialAnimation {
+ NumberAnimation { property: "y"; duration: 600; easing.type: "OutBounce" }
+ PropertyAction { target: sketchLogo; property: "opacity" }
+ }
+ },
+ Transition {
+ to: "finale"
+ PropertyAction { target: fullLogo; property: "opacity" }
+ SequentialAnimation {
+ NumberAnimation { target: backLogo; properties: "scale, opacity"; duration: 300 }
+ NumberAnimation { target: frontLogo; properties: "scale, opacity"; duration: 300 }
+ ParallelAnimation {
+ NumberAnimation { target: qtText; properties: "opacity, scale"; duration: 400; easing.type: "OutQuad" }
+ NumberAnimation { target: sketchBlueHolder; property: "opacity"; duration: 300; easing.type: "OutQuad" }
+ NumberAnimation { target: sketchBlueHolder; property: "scale"; duration: 320; easing.type: "OutQuad" }
+ }
+ PauseAnimation { duration: 1000 }
+ ScriptAction { script: myApp.animationFinished() }
+ }
+ }
+ ]
+
+ Item {
+ id: fullLogo
+ opacity: 0
+ Image {
+ id: backLogo
+ x: -16
+ y: -41
+ opacity: 0
+ scale: 0.7
+ smooth: true
+ source: "qt-back.png"
+ }
+ Image {
+ id: frontLogo
+ x: -17
+ y: -41
+ opacity: 0
+ scale: 1.2
+ smooth: true
+ source: "qt-front.png"
+ }
+ Image {
+ id: qtText
+ x: -10
+ y: -41
+ opacity: 0
+ scale: 1.2
+ smooth: true
+ source: "qt-text.png"
+ }
+ }
+}
diff --git a/tools/qmlviewer/startup/qt-back.png b/tools/qmlviewer/startup/qt-back.png
new file mode 100644
index 0000000000..077215f882
--- /dev/null
+++ b/tools/qmlviewer/startup/qt-back.png
Binary files differ
diff --git a/tools/qmlviewer/startup/qt-blue.jpg b/tools/qmlviewer/startup/qt-blue.jpg
new file mode 100644
index 0000000000..b204896483
--- /dev/null
+++ b/tools/qmlviewer/startup/qt-blue.jpg
Binary files differ
diff --git a/tools/qmlviewer/startup/qt-front.png b/tools/qmlviewer/startup/qt-front.png
new file mode 100644
index 0000000000..dbfb43e374
--- /dev/null
+++ b/tools/qmlviewer/startup/qt-front.png
Binary files differ
diff --git a/tools/qmlviewer/startup/qt-sketch.jpg b/tools/qmlviewer/startup/qt-sketch.jpg
new file mode 100644
index 0000000000..1ede6f079b
--- /dev/null
+++ b/tools/qmlviewer/startup/qt-sketch.jpg
Binary files differ
diff --git a/tools/qmlviewer/startup/qt-text.png b/tools/qmlviewer/startup/qt-text.png
new file mode 100644
index 0000000000..d44995c9b3
--- /dev/null
+++ b/tools/qmlviewer/startup/qt-text.png
Binary files differ
diff --git a/tools/qmlviewer/startup/quick-blur.png b/tools/qmlviewer/startup/quick-blur.png
new file mode 100644
index 0000000000..29ec243387
--- /dev/null
+++ b/tools/qmlviewer/startup/quick-blur.png
Binary files differ
diff --git a/tools/qmlviewer/startup/quick-regular.png b/tools/qmlviewer/startup/quick-regular.png
new file mode 100644
index 0000000000..38321cbf19
--- /dev/null
+++ b/tools/qmlviewer/startup/quick-regular.png
Binary files differ
diff --git a/tools/qmlviewer/startup/shadow.png b/tools/qmlviewer/startup/shadow.png
new file mode 100644
index 0000000000..44f92fee73
--- /dev/null
+++ b/tools/qmlviewer/startup/shadow.png
Binary files differ
diff --git a/tools/qmlviewer/startup/startup.qml b/tools/qmlviewer/startup/startup.qml
new file mode 100644
index 0000000000..a216ac6fe9
--- /dev/null
+++ b/tools/qmlviewer/startup/startup.qml
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+Rectangle {
+ id: treatsApp
+ width: 800
+ height: 480
+ color: "darkgrey"
+ Component.onCompleted: treatsApp.state = "part1"
+ signal animationFinished
+
+ Item {
+ width: 800
+ height: 480
+ anchors.centerIn: parent
+ clip: true
+
+ Logo {
+ id: logo
+ x: 165
+ y: 35
+ rotation: -15
+ scale: 0.6
+ opacity: 0
+ onAnimationFinished: treatsApp.animationFinished();
+ }
+
+ Item {
+ id: quickblur
+ x: 800//325
+ y: 344
+ Image {
+ id: blurText
+ source: "quick-blur.png"
+ }
+ Image {
+ id: quickregular
+ x: -1
+ y: 0
+ opacity: 0
+ source: "quick-regular.png"
+ }
+ Image {
+ id: star
+ x: -1
+ y: 0
+ opacity: 0
+ source: "white-star.png"
+ smooth: true
+ NumberAnimation on rotation {
+ from: 0
+ to: 360
+ loops: 3
+ running: true
+ duration: 2000
+ }
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "part1"
+ PropertyChanges {
+ target: logo
+ scale: 0.8
+ opacity: 1
+ rotation: 0
+ }
+ PropertyChanges {
+ target: treatsApp
+ color: "black"
+ }
+ PropertyChanges {
+ target: logo
+ y: 10
+ }
+ PropertyChanges {
+ target: quickblur
+ x: logo.x + 145
+ }
+ PropertyChanges {
+ target: blurText
+ opacity: 0
+ }
+ PropertyChanges {
+ target: quickregular
+ opacity: 1
+ }
+ PropertyChanges {
+ target: star
+ x: -7
+ y: -37
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ ParallelAnimation {
+ NumberAnimation { target: logo; property: "opacity"; duration: 500 }
+ NumberAnimation { target: logo; property: "scale"; duration: 4000; }
+ NumberAnimation { target: logo; property: "rotation"; duration: 2000; easing.type: "OutBack"}
+ ColorAnimation { duration: 3000}
+ SequentialAnimation {
+ PauseAnimation { duration: 1000 }
+ ScriptAction { script: logo.logoState = "showBlueprint" }
+ PauseAnimation { duration: 800 }
+ ScriptAction { script: logo.logoState = "finale" }
+ PauseAnimation { duration: 800 }
+ ParallelAnimation {
+ NumberAnimation { target: quickblur; property: "x"; duration: 200;}
+ SequentialAnimation {
+ PauseAnimation { duration: 200}
+ ParallelAnimation {
+ NumberAnimation { target: blurText; property: "opacity"; duration: 300;}
+ NumberAnimation { target: quickregular; property: "opacity"; duration: 300;}
+ }
+ NumberAnimation { target: star; property: "opacity"; from: 0; to: 1; duration: 500 }
+ PauseAnimation { duration: 200 }
+ NumberAnimation { target: star; property: "opacity"; from: 1; to: 0; duration: 500 }
+ }
+ SequentialAnimation {
+ PauseAnimation { duration: 150}
+ NumberAnimation { target: logo; property: "y"; duration: 300; easing.type: "OutBounce" }
+ }
+ }
+ }
+ }
+ }
+ ]
+
+} // treatsApp
diff --git a/tools/qmlviewer/startup/startup.qrc b/tools/qmlviewer/startup/startup.qrc
new file mode 100644
index 0000000000..52e67050d9
--- /dev/null
+++ b/tools/qmlviewer/startup/startup.qrc
@@ -0,0 +1,16 @@
+<RCC>
+ <qresource prefix="/startup">
+ <file>Logo.qml</file>
+ <file>qt-back.png</file>
+ <file>qt-blue.jpg</file>
+ <file>qt-front.png</file>
+ <file>qt-sketch.jpg</file>
+ <file>qt-text.png</file>
+ <file>quick-blur.png</file>
+ <file>quick-regular.png</file>
+ <file>shadow.png</file>
+ <file>startup.qml</file>
+ <file>startup.qrc</file>
+ <file>white-star.png</file>
+ </qresource>
+</RCC>
diff --git a/tools/qmlviewer/startup/white-star.png b/tools/qmlviewer/startup/white-star.png
new file mode 100644
index 0000000000..f467c9480e
--- /dev/null
+++ b/tools/qmlviewer/startup/white-star.png
Binary files differ
diff --git a/tools/qmlviewer/texteditautoresizer_maemo5.h b/tools/qmlviewer/texteditautoresizer_maemo5.h
new file mode 100644
index 0000000000..71dbce0a1f
--- /dev/null
+++ b/tools/qmlviewer/texteditautoresizer_maemo5.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the 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 <QtGui/qplaintextedit.h>
+#include <QtGui/qtextedit.h>
+#include <QtGui/qscroller.h>
+#include <QtGui/qscrollarea.h>
+#include <QtDebug>
+
+#ifndef TEXTEDITAUTORESIZER_H
+#define TEXTEDITAUTORESIZER_H
+
+class TextEditAutoResizer : public QObject
+{
+ Q_OBJECT
+public:
+ TextEditAutoResizer(QWidget *parent)
+ : QObject(parent), plainTextEdit(qobject_cast<QPlainTextEdit *>(parent)),
+ textEdit(qobject_cast<QTextEdit *>(parent)), edit(qobject_cast<QFrame *>(parent))
+ {
+ // parent must either inherit QPlainTextEdit or QTextEdit!
+ Q_ASSERT(plainTextEdit || textEdit);
+
+ connect(parent, SIGNAL(textChanged()), this, SLOT(textEditChanged()));
+ connect(parent, SIGNAL(cursorPositionChanged()), this, SLOT(textEditChanged()));
+
+ textEditChanged();
+ }
+
+private Q_SLOTS:
+ inline void textEditChanged();
+
+private:
+ QPlainTextEdit *plainTextEdit;
+ QTextEdit *textEdit;
+ QFrame *edit;
+};
+
+void TextEditAutoResizer::textEditChanged()
+{
+ QTextDocument *doc = textEdit ? textEdit->document() : plainTextEdit->document();
+ QRect cursor = textEdit ? textEdit->cursorRect() : plainTextEdit->cursorRect();
+
+ QSize s = doc->size().toSize();
+ if (plainTextEdit)
+ s.setHeight((s.height() + 2) * edit->fontMetrics().lineSpacing());
+
+ const QRect fr = edit->frameRect();
+ const QRect cr = edit->contentsRect();
+
+ edit->setMinimumHeight(qMax(70, s.height() + (fr.height() - cr.height() - 1)));
+
+ // make sure the cursor is visible in case we have a QAbstractScrollArea parent
+ QPoint pos = edit->pos();
+ QWidget *pw = edit->parentWidget();
+ while (pw) {
+ if (qobject_cast<QScrollArea *>(pw))
+ break;
+ pw = pw->parentWidget();
+ }
+
+ if (pw) {
+ QScrollArea *area = static_cast<QScrollArea *>(pw);
+ QPoint scrollto = area->widget()->mapFrom(edit, cursor.center());
+ QPoint margin(10 + cursor.width(), 2 * cursor.height());
+
+#ifdef Q_WS_MAEMO_5
+ QScroller::scroller(area)->ensureVisible(scrollto, margin.x(), margin.y());
+#else
+ area->ensureVisible(scrollto.x(), scrollto.y(), margin.x(), margin.y());
+#endif
+ }
+}
+
+#endif