Introduce a new constructor to QQuickView
authorCharles Yin <charles.yin@nokia.com>
Thu, 3 May 2012 01:36:36 +0000 (11:36 +1000)
committerQt by Nokia <qt-info@nokia.com>
Wed, 23 May 2012 03:28:54 +0000 (05:28 +0200)
Make it possible let QQuickView use an existing qml engine
and multiple QQuickView objects can share one QQmlEngine instance.

Change-Id: I035d1c15155be22f1131b504c40cf4ffb5da0f45
Reviewed-by: Glenn Watson <glenn.watson@nokia.com>
src/quick/items/qquickview.cpp
src/quick/items/qquickview.h
src/quick/items/qquickview_p.h
tests/auto/quick/qquickview/tst_qquickview.cpp

index 03a8e6e..b6b6f41 100644 (file)
 #include <private/qqmlengine_p.h>
 #include <QtCore/qbasictimer.h>
 
-
 QT_BEGIN_NAMESPACE
 
-void QQuickViewPrivate::init()
+void QQuickViewPrivate::init(QQmlEngine* e)
 {
     Q_Q(QQuickView);
 
-    engine.setIncubationController(q->incubationController());
+    engine = e;
+
+    if (engine.isNull())
+        engine = new QQmlEngine(q);
+
+    if (!engine.data()->incubationController())
+        engine.data()->setIncubationController(q->incubationController());
 
     if (QQmlDebugService::isDebuggingEnabled())
         QQmlInspectorService::instance()->addView(q);
@@ -83,6 +88,11 @@ QQuickViewPrivate::~QQuickViewPrivate()
 void QQuickViewPrivate::execute()
 {
     Q_Q(QQuickView);
+    if (!engine) {
+        qWarning() << "QQuickView: invalid qml engine.";
+        return;
+    }
+
     if (root) {
         delete root;
         root = 0;
@@ -92,8 +102,8 @@ void QQuickViewPrivate::execute()
         component = 0;
     }
     if (!source.isEmpty()) {
-        QML_MEMORY_SCOPE_URL(engine.baseUrl().resolved(source));
-        component = new QQmlComponent(&engine, source, q);
+        QML_MEMORY_SCOPE_URL(engine.data()->baseUrl().resolved(source));
+        component = new QQmlComponent(engine.data(), source, q);
         if (!component->isLoading()) {
             q->continueExecute();
         } else {
@@ -153,9 +163,12 @@ void QQuickViewPrivate::itemGeometryChanged(QQuickItem *resizeItem, const QRectF
 */
 
 /*!
-  \fn QQuickView::QQuickView(QWindow *parent)
+  \fn QQuickView::QQuickView(QWindow *parent, Qt::WindowFlags f)
 
-  Constructs a QQuickView with the given \a parent.
+  Constructs a QQuickView with the given \a parent and window flags \a f.
+  The default value of \a parent is 0, default window flags \a f is Qt::Window.
+
+  \sa Qt::WindowFlags
 */
 QQuickView::QQuickView(QWindow *parent, Qt::WindowFlags f)
 : QQuickCanvas(*(new QQuickViewPrivate), parent)
@@ -165,9 +178,12 @@ QQuickView::QQuickView(QWindow *parent, Qt::WindowFlags f)
 }
 
 /*!
-  \fn QQuickView::QQuickView(const QUrl &source, QWidget *parent)
+  \fn QQuickView::QQuickView(const QUrl &source, QWidget *parent, Qt::WindowFlags f)
+
+  Constructs a QQuickView with the given QML \a source, \a parent and a window flags \a f.
+  The default value of \a parent is 0, default window flags \a f is Qt::Window.
 
-  Constructs a QQuickView with the given QML \a source and \a parent.
+  \sa Qt::WindowFlags
 */
 QQuickView::QQuickView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
 : QQuickCanvas(*(new QQuickViewPrivate), parent)
@@ -177,6 +193,26 @@ QQuickView::QQuickView(const QUrl &source, QWindow *parent, Qt::WindowFlags f)
     setSource(source);
 }
 
+/*!
+  \fn QQuickView::QQuickView(QQmlEngine* engine, QWindow *parent, Qt::WindowFlags f)
+
+  Constructs a QQuickView with the given QML \a engine, \a parent and a window flags \a f.
+  The default value of \a parent is 0, default window flags \a f is Qt::Window.
+
+  Note: In this case, the QQuickView does not own the given \a engine object;
+  it is the caller's responsibility to destroy the engine. If the \a engine is deleted
+  before the view \a status() will return \a QQuickView::Error.
+
+  \sa Status, status(), errors(), Qt::WindowFlags
+*/
+QQuickView::QQuickView(QQmlEngine* engine, QWindow *parent, Qt::WindowFlags f)
+    : QQuickCanvas(*(new QQuickViewPrivate), parent)
+{
+    Q_ASSERT(engine);
+    setWindowFlags(f);
+    d_func()->init(engine);
+}
+
 QQuickView::~QQuickView()
 {
 }
@@ -224,7 +260,7 @@ QUrl QQuickView::source() const
 QQmlEngine* QQuickView::engine() const
 {
     Q_D(const QQuickView);
-    return const_cast<QQmlEngine *>(&d->engine);
+    return d->engine ? const_cast<QQmlEngine *>(d->engine.data()) : 0;
 }
 
 /*!
@@ -237,7 +273,7 @@ QQmlEngine* QQuickView::engine() const
 QQmlContext* QQuickView::rootContext() const
 {
     Q_D(const QQuickView);
-    return d->engine.rootContext();
+    return d->engine ? d->engine.data()->rootContext() : 0;
 }
 
 /*!
@@ -267,6 +303,9 @@ QQmlContext* QQuickView::rootContext() const
 QQuickView::Status QQuickView::status() const
 {
     Q_D(const QQuickView);
+    if (!d->engine)
+        return QQuickView::Error;
+
     if (!d->component)
         return QQuickView::Null;
 
@@ -280,9 +319,18 @@ QQuickView::Status QQuickView::status() const
 QList<QQmlError> QQuickView::errors() const
 {
     Q_D(const QQuickView);
+    QList<QQmlError> errs;
+
     if (d->component)
-        return d->component->errors();
-    return QList<QQmlError>();
+        errs = d->component->errors();
+
+    if (!d->engine) {
+        QQmlError error;
+        error.setDescription(QLatin1String("QQuickView: invalid qml engine."));
+        errs << error;
+    }
+
+    return errs;
 }
 
 /*!
index 2143a80..6ef3531 100644 (file)
@@ -65,6 +65,7 @@ class Q_QUICK_EXPORT QQuickView : public QQuickCanvas
     Q_ENUMS(ResizeMode Status)
 public:
     explicit QQuickView(QWindow *parent = 0, Qt::WindowFlags f = Qt::Window);
+    QQuickView(QQmlEngine* engine, QWindow *parent, Qt::WindowFlags f = Qt::Window);
     QQuickView(const QUrl &source, QWindow *parent = 0, Qt::WindowFlags f = Qt::Window);
     virtual ~QQuickView();
 
index 9b0e26e..00f7640 100644 (file)
@@ -48,6 +48,8 @@
 #include <QtCore/qelapsedtimer.h>
 #include <QtCore/qtimer.h>
 #include <QtCore/qpointer.h>
+#include <QtCore/QWeakPointer>
+
 #include <QtQml/qqmlengine.h>
 #include "qquickcanvas_p.h"
 
@@ -79,7 +81,7 @@ public:
     void updateSize();
     void setRootObject(QObject *);
 
-    void init();
+    void init(QQmlEngine* e = 0);
 
     QSize rootObjectSize() const;
 
@@ -87,7 +89,7 @@ public:
 
     QUrl source;
 
-    QQmlEngine engine;
+    QWeakPointer<QQmlEngine> engine;
     QQmlComponent *component;
     QBasicTimer resizetimer;
 
index e5e8a83..cb2f5c6 100644 (file)
@@ -47,6 +47,7 @@
 #include "../../shared/util.h"
 #include <QtGui/QWindow>
 #include <QtCore/QDebug>
+#include <QtQml/qqmlengine.h>
 
 class tst_QQuickView : public QQmlDataTest
 {
@@ -57,6 +58,7 @@ public:
 private slots:
     void resizemodeitem();
     void errors();
+    void engine();
 };
 
 
@@ -201,6 +203,42 @@ void tst_QQuickView::errors()
     delete canvas;
 }
 
+void tst_QQuickView::engine()
+{
+    QQmlEngine *engine = new QQmlEngine;
+    QVERIFY(!engine->incubationController());
+
+    QQuickView *canvas = new QQuickView(engine, 0);
+    QVERIFY(canvas);
+    QVERIFY(engine->incubationController() == canvas->incubationController());
+
+    QQuickView *canvas2 = new QQuickView(engine, 0);
+    QVERIFY(canvas);
+    QVERIFY(engine->incubationController() == canvas->incubationController());
+    delete canvas;
+    QVERIFY(!engine->incubationController());
+
+    engine->setIncubationController(canvas2->incubationController());
+    QVERIFY(engine->incubationController() == canvas2->incubationController());
+    delete canvas2;
+    QVERIFY(!engine->incubationController());
+
+    QQuickView *canvas3 = new QQuickView;
+    QQuickView *canvas4 = new QQuickView(canvas3->engine(), 0);
+
+    QVERIFY(canvas3->engine());
+    QVERIFY(canvas4->engine());
+    QCOMPARE(canvas3->engine(), canvas4->engine());
+    delete canvas3;
+    QVERIFY(!canvas4->engine());
+    QTest::ignoreMessage(QtWarningMsg, "QQuickView: invalid qml engine. ");
+    canvas4->setSource(QUrl());
+
+    QCOMPARE(canvas4->status(), QQuickView::Error);
+    QVERIFY(!canvas4->errors().isEmpty());
+    QCOMPARE(canvas4->errors().back().description(), QLatin1String("QQuickView: invalid qml engine."));
+    delete canvas4;
+}
 
 QTEST_MAIN(tst_QQuickView)