diff options
author | Matthew Vogt <matthew.vogt@nokia.com> | 2012-01-30 14:16:15 +1000 |
---|---|---|
committer | Matthew Vogt <matthew.vogt@nokia.com> | 2012-01-30 14:16:15 +1000 |
commit | 12a5ddf456ba8549645a8cb28a8b4ed6197a14da (patch) | |
tree | 63ee2c88af936e0609a3a194f5bcc304c4c0b707 /tools |
Import relevant source from Qt 4.8
Change-Id: I5078db4081d95290c54f39d3c0efc2fc2f62e6a6
Diffstat (limited to 'tools')
46 files changed, 6553 insertions, 0 deletions
diff --git a/tools/designer/src/plugins/plugins.pri b/tools/designer/src/plugins/plugins.pri new file mode 100644 index 00000000..e5edfe2f --- /dev/null +++ b/tools/designer/src/plugins/plugins.pri @@ -0,0 +1,8 @@ +CONFIG += designer +win32|mac: CONFIG+= debug_and_release +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/designer +contains(TEMPLATE, ".*lib"):TARGET = $$qtLibraryTarget($$TARGET) + +# install +target.path = $$[QT_INSTALL_PLUGINS]/designer +INSTALLS += target diff --git a/tools/designer/src/plugins/plugins.pro b/tools/designer/src/plugins/plugins.pro new file mode 100644 index 00000000..bcebb82e --- /dev/null +++ b/tools/designer/src/plugins/plugins.pro @@ -0,0 +1,10 @@ +TEMPLATE = subdirs +CONFIG += ordered + +REQUIRES = !CONFIG(static,shared|static) +contains(QT_CONFIG, qt3support): SUBDIRS += widgets +win32: SUBDIRS += activeqt +# contains(QT_CONFIG, opengl): SUBDIRS += tools/view3d +contains(QT_CONFIG, webkit): SUBDIRS += qwebview +contains(QT_CONFIG, phonon): SUBDIRS += phononwidgets +contains(QT_CONFIG, declarative): SUBDIRS += qdeclarativeview diff --git a/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro b/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro new file mode 100644 index 00000000..b8abe874 --- /dev/null +++ b/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview.pro @@ -0,0 +1,13 @@ +TEMPLATE = lib +TARGET = qdeclarativeview +CONFIG += qt warn_on plugin designer +QT += declarative + +include(../plugins.pri) +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +SOURCES += qdeclarativeview_plugin.cpp +HEADERS += qdeclarativeview_plugin.h diff --git a/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp b/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp new file mode 100644 index 00000000..d35df04f --- /dev/null +++ b/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeview_plugin.h" + +#include <QtDesigner/QExtensionFactory> +#include <QtDesigner/QExtensionManager> + +#include <QtCore/qplugin.h> +#include <QtDeclarative/QDeclarativeView> + +static const char toolTipC[] = "QtDeclarative view widget"; + +QT_BEGIN_NAMESPACE + +QDeclarativeViewPlugin::QDeclarativeViewPlugin(QObject *parent) : + QObject(parent), + m_initialized(false) +{ +} + +QString QDeclarativeViewPlugin::name() const +{ + return QLatin1String("QDeclarativeView"); +} + +QString QDeclarativeViewPlugin::group() const +{ + return QLatin1String("Display Widgets"); +} + +QString QDeclarativeViewPlugin::toolTip() const +{ + return tr(toolTipC); +} + +QString QDeclarativeViewPlugin::whatsThis() const +{ + return tr(toolTipC); +} + +QString QDeclarativeViewPlugin::includeFile() const +{ + return QLatin1String("QtDeclarative/QDeclarativeView"); +} + +QIcon QDeclarativeViewPlugin::icon() const +{ + return QIcon(); +} + +bool QDeclarativeViewPlugin::isContainer() const +{ + return false; +} + +QWidget *QDeclarativeViewPlugin::createWidget(QWidget *parent) +{ + return new QDeclarativeView(parent); +} + +bool QDeclarativeViewPlugin::isInitialized() const +{ + return m_initialized; +} + +void QDeclarativeViewPlugin::initialize(QDesignerFormEditorInterface * /*core*/) +{ + if (m_initialized) + return; + + m_initialized = true; +} + +QString QDeclarativeViewPlugin::domXml() const +{ + return QLatin1String("\ + <ui language=\"c++\">\ + <widget class=\"QDeclarativeView\" name=\"declarativeView\">\ + <property name=\"geometry\">\ + <rect>\ + <x>0</x>\ + <y>0</y>\ + <width>300</width>\ + <height>200</height>\ + </rect>\ + </property>\ + </widget>\ + </ui>"); +} + +Q_EXPORT_PLUGIN2(customwidgetplugin, QDeclarativeViewPlugin) + +QT_END_NAMESPACE diff --git a/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h b/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h new file mode 100644 index 00000000..7b1de243 --- /dev/null +++ b/tools/designer/src/plugins/qdeclarativeview/qdeclarativeview_plugin.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Designer of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEVIEW_PLUGIN_H +#define QDECLARATIVEVIEW_PLUGIN_H + +#include <QtDesigner/QDesignerCustomWidgetInterface> + +QT_BEGIN_NAMESPACE + +class QDeclarativeViewPlugin: public QObject, public QDesignerCustomWidgetInterface +{ + Q_OBJECT + Q_INTERFACES(QDesignerCustomWidgetInterface) +public: + QDeclarativeViewPlugin(QObject *parent = 0); + + virtual QString name() const; + virtual QString group() const; + virtual QString toolTip() const; + virtual QString whatsThis() const; + virtual QString includeFile() const; + virtual QIcon icon() const; + virtual bool isContainer() const; + virtual QWidget *createWidget(QWidget *parent); + virtual bool isInitialized() const; + virtual void initialize(QDesignerFormEditorInterface *core); + virtual QString domXml() const; + +private: + bool m_initialized; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEVIEW_PLUGIN_H diff --git a/tools/qml/Info_mac.plist b/tools/qml/Info_mac.plist new file mode 100644 index 00000000..08775479 --- /dev/null +++ b/tools/qml/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/qml/browser/Browser.qml b/tools/qml/browser/Browser.qml new file mode 100644 index 00000000..5c5598b5 --- /dev/null +++ b/tools/qml/browser/Browser.qml @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/browser/browser.qrc b/tools/qml/browser/browser.qrc new file mode 100644 index 00000000..9c688e75 --- /dev/null +++ b/tools/qml/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/qml/browser/images/folder.png b/tools/qml/browser/images/folder.png Binary files differnew file mode 100644 index 00000000..e53e2ad4 --- /dev/null +++ b/tools/qml/browser/images/folder.png diff --git a/tools/qml/browser/images/titlebar.png b/tools/qml/browser/images/titlebar.png Binary files differnew file mode 100644 index 00000000..51c90082 --- /dev/null +++ b/tools/qml/browser/images/titlebar.png diff --git a/tools/qml/browser/images/titlebar.sci b/tools/qml/browser/images/titlebar.sci new file mode 100644 index 00000000..0418d94c --- /dev/null +++ b/tools/qml/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/qml/browser/images/up.png b/tools/qml/browser/images/up.png Binary files differnew file mode 100644 index 00000000..b05f8025 --- /dev/null +++ b/tools/qml/browser/images/up.png diff --git a/tools/qml/deviceorientation.cpp b/tools/qml/deviceorientation.cpp new file mode 100644 index 00000000..d37df09b --- /dev/null +++ b/tools/qml/deviceorientation.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/deviceorientation.h b/tools/qml/deviceorientation.h new file mode 100644 index 00000000..7662d3ff --- /dev/null +++ b/tools/qml/deviceorientation.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/deviceorientation_harmattan.cpp b/tools/qml/deviceorientation_harmattan.cpp new file mode 100644 index 00000000..d415f51f --- /dev/null +++ b/tools/qml/deviceorientation_harmattan.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/deviceorientation_maemo5.cpp b/tools/qml/deviceorientation_maemo5.cpp new file mode 100644 index 00000000..14162767 --- /dev/null +++ b/tools/qml/deviceorientation_maemo5.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/deviceorientation_symbian.cpp b/tools/qml/deviceorientation_symbian.cpp new file mode 100644 index 00000000..96f2809f --- /dev/null +++ b/tools/qml/deviceorientation_symbian.cpp @@ -0,0 +1,192 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/loggerwidget.cpp b/tools/qml/loggerwidget.cpp new file mode 100644 index 00000000..30bd3449 --- /dev/null +++ b/tools/qml/loggerwidget.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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(QLatin1String("warnings"), QLatin1String("hide")).toString(); + if (warningsPreferences == QLatin1String("show")) { + m_visibility = ShowWarnings; + } else if (warningsPreferences == QLatin1String("hide")) { + m_visibility = HideWarnings; + } else { + m_visibility = AutoShowWarnings; + } +} + +void LoggerWidget::saveSettings() +{ + if (m_visibilityOrigin != SettingsOrigin) + return; + + QString value = QLatin1String("autoShow"); + if (defaultVisibility() == ShowWarnings) { + value = QLatin1String("show"); + } else if (defaultVisibility() == HideWarnings) { + value = QLatin1String("hide"); + } + + QSettings settings; + settings.setValue(QLatin1String("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/qml/loggerwidget.h b/tools/qml/loggerwidget.h new file mode 100644 index 00000000..abe67534 --- /dev/null +++ b/tools/qml/loggerwidget.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/main.cpp b/tools/qml/main.cpp new file mode 100644 index 00000000..d62249df --- /dev/null +++ b/tools/qml/main.cpp @@ -0,0 +1,606 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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 <QLibraryInfo> +#include "qdeclarativetester.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::translate("QDeclarativeViewer", "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 = QLatin1String("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"); + qWarning(" -opengl .................................. use a QGLWidget for the viewport (default)"); +#else + qWarning(" -no-opengl ............................... don't use a QGLWidget for the viewport (default)"); + 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(QLatin1String("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 == QLatin1String("-frameless")) { + opts.frameless = true; + } else if (arg == QLatin1String("-maximized")) { + opts.maximized = true; + } else if (arg == QLatin1String("-fullscreen")) { + opts.fullScreen = true; + } else if (arg == QLatin1String("-stayontop")) { + opts.stayOnTop = true; + } else if (arg == QLatin1String("-netcache")) { + if (lastArg) usage(); + opts.cache = arguments.at(++i).toInt(); + } else if (arg == QLatin1String("-recordrate")) { + if (lastArg) usage(); + opts.fps = arguments.at(++i).toDouble(); + } else if (arg == QLatin1String("-recordfile")) { + if (lastArg) usage(); + opts.recordfile = arguments.at(++i); + } else if (arg == QLatin1String("-record")) { + if (lastArg) usage(); + opts.recordargs << arguments.at(++i); + } else if (arg == QLatin1String("-recorddither")) { + if (lastArg) usage(); + opts.dither = arguments.at(++i); + } else if (arg == QLatin1String("-autorecord")) { + if (lastArg) usage(); + QString range = arguments.at(++i); + int dash = range.indexOf(QLatin1Char('-')); + if (dash > 0) + opts.autorecord_from = range.left(dash).toInt(); + opts.autorecord_to = range.mid(dash+1).toInt(); + } else if (arg == QLatin1String("-devicekeys")) { + opts.devkeys = true; + } else if (arg == QLatin1String("-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 == QLatin1String("-translation")) { + if (lastArg) usage(); + opts.translationFile = arguments.at(++i); + } else if (arg == QLatin1String("-no-opengl")) { + opts.useGL = false; + } else if (arg == QLatin1String("-opengl")) { + opts.useGL = true; + } else if (arg == QLatin1String("-qmlbrowser")) { + opts.useNativeFileBrowser = false; + } else if (arg == QLatin1String("-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 == QLatin1String("-I") || arg == QLatin1String("-L")) { + if (arg == QLatin1String("-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 == QLatin1String("-P")) { + if (lastArg) usage(); + opts.plugins << arguments.at(++i); + } else if (arg == QLatin1String("-script")) { + if (lastArg) usage(); + opts.script = arguments.at(++i); + } else if (arg == QLatin1String("-scriptopts")) { + if (lastArg) usage(); + opts.scriptopts = arguments.at(++i); + } else if (arg == QLatin1String("-savescript")) { + if (lastArg) usage(); + opts.script = arguments.at(++i); + opts.runScript = false; + } else if (arg == QLatin1String("-playscript")) { + if (lastArg) usage(); + opts.script = arguments.at(++i); + opts.runScript = true; + } else if (arg == QLatin1String("-sizeviewtorootobject")) { + opts.sizeToView = false; + } else if (arg == QLatin1String("-sizerootobjecttoview")) { + opts.sizeToView = true; + } else if (arg == QLatin1String("-experimentalgestures")) { + opts.experimentalGestures = true; + } else if (!arg.startsWith(QLatin1Char('-'))) { + fileNames.append(arg); + } else if (true || arg == QLatin1String("-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 = QString::fromAscii(argv[i]); + if (arg == QLatin1String("-graphicssystem")) { + gsSpecified = true; + break; + } + } + + if (!gsSpecified) + QApplication::setGraphicsSystem(QLatin1String("raster")); +#endif + + Application app(argc, argv); + app.setApplicationName(QLatin1String("QtQmlViewer")); + app.setOrganizationName(QLatin1String("Nokia")); + app.setOrganizationDomain(QLatin1String("nokia.com")); + + QDeclarativeViewer::registerTypes(); + QDeclarativeTester::registerTypes(); + + parseCommandLineOptions(app.arguments()); + + QTranslator translator; + QTranslator qtTranslator; + QString sysLocale = QLocale::system().name(); + if (translator.load(QLatin1String("qmlviewer_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&translator); + if (qtTranslator.load(QLatin1String("qt_") + sysLocale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&qtTranslator); + } else { + app.removeTranslator(&translator); + } + } + + 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/qml/proxysettings.cpp b/tools/qml/proxysettings.cpp new file mode 100644 index 00000000..a3ad2125 --- /dev/null +++ b/tools/qml/proxysettings.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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(QLatin1String("000.000.000.000;_")); +#endif + QIntValidator *validator = new QIntValidator (0, 9999, this); + proxyPortEdit->setValidator(validator); + + QSettings settings; + proxyCheckBox->setChecked(settings.value(QLatin1String("http_proxy/use"), 0).toBool()); + proxyServerEdit->insert(settings.value(QLatin1String("http_proxy/hostname")).toString()); + proxyPortEdit->insert(settings.value(QLatin1String("http_proxy/port"), QLatin1String("80")).toString ()); + usernameEdit->insert(settings.value(QLatin1String("http_proxy/username")).toString ()); + passwordEdit->insert(settings.value(QLatin1String("http_proxy/password")).toString ()); +} + +ProxySettings::~ProxySettings() +{ +} + +void ProxySettings::accept () +{ + QSettings settings; + + settings.setValue(QLatin1String("http_proxy/use"), proxyCheckBox->isChecked()); + settings.setValue(QLatin1String("http_proxy/hostname"), proxyServerEdit->text()); + settings.setValue(QLatin1String("http_proxy/port"), proxyPortEdit->text()); + settings.setValue(QLatin1String("http_proxy/username"), usernameEdit->text()); + settings.setValue(QLatin1String("http_proxy/password"), passwordEdit->text()); + + QDialog::accept (); +} + +QNetworkProxy ProxySettings::httpProxy () +{ + QSettings settings; + QNetworkProxy proxy; + + bool proxyInUse = settings.value(QLatin1String("http_proxy/use"), 0).toBool(); + if (proxyInUse) { + proxy.setType (QNetworkProxy::HttpProxy); + proxy.setHostName (settings.value(QLatin1String("http_proxy/hostname")).toString());// "192.168.220.5" + proxy.setPort (settings.value(QLatin1String("http_proxy/port"), 80).toInt()); // 8080 + proxy.setUser (settings.value(QLatin1String("http_proxy/username")).toString()); + proxy.setPassword (settings.value(QLatin1String("http_proxy/password")).toString()); + //QNetworkProxy::setApplicationProxy (proxy); + } + else { + proxy.setType (QNetworkProxy::NoProxy); + } + return proxy; +} + +bool ProxySettings::httpProxyInUse() +{ + QSettings settings; + return settings.value(QLatin1String("http_proxy/use"), 0).toBool(); +} + +QT_END_NAMESPACE diff --git a/tools/qml/proxysettings.h b/tools/qml/proxysettings.h new file mode 100644 index 00000000..33d38a5e --- /dev/null +++ b/tools/qml/proxysettings.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/proxysettings.ui b/tools/qml/proxysettings.ui new file mode 100644 index 00000000..84e39fe0 --- /dev/null +++ b/tools/qml/proxysettings.ui @@ -0,0 +1,115 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>ProxySettings</class> + <widget class="QDialog" name="ProxySettings"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>318</width> + <height>199</height> + </rect> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QCheckBox" name="proxyCheckBox"> + <property name="text"> + <string>Use http proxy</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="serverAddressLabel"> + <property name="text"> + <string>Server Address:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="proxyServerEdit"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="proxyPortEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="usernameLabel"> + <property name="text"> + <string>Username:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="usernameEdit"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="passwordLabel"> + <property name="text"> + <string>Password:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="passwordEdit"> + <property name="echoMode"> + <enum>QLineEdit::Password</enum> + </property> + </widget> + </item> + <item row="5" column="0" colspan="2"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>ProxySettings</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>ProxySettings</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/tools/qml/proxysettings_maemo5.ui b/tools/qml/proxysettings_maemo5.ui new file mode 100644 index 00000000..75875d83 --- /dev/null +++ b/tools/qml/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>447</width> + <height>162</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 notr="true">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/qml/qdeclarativetester.cpp b/tools/qml/qdeclarativetester.cpp new file mode 100644 index 00000000..0ea91282 --- /dev/null +++ b/tools/qml/qdeclarativetester.cpp @@ -0,0 +1,453 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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(QLatin1String(".")); + + 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() + QLatin1String(".") + QString::number(imgCount) + QLatin1String(".png"); + fe.image.save(m_script + QLatin1String(".") + QString::number(imgCount) + QLatin1String(".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() + QLatin1String(".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() + QLatin1String(".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/qml/qdeclarativetester.h b/tools/qml/qdeclarativetester.h new file mode 100644 index 00000000..5c79b1fe --- /dev/null +++ b/tools/qml/qdeclarativetester.h @@ -0,0 +1,290 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/qml.icns b/tools/qml/qml.icns Binary files differnew file mode 100644 index 00000000..c7605162 --- /dev/null +++ b/tools/qml/qml.icns diff --git a/tools/qml/qml.pri b/tools/qml/qml.pri new file mode 100644 index 00000000..cfc74af8 --- /dev/null +++ b/tools/qml/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/qml/qml.pro b/tools/qml/qml.pro new file mode 100644 index 00000000..3d1b84bb --- /dev/null +++ b/tools/qml/qml.pro @@ -0,0 +1,54 @@ +TEMPLATE = app +CONFIG += qt uic declarative_debug +DESTDIR = ../../bin + +include(qml.pri) + +SOURCES += main.cpp + +INCLUDEPATH += ../../include/QtDeclarative +INCLUDEPATH += ../../src/declarative/util +INCLUDEPATH += ../../src/declarative/graphicsitems + +DEFINES += QT_NO_CAST_FROM_ASCII QT_NO_CAST_TO_ASCII + +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/qml/qmlruntime.cpp b/tools/qml/qmlruntime.cpp new file mode 100644 index 00000000..9f79f3b7 --- /dev/null +++ b/tools/qml/qmlruntime.cpp @@ -0,0 +1,1554 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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(QString::fromAscii(ffmpegprofiles[i].name)); + } + } + + void setArguments(QString a) + { + int i; + for (i=0; ffmpegprofiles[i].args[0]; ++i) { + if (QString::fromAscii(ffmpegprofiles[i].args) == a) { + profile->setCurrentIndex(i); + args->setText(QString::fromAscii(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(QLatin1String("Cookies"), data); + } + + void load() + { + QMutexLocker lock(&mutex); + QSettings settings; + QByteArray data = settings.value(QLatin1String("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 == QLatin1String("http") || protocolTag == QLatin1String("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, QString(), types.join(QLatin1String(";; "))); +} + +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(tr("F3"))); + connect(snapshotAction, SIGNAL(triggered()), this, SLOT(takeSnapShot())); + + recordAction = new QAction(tr("Start Recording &Video"), this); + recordAction->setShortcut(QKeySequence(tr("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(tr("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(tr("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(QLatin1String(" "))); + 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(QLatin1Char(' '),QString::SkipEmptyParts); + } +} + +void QDeclarativeViewer::toggleRecordingWithSelection() +{ + if (!recordTimer.isActive()) { + if (record_file.isEmpty()) { + QString fileName = getVideoFileName(); + if (fileName.isEmpty()) + return; + if (!fileName.contains(QRegExp(QLatin1String(".[^\\/]*$")))) + fileName += QLatin1String(".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(QLatin1String("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 + QLatin1String("/dummydata"), QLatin1String("*.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(QLatin1String("qmlViewer"), this); +#ifdef Q_OS_SYMBIAN + ctxt->setContextProperty(QLatin1String("qmlViewerFolder"), QLatin1String("E:\\")); // Documents on your S60 phone +#else + ctxt->setContextProperty(QLatin1String("qmlViewerFolder"), QDir::currentPath()); +#endif + + ctxt->setContextProperty(QLatin1String("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(QLatin1String("convert"), QStringList() << QLatin1String("-h")); + proc.waitForFinished(2000); + QString help = QString::fromAscii(proc.readAllStandardOutput()); + convertAvailable = help.contains(QLatin1String("ImageMagick")); +} + +void QDeclarativeViewer::senseFfmpeg() +{ + QProcess proc; + proc.start(QLatin1String("ffmpeg"), QStringList() << QLatin1String("-h")); + proc.waitForFinished(2000); + QString ffmpegHelp = QString::fromAscii(proc.readAllStandardOutput()); + ffmpegAvailable = ffmpegHelp.contains(QLatin1String("-s ")); + ffmpegHelp = tr("Video recording uses ffmpeg:") + QLatin1String("\n\n") + ffmpegHelp; + + QDialog *d = new QDialog(recdlg); + QVBoxLayout *l = new QVBoxLayout(d); + QTextBrowser *b = new QTextBrowser(d); + QFont f = b->font(); + f.setFamily(QLatin1String("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 != QLatin1String(".png") && (!convertAvailable || frame_fmt != QLatin1String(".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 << QLatin1String("-y"); + args << QLatin1String("-r") << QString::number(record_rate); + args << QLatin1String("-f") << QLatin1String("rawvideo"); + args << QLatin1String("-pix_fmt") << (frame_fmt == QLatin1String(".gif") ? QLatin1String("rgb24") : QLatin1String("rgb32")); + args << QLatin1String("-s") << QString::fromAscii("%1x%2").arg(canvas->width()).arg(canvas->height()); + args << QLatin1String("-i") << QLatin1String("-"); + if (record_outsize.isValid()) { + args << QLatin1String("-s") << QString::fromAscii("%1x%2").arg(record_outsize.width()).arg(record_outsize.height()); + args << QLatin1String("-aspect") << QString::number(double(canvas->width())/canvas->height()); + } + args += record_args; + args << record_file; + proc->start(QLatin1String("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() == QLatin1String(".png")) { + if (record_file.contains(QLatin1Char('%'))) + framename = record_file; + else + framename = record_file.left(record_file.length()-4) + QLatin1String("%04d") + record_file.right(4); + png_output = true; + } else { + framename = QLatin1String("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==QLatin1String("ordered")) + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::OrderedDither).save(name); + else if (record_dither==QLatin1String("threshold")) + img->convertToFormat(QImage::Format_Indexed8,Qt::PreferDither|Qt::ThresholdDither).save(name); + else if (record_dither==QLatin1String("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(QLatin1String("%\\d*.")), QLatin1String("*")); + 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 << QLatin1String("-delay") << QString::number(period/10); + args << inputs; + args << record_file; + qDebug() << "Converting..." << record_file << "(this may take a while)"; + if (0!=QProcess::execute(QLatin1String("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() == QLatin1String(".gif")) { + qDebug() << "Compressing..." << record_file; + if (0!=QProcess::execute(QLatin1String("gifsicle"), QStringList() << QLatin1String("-O2") + << QLatin1String("-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; + close(); +} + +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 == QLatin1String(".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", QString()); + qmlRegisterUncreatableType<DeviceOrientation>("QtQuick", 1, 0, "Orientation", QString()); + registered = true; + } +} + +QT_END_NAMESPACE + +#include "qmlruntime.moc" diff --git a/tools/qml/qmlruntime.h b/tools/qml/qmlruntime.h new file mode 100644 index 00000000..1b5cb076 --- /dev/null +++ b/tools/qml/qmlruntime.h @@ -0,0 +1,204 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/recopts.ui b/tools/qml/recopts.ui new file mode 100644 index 00000000..ce2da307 --- /dev/null +++ b/tools/qml/recopts.ui @@ -0,0 +1,513 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>RecordingOptions</class> + <widget class="QDialog" name="RecordingOptions"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>316</width> + <height>436</height> + </rect> + </property> + <property name="windowTitle"> + <string>Video options</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>File:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="file"/> + </item> + <item> + <widget class="QToolButton" name="pickfile"> + <property name="text"> + <string>...</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Size</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <widget class="QRadioButton" name="sizeOriginal"> + <property name="text"> + <string/> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QRadioButton" name="sizeVGA"> + <property name="text"> + <string>VGA</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="size720p"> + <property name="text"> + <string>720p</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QRadioButton" name="sizeQVGA"> + <property name="text"> + <string>QVGA</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="3"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QRadioButton" name="sizeCustom"> + <property name="text"> + <string>Width:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sizeWidth"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Height:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="sizeHeight"> + <property name="minimum"> + <number>1</number> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="2"> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="rateOptions"> + <property name="title"> + <string>Rate</string> + </property> + <layout class="QGridLayout" name="gridLayout_4"> + <item row="0" column="0"> + <widget class="QRadioButton" name="hz60"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>60Hz</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="hz50"> + <property name="text"> + <string>50Hz</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QRadioButton" name="hz25"> + <property name="text"> + <string>25Hz</string> + </property> + </widget> + </item> + <item row="2" column="0" colspan="4"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <property name="spacing"> + <number>0</number> + </property> + <item> + <widget class="QRadioButton" name="hzCustom"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="hz"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>100</width> + <height>16777215</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Hz</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="2"> + <widget class="QRadioButton" name="hz24"> + <property name="text"> + <string>24Hz</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::MinimumExpanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer_5"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="ffmpegOptions"> + <property name="title"> + <string>Profile</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0" colspan="3"> + <widget class="QComboBox" name="profile"/> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QLineEdit" name="args"/> + </item> + <item row="1" column="2"> + <widget class="QToolButton" name="ffmpegHelp"> + <property name="text"> + <string>Help</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QLabel" name="warning"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>file</tabstop> + <tabstop>pickfile</tabstop> + <tabstop>sizeOriginal</tabstop> + <tabstop>sizeVGA</tabstop> + <tabstop>size720p</tabstop> + <tabstop>sizeQVGA</tabstop> + <tabstop>sizeCustom</tabstop> + <tabstop>sizeWidth</tabstop> + <tabstop>sizeHeight</tabstop> + <tabstop>hz60</tabstop> + <tabstop>hz25</tabstop> + <tabstop>hz50</tabstop> + <tabstop>hz24</tabstop> + <tabstop>hzCustom</tabstop> + <tabstop>hz</tabstop> + <tabstop>profile</tabstop> + <tabstop>args</tabstop> + <tabstop>ffmpegHelp</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>hzCustom</sender> + <signal>clicked()</signal> + <receiver>hz</receiver> + <slot>setFocus()</slot> + <hints> + <hint type="sourcelabel"> + <x>43</x> + <y>257</y> + </hint> + <hint type="destinationlabel"> + <x>129</x> + <y>262</y> + </hint> + </hints> + </connection> + <connection> + <sender>hz</sender> + <signal>textChanged(QString)</signal> + <receiver>hzCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>143</x> + <y>262</y> + </hint> + <hint type="destinationlabel"> + <x>43</x> + <y>257</y> + </hint> + </hints> + </connection> + <connection> + <sender>hz</sender> + <signal>selectionChanged()</signal> + <receiver>hzCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>143</x> + <y>262</y> + </hint> + <hint type="destinationlabel"> + <x>43</x> + <y>257</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>RecordingOptions</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>258</x> + <y>424</y> + </hint> + <hint type="destinationlabel"> + <x>60</x> + <y>219</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>RecordingOptions</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>258</x> + <y>424</y> + </hint> + <hint type="destinationlabel"> + <x>92</x> + <y>219</y> + </hint> + </hints> + </connection> + <connection> + <sender>profile</sender> + <signal>activated(int)</signal> + <receiver>RecordingOptions</receiver> + <slot>pickProfile(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>92</x> + <y>329</y> + </hint> + <hint type="destinationlabel"> + <x>48</x> + <y>194</y> + </hint> + </hints> + </connection> + <connection> + <sender>args</sender> + <signal>textEdited(QString)</signal> + <receiver>RecordingOptions</receiver> + <slot>storeCustomArgs(QString)</slot> + <hints> + <hint type="sourcelabel"> + <x>128</x> + <y>357</y> + </hint> + <hint type="destinationlabel"> + <x>102</x> + <y>189</y> + </hint> + </hints> + </connection> + <connection> + <sender>sizeWidth</sender> + <signal>valueChanged(int)</signal> + <receiver>sizeCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>108</x> + <y>133</y> + </hint> + <hint type="destinationlabel"> + <x>48</x> + <y>133</y> + </hint> + </hints> + </connection> + <connection> + <sender>sizeHeight</sender> + <signal>valueChanged(int)</signal> + <receiver>sizeCustom</receiver> + <slot>toggle()</slot> + <hints> + <hint type="sourcelabel"> + <x>212</x> + <y>133</y> + </hint> + <hint type="destinationlabel"> + <x>64</x> + <y>129</y> + </hint> + </hints> + </connection> + </connections> + <slots> + <signal>filePicked(QString)</signal> + <signal>argumentsPicked(QString)</signal> + <slot>pickFile()</slot> + <slot>pickProfile(int)</slot> + <slot>storeCustomArgs(QString)</slot> + </slots> +</ui> diff --git a/tools/qml/recopts_maemo5.ui b/tools/qml/recopts_maemo5.ui new file mode 100644 index 00000000..3bb5ecab --- /dev/null +++ b/tools/qml/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/qml/startup/Logo.qml b/tools/qml/startup/Logo.qml new file mode 100644 index 00000000..9d088eef --- /dev/null +++ b/tools/qml/startup/Logo.qml @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/startup/qt-back.png b/tools/qml/startup/qt-back.png Binary files differnew file mode 100644 index 00000000..077215f8 --- /dev/null +++ b/tools/qml/startup/qt-back.png diff --git a/tools/qml/startup/qt-blue.jpg b/tools/qml/startup/qt-blue.jpg Binary files differnew file mode 100644 index 00000000..b2048964 --- /dev/null +++ b/tools/qml/startup/qt-blue.jpg diff --git a/tools/qml/startup/qt-front.png b/tools/qml/startup/qt-front.png Binary files differnew file mode 100644 index 00000000..dbfb43e3 --- /dev/null +++ b/tools/qml/startup/qt-front.png diff --git a/tools/qml/startup/qt-sketch.jpg b/tools/qml/startup/qt-sketch.jpg Binary files differnew file mode 100644 index 00000000..1ede6f07 --- /dev/null +++ b/tools/qml/startup/qt-sketch.jpg diff --git a/tools/qml/startup/qt-text.png b/tools/qml/startup/qt-text.png Binary files differnew file mode 100644 index 00000000..d44995c9 --- /dev/null +++ b/tools/qml/startup/qt-text.png diff --git a/tools/qml/startup/quick-blur.png b/tools/qml/startup/quick-blur.png Binary files differnew file mode 100644 index 00000000..29ec2433 --- /dev/null +++ b/tools/qml/startup/quick-blur.png diff --git a/tools/qml/startup/quick-regular.png b/tools/qml/startup/quick-regular.png Binary files differnew file mode 100644 index 00000000..38321cbf --- /dev/null +++ b/tools/qml/startup/quick-regular.png diff --git a/tools/qml/startup/shadow.png b/tools/qml/startup/shadow.png Binary files differnew file mode 100644 index 00000000..44f92fee --- /dev/null +++ b/tools/qml/startup/shadow.png diff --git a/tools/qml/startup/startup.qml b/tools/qml/startup/startup.qml new file mode 100644 index 00000000..d91a8f69 --- /dev/null +++ b/tools/qml/startup/startup.qml @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $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/qml/startup/startup.qrc b/tools/qml/startup/startup.qrc new file mode 100644 index 00000000..52e67050 --- /dev/null +++ b/tools/qml/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/qml/startup/white-star.png b/tools/qml/startup/white-star.png Binary files differnew file mode 100644 index 00000000..f467c948 --- /dev/null +++ b/tools/qml/startup/white-star.png diff --git a/tools/qml/texteditautoresizer_maemo5.h b/tools/qml/texteditautoresizer_maemo5.h new file mode 100644 index 00000000..90a61f48 --- /dev/null +++ b/tools/qml/texteditautoresizer_maemo5.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2012 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/qplaintextedit.h> +#include <QtGui/qtextedit.h> +#include <QtGui/qabstractkineticscroller.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()); + + if (QAbstractKineticScroller *scroller = area->property("kineticScroller").value<QAbstractKineticScroller *>()) { + scroller->ensureVisible(scrollto, margin.x(), margin.y()); + } else { + area->ensureVisible(scrollto.x(), scrollto.y(), margin.x(), margin.y()); + } + } +} + +#endif |