Add QQmlApplicationEngine
authorAlan Alpert <aalpert@rim.com>
Fri, 21 Dec 2012 21:37:30 +0000 (13:37 -0800)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Wed, 20 Mar 2013 05:48:30 +0000 (06:48 +0100)
This helper class exposes QML application functionality that QML-only
applications want to have, but QML-using applications may not.

Change-Id: If91c3f55ffa2a4aecdd9d6cc62f6ad09fd35b0dd
Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com>
17 files changed:
src/qml/qml/qml.pri
src/qml/qml/qqmlapplicationengine.cpp [new file with mode: 0644]
src/qml/qml/qqmlapplicationengine.h [new file with mode: 0644]
src/qml/qml/qqmlapplicationengine_p.h [new file with mode: 0644]
src/qml/qml/qqmlengine.cpp
src/qml/qml/qqmlengine.h
tests/auto/qml/qml.pro
tests/auto/qml/qqmlapplicationengine/data/TestItem.qml [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/data/applicationTest.qml [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/data/basicTest.qml [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/qqmlapplicationengine.pro [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/testapp/main.cpp [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/testapp/main.qml [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/testapp/main.qrc [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/testapp/testapp.pro [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp [new file with mode: 0644]
tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.pro [new file with mode: 0644]

index a660abe..aafc50d 100644 (file)
@@ -50,7 +50,8 @@ SOURCES += \
     $$PWD/qqmlbundle.cpp \
     $$PWD/qqmlmemoryprofiler.cpp \
     $$PWD/qqmlplatform.cpp \
-    $$PWD/qqmlbinding.cpp
+    $$PWD/qqmlbinding.cpp \
+    $$PWD/qqmlapplicationengine.cpp
 
 HEADERS += \
     $$PWD/qqmlglobal_p.h \
@@ -121,7 +122,9 @@ HEADERS += \
     $$PWD/qqmlmemoryprofiler_p.h \
     $$PWD/qqmlplatform_p.h \
     $$PWD/qqmlbinding_p.h \
-    $$PWD/qqmlextensionplugin_p.h
+    $$PWD/qqmlextensionplugin_p.h \
+    $$PWD/qqmlapplicationengine_p.h \
+    $$PWD/qqmlapplicationengine.h
 
 
 include(parser/parser.pri)
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp
new file mode 100644 (file)
index 0000000..7dc2c77
--- /dev/null
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QTranslator>
+#include <QQmlComponent>
+#include "qqmlapplicationengine.h"
+#include "qqmlapplicationengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QQmlApplicationEnginePrivate::QQmlApplicationEnginePrivate(QQmlEngine *e)
+    : QQmlEnginePrivate(e)
+{
+}
+
+QQmlApplicationEnginePrivate::~QQmlApplicationEnginePrivate()
+{
+    qDeleteAll(objects);
+#ifndef QT_NO_TRANSLATIONS
+    qDeleteAll(translators);
+#endif
+}
+
+void QQmlApplicationEnginePrivate::init()
+{
+    Q_Q(QQmlApplicationEngine);
+    q->connect(&statusMapper, SIGNAL(mapped(QObject*)),
+            q, SLOT(_q_finishLoad(QObject*)));
+    q->connect(q, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
+#ifndef QT_NO_TRANSLATIONS
+    QTranslator* qtTranslator = new QTranslator;
+    if (qtTranslator->load(QLatin1String("qt_") + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
+        QCoreApplication::installTranslator(qtTranslator);
+    translators << qtTranslator;
+#endif
+}
+
+void QQmlApplicationEnginePrivate::loadTranslations(const QUrl &rootFile)
+{
+#ifndef QT_NO_TRANSLATIONS
+    if (rootFile.scheme() != QLatin1String("file") && rootFile.scheme() != QLatin1String("qrc"))
+        return;
+
+    QFileInfo fi(rootFile.toLocalFile());
+
+    QTranslator *translator = new QTranslator;
+    if (translator->load(QLatin1String("qml_") + QLocale::system().name(), fi.path() + QLatin1String("/i18n"))) {
+        QCoreApplication::installTranslator(translator);
+        translators << translator;
+    } else {
+        delete translator;
+    }
+#endif
+}
+
+void QQmlApplicationEnginePrivate::startLoad(const QUrl &url, const QByteArray &data, bool dataFlag)
+{
+    Q_Q(QQmlApplicationEngine);
+
+    loadTranslations(url); //Translations must be loaded before the QML file is
+    QQmlComponent *c = new QQmlComponent(q, q);
+
+    if (dataFlag)
+        c->setData(data,url);
+    else
+        c->loadUrl(url);
+
+    if (!c->isLoading()) {
+        _q_finishLoad(c);
+        return;
+    }
+    statusMapper.setMapping(c, c);
+    q->connect(c, SIGNAL(statusChanged(QQmlComponent::Status)),
+        &statusMapper, SLOT(map()));
+}
+
+void QQmlApplicationEnginePrivate::_q_finishLoad(QObject *o)
+{
+    Q_Q(QQmlApplicationEngine);
+    QQmlComponent *c = qobject_cast<QQmlComponent *>(o);
+    if (!c)
+        return;
+    switch (c->status()) {
+    case QQmlComponent::Error:
+        qWarning() << "QQmlApplicationEngine failed to load component";
+        qWarning() << qPrintable(c->errorString());
+        q->objectCreated(0, c->url());
+        break;
+    case QQmlComponent::Ready:
+        objects << c->create();
+        q->objectCreated(objects.last(), c->url());
+        break;
+    case QQmlComponent::Loading:
+    case QQmlComponent::Null:
+        return; //These cases just wait for the next status update
+    }
+    delete c;
+}
+
+/*!
+  \class QQmlApplicationEngine
+  \since 5.1
+  \inmodule QtQml
+  \brief QQmlApplicationEngine provides a convenient way to load an application from a single QML file.
+
+  This class combines a QQmlEngine and QQmlComponent to provide a convenient way to load a single QML file. It also exposes some central application functionality to QML, which a C++/QML hybrid application would normally control from C++.
+
+  It can be used like so:
+
+  \code
+  #include <QGuiApplication>
+  #include <QQmlApplicationEngine>
+
+  int main(int argc, char *argv[])
+  {
+      QGuiApplication app(argc, argv);
+      QQmlApplicationEngine engine("main.qml");
+      return app.exec();
+  }
+  \endcode
+
+  You can also use QCoreApplication with QQmlApplicationEngine, if you are not using any QML modules which require a QGuiApplication (such as QtQuick).
+
+  List of configuration changes from a default QQmlEngine:
+
+  \list
+  \li Connecting Qt.quit() to QCoreApplication::quit()
+  \li Automatically loads translation files from an i18n directory adjacent to the main QML file.
+  \endlist
+
+  The engine behavior can be further tweaked by using the inherited methods from QQmlEngine.
+*/
+
+/*!
+  \fn QQmlApplicationEngine::objectCreated(QObject *object, const QUrl &url)
+
+  This signal is emitted when an object finishes loading. If loading was successful, \a object contains a pointer to the loaded object.
+  Otherwise the pointer is NULL. The \a url loaded is also provided, note that if a QString file path was initially passed to the
+  QQmlApplicationEngine, this url will be the equivalent of QUrl::fromLocalFile(filePath).
+*/
+
+/*!
+  Create a new QQmlApplicationEngine with the given \a parent. You will have to call load() later in
+  order to load a QML file.
+*/
+QQmlApplicationEngine::QQmlApplicationEngine(QObject *parent)
+: QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent)
+{
+    Q_D(QQmlApplicationEngine);
+    d->init();
+}
+
+/*!
+  Create a new QQmlApplicationEngine and loads the QML file at the given \a url.
+  This is provided as a convenience,  and is the same as using the empty constructor and calling load afterwards.
+*/
+QQmlApplicationEngine::QQmlApplicationEngine(const QUrl &url, QObject *parent)
+    : QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent)
+{
+    Q_D(QQmlApplicationEngine);
+    d->init();
+    load(url);
+}
+
+/*!
+  Create a new QQmlApplicationEngine and loads the QML file at the given
+  \a filePath, which must be a local file path. If a relative path is
+  given then it will be interpreted as relative to the working directory of the
+  application.
+
+  This is provided as a convenience, and is the same as using the empty constructor and calling load afterwards.
+*/
+QQmlApplicationEngine::QQmlApplicationEngine(const QString &filePath, QObject *parent)
+    : QQmlEngine(*(new QQmlApplicationEnginePrivate(this)), parent)
+{
+    Q_D(QQmlApplicationEngine);
+    d->init();
+    load(QUrl::fromLocalFile(filePath));
+}
+
+/*!
+  Destroys the QQmlApplicationEngine and all QML objects it loaded.
+*/
+QQmlApplicationEngine::~QQmlApplicationEngine()
+{
+    //Instantiated root objects cleaned up in private class
+}
+
+/*!
+  Loads the root QML file located at \a url. The object tree defined by the file
+  is created immediately for local file urls. Remote urls are loaded asynchronously,
+  listen to the objectCreated signal to determine when the object
+  tree is ready.
+
+  If an error occurs, error messages are printed with qWarning.
+*/
+void QQmlApplicationEngine::load(const QUrl &url)
+{
+    Q_D(QQmlApplicationEngine);
+    d->startLoad(url);
+}
+
+/*!
+  Loads the root QML file located at \a filePath. \a filePath must be a path to
+  a local file. If \a filePath is a relative path, it is taken as relative to
+  the application's working directory. The object tree defined by the file is
+  instantiated immediately.
+
+  If an error occurs, error messages are printed with qWarning.
+*/
+void QQmlApplicationEngine::load(const QString &filePath)
+{
+    Q_D(QQmlApplicationEngine);
+    d->startLoad(QUrl::fromLocalFile(filePath));
+}
+
+/*!
+  Loads the QML given in \a data. The object tree defined by \a data is
+  instantiated immediately.
+
+  If a \a url is specified it is used as the base url of the component. This affects
+  relative paths within the data and error messages.
+
+  If an error occurs, error messages are printed with qWarning.
+*/
+void QQmlApplicationEngine::loadData(const QByteArray &data, const QUrl &url)
+{
+    Q_D(QQmlApplicationEngine);
+    d->startLoad(url, data, true);
+}
+
+/*!
+  Returns a list of all the root objects instantiated by the
+  QQmlApplicationEngine. This will only contain objects loaded via load() or a
+  convenience constructor.
+*/
+
+QList<QObject *> QQmlApplicationEngine::rootObjects()
+{
+    Q_D(QQmlApplicationEngine);
+    return d->objects;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qqmlapplicationengine.cpp"
diff --git a/src/qml/qml/qqmlapplicationengine.h b/src/qml/qml/qqmlapplicationengine.h
new file mode 100644 (file)
index 0000000..b5de998
--- /dev/null
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLAPPLICATIONENGINE_H
+#define QQMLAPPLICATIONENGINE_H
+
+#include <QtQml/qqmlengine.h>
+
+#include <QtCore/qurl.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlApplicationEnginePrivate;
+class Q_QML_EXPORT QQmlApplicationEngine : public QQmlEngine
+{
+    Q_OBJECT
+public:
+    QQmlApplicationEngine(QObject *parent=0);
+    QQmlApplicationEngine(const QUrl &url, QObject *parent=0);
+    QQmlApplicationEngine(const QString &filePath, QObject *parent=0);
+    ~QQmlApplicationEngine();
+
+    QList<QObject*> rootObjects();
+public Q_SLOTS:
+    void load(const QUrl &url);
+    void load(const QString &filePath);
+    void loadData(const QByteArray &data, const QUrl &url = QUrl());
+
+Q_SIGNALS:
+    void objectCreated(QObject *object, const QUrl &url);
+
+private:
+    Q_DISABLE_COPY(QQmlApplicationEngine)
+    Q_DECLARE_PRIVATE(QQmlApplicationEngine)
+    Q_PRIVATE_SLOT(d_func(), void _q_finishLoad(QObject*))
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/qml/qml/qqmlapplicationengine_p.h b/src/qml/qml/qqmlapplicationengine_p.h
new file mode 100644 (file)
index 0000000..db144af
--- /dev/null
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtQml module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQMLAPPLICATIONENGINE_P_H
+#define QQMLAPPLICATIONENGINE_P_H
+
+#include "qqmlapplicationengine.h"
+#include "qqmlengine_p.h"
+#include <QSignalMapper>
+#include <QCoreApplication>
+#include <QFileInfo>
+#include <QLibraryInfo>
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QTranslator;
+class Q_QML_PRIVATE_EXPORT QQmlApplicationEnginePrivate : public QQmlEnginePrivate
+{
+    Q_DECLARE_PUBLIC(QQmlApplicationEngine)
+public:
+    QQmlApplicationEnginePrivate(QQmlEngine *e);
+    ~QQmlApplicationEnginePrivate();
+    void init();
+
+    void startLoad(const QUrl &url, const QByteArray &data = QByteArray(), bool dataFlag = false);
+    void loadTranslations(const QUrl &rootFile);
+    void _q_finishLoad(QObject *component);
+    QList<QObject *> objects;
+    QSignalMapper statusMapper;
+    QObject *appObj;
+
+#ifndef QT_NO_TRANSLATIONS
+    QList<QTranslator *> translators;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
index 23d1cf7..96d0192 100644 (file)
@@ -814,6 +814,16 @@ QQmlEngine::QQmlEngine(QObject *parent)
 }
 
 /*!
+* \internal
+*/
+QQmlEngine::QQmlEngine(QQmlEnginePrivate &dd, QObject *parent)
+: QJSEngine(dd, parent)
+{
+    Q_D(QQmlEngine);
+    d->init();
+}
+
+/*!
   Destroys the QQmlEngine.
 
   Any QQmlContext's created on this engine will be
index 9433fcb..45826a4 100644 (file)
@@ -142,6 +142,7 @@ public:
     static void setObjectOwnership(QObject *, ObjectOwnership);
     static ObjectOwnership objectOwnership(QObject *);
 protected:
+    QQmlEngine(QQmlEnginePrivate &dd, QObject *p);
     virtual bool event(QEvent *);
 
 Q_SIGNALS:
index ede7689..584533c 100644 (file)
@@ -24,7 +24,8 @@ PUBLICTESTS += \
     qqmltranslation \
     qqmlxmlhttprequest \
     qtqmlmodules \
-    qquickfolderlistmodel
+    qquickfolderlistmodel \
+    qqmlapplicationengine
 
 PRIVATETESTS += \
     animation \
diff --git a/tests/auto/qml/qqmlapplicationengine/data/TestItem.qml b/tests/auto/qml/qqmlapplicationengine/data/TestItem.qml
new file mode 100644 (file)
index 0000000..e879577
--- /dev/null
@@ -0,0 +1,4 @@
+import QtQml 2.0
+
+QtObject {
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/data/applicationTest.qml b/tests/auto/qml/qqmlapplicationengine/data/applicationTest.qml
new file mode 100644 (file)
index 0000000..2a1b4fb
--- /dev/null
@@ -0,0 +1,14 @@
+import QtQml 2.0
+
+QtObject {
+    property string originalName
+    property string originalVersion
+    property string currentName: Qt.application.name
+    property string currentVersion: Qt.application.version
+    Component.onCompleted: {
+        originalName = Qt.application.name
+        originalVersion = Qt.application.version
+        Qt.application.name = "Test B"
+        Qt.application.version = "0.0B"
+    }
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/data/basicTest.qml b/tests/auto/qml/qqmlapplicationengine/data/basicTest.qml
new file mode 100644 (file)
index 0000000..837835f
--- /dev/null
@@ -0,0 +1,5 @@
+import QtQml 2.0
+
+QtObject {
+    property bool success: true
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/qqmlapplicationengine.pro b/tests/auto/qml/qqmlapplicationengine/qqmlapplicationengine.pro
new file mode 100644 (file)
index 0000000..4a2dde7
--- /dev/null
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = tst_qqmlapplicationengine.pro \
+          testapp
diff --git a/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp b/tests/auto/qml/qqmlapplicationengine/testapp/main.cpp
new file mode 100644 (file)
index 0000000..fe64bb3
--- /dev/null
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QCoreApplication>
+#include <QQmlApplicationEngine>
+
+int main (int argc, char *argv[])
+{
+    QCoreApplication app(argc, argv);
+    QQmlApplicationEngine e(QUrl("qrc:///main.qml"));
+    return app.exec();
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/testapp/main.qml b/tests/auto/qml/qqmlapplicationengine/testapp/main.qml
new file mode 100644 (file)
index 0000000..c75485a
--- /dev/null
@@ -0,0 +1,11 @@
+import QtQml 2.0
+
+QtObject {
+    id: root
+    property Timer t: Timer { interval: 1; running: true; onTriggered: Qt.quit(); }
+    property Connections c: Connections {
+        target: Qt.application
+        onAboutToQuit: console.log("End");
+    }
+    Component.onCompleted: console.log("Start: " + Qt.application.arguments[1]);
+}
diff --git a/tests/auto/qml/qqmlapplicationengine/testapp/main.qrc b/tests/auto/qml/qqmlapplicationengine/testapp/main.qrc
new file mode 100644 (file)
index 0000000..5f6483a
--- /dev/null
@@ -0,0 +1,5 @@
+<RCC>
+    <qresource prefix="/">
+        <file>main.qml</file>
+    </qresource>
+</RCC>
diff --git a/tests/auto/qml/qqmlapplicationengine/testapp/testapp.pro b/tests/auto/qml/qqmlapplicationengine/testapp/testapp.pro
new file mode 100644 (file)
index 0000000..34d2718
--- /dev/null
@@ -0,0 +1,11 @@
+TEMPLATE = app
+TARGET = testapp
+DESTDIR = ./
+CONFIG -= app_bundle
+CONFIG += console
+
+QT += qml
+
+# Input
+SOURCES += main.cpp
+RESOURCES += main.qrc
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.cpp
new file mode 100644 (file)
index 0000000..1c11fcb
--- /dev/null
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Research In Motion.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../shared/util.h"
+#include <QQmlApplicationEngine>
+#include <QSignalSpy>
+#include <QProcess>
+#include <QDebug>
+
+class tst_qqmlapplicationengine : public QQmlDataTest
+{
+    Q_OBJECT
+public:
+    tst_qqmlapplicationengine() {}
+
+
+private slots:
+    void initTestCase();
+    void basicLoading();
+    void application();
+    void applicationProperties();
+private:
+    QString buildDir;
+    QString srcDir;
+};
+
+void tst_qqmlapplicationengine::initTestCase()
+{
+    buildDir = QDir::currentPath();
+    QQmlDataTest::initTestCase(); //Changes current path to src dir
+    srcDir = QDir::currentPath();
+}
+
+void tst_qqmlapplicationengine::basicLoading()
+{
+    int size = 0;
+
+    QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("basicTest.qml"));
+    QCOMPARE(test->rootObjects().size(), ++size);
+    QVERIFY(test->rootObjects()[size -1]);
+    QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
+
+    QSignalSpy objectCreated(test, SIGNAL(objectCreated(QObject*,const QUrl&)));
+    test->load(testFileUrl("basicTest.qml"));
+    QCOMPARE(objectCreated.count(), size);//one less than rootObjects().size() because we missed the first one
+    QCOMPARE(test->rootObjects().size(), ++size);
+    QVERIFY(test->rootObjects()[size -1]);
+    QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
+
+    QByteArray testQml("import QtQml 2.0; QtObject{property bool success: true; property TestItem t: TestItem{}}");
+    test->loadData(testQml, testFileUrl("dynamicTest.qml"));
+    QCOMPARE(objectCreated.count(), size);
+    QCOMPARE(test->rootObjects().size(), ++size);
+    QVERIFY(test->rootObjects()[size -1]);
+    QVERIFY(test->rootObjects()[size -1]->property("success").toBool());
+
+    delete test;
+}
+
+void tst_qqmlapplicationengine::application()
+{
+    /* This test batches together some tests about running an external application
+       written with QQmlApplicationEngine. The application tests the following functionality
+       which is easier to do by watching a separate process:
+       -Loads relative paths from the working directory
+       -quits when quit is called
+       -emits aboutToQuit after quit is called
+       -has access to application command line arguments
+
+       Note that checking the output means that on builds with extra debugging, this might fail with a false positive.
+       Also the testapp is automatically built and installed in shadow builds, so it does NOT use testData
+   */
+    QDir::setCurrent(buildDir);
+    QProcess *testProcess = new QProcess(this);
+    QTest::ignoreMessage(QtWarningMsg, "Don't know how to handle 'QProcess::ExitStatus', use qRegisterMetaType to register it.");
+    QSignalSpy processFinished(testProcess, SIGNAL(finished(int,QProcess::ExitStatus)));
+    QStringList args;
+    args << QLatin1String("testData");
+    testProcess->start(QLatin1String("testapp/testapp"), args);
+    QTRY_VERIFY(processFinished.count());//Application should immediately exit
+    QCOMPARE(processFinished[0][0].toInt(), 0);
+    QByteArray test_stdout = testProcess->readAllStandardOutput();
+    QByteArray test_stderr = testProcess->readAllStandardError();
+    QByteArray test_stderr_target("Start: testData\nEnd\n");
+#ifdef Q_OS_WIN
+    test_stderr_target.replace('\n', QByteArray("\r\n"));
+#endif
+    QCOMPARE(test_stdout, QByteArray(""));
+    QCOMPARE(test_stderr, test_stderr_target);
+    delete testProcess;
+    QDir::setCurrent(srcDir);
+}
+
+void tst_qqmlapplicationengine::applicationProperties()
+{
+    QCoreApplication* coreApp = QCoreApplication::instance();
+    QString originalName = coreApp->applicationName();
+    QString originalVersion = coreApp->applicationVersion();
+    QString firstName = QLatin1String("Test A");
+    QString firstVersion = QLatin1String("0.0A");
+    QString secondName = QLatin1String("Test B");
+    QString secondVersion = QLatin1String("0.0B");
+
+    coreApp->setApplicationName(firstName);
+    coreApp->setApplicationVersion(firstVersion);
+
+    QQmlApplicationEngine *test = new QQmlApplicationEngine(testFileUrl("applicationTest.qml"));
+    QObject* root = test->rootObjects().at(0);
+    QVERIFY(root);
+    QCOMPARE(root->property("originalName").toString(), firstName);
+    QCOMPARE(root->property("originalVersion").toString(), firstVersion);
+    QCOMPARE(root->property("currentName").toString(), secondName);
+    QCOMPARE(root->property("currentVersion").toString(), secondVersion);
+    QCOMPARE(coreApp->applicationName(), secondName);
+    QCOMPARE(coreApp->applicationVersion(), secondVersion);
+
+    coreApp->setApplicationName(originalName);
+    coreApp->setApplicationVersion(originalVersion);
+    delete test;
+}
+
+QTEST_MAIN(tst_qqmlapplicationengine)
+
+#include "tst_qqmlapplicationengine.moc"
diff --git a/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.pro b/tests/auto/qml/qqmlapplicationengine/tst_qqmlapplicationengine.pro
new file mode 100644 (file)
index 0000000..18c38a8
--- /dev/null
@@ -0,0 +1,10 @@
+CONFIG += testcase
+TARGET = tst_qqmlapplicationengine
+macx:CONFIG -= app_bundle
+
+
+SOURCES += tst_qqmlapplicationengine.cpp
+TESTDATA += data/*
+
+include (../../shared/util.pri)
+QT += core-private gui-private qml-private network testlib