~loic.molinari/+junk/qtdeclarative-shadereffectsource-changes

« back to all changes in this revision

Viewing changes to tests/auto/quick/qquickloader/tst_qquickloader.cpp

  • Committer: Loïc Molinari
  • Date: 2012-04-21 17:59:51 UTC
  • Revision ID: loic.molinari@canonical.com-20120421175951-bqx68caaf5zrp76l
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/
 
5
**
 
6
** This file is part of the test suite of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** GNU Lesser General Public License Usage
 
10
** This file may be used under the terms of the GNU Lesser General Public
 
11
** License version 2.1 as published by the Free Software Foundation and
 
12
** appearing in the file LICENSE.LGPL included in the packaging of this
 
13
** file. Please review the following information to ensure the GNU Lesser
 
14
** General Public License version 2.1 requirements will be met:
 
15
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
16
**
 
17
** In addition, as a special exception, Nokia gives you certain additional
 
18
** rights. These rights are described in the Nokia Qt LGPL Exception
 
19
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
20
**
 
21
** GNU General Public License Usage
 
22
** Alternatively, this file may be used under the terms of the GNU General
 
23
** Public License version 3.0 as published by the Free Software Foundation
 
24
** and appearing in the file LICENSE.GPL included in the packaging of this
 
25
** file. Please review the following information to ensure the GNU General
 
26
** Public License version 3.0 requirements will be met:
 
27
** http://www.gnu.org/copyleft/gpl.html.
 
28
**
 
29
** Other Usage
 
30
** Alternatively, this file may be used in accordance with the terms and
 
31
** conditions contained in a signed written agreement between you and Nokia.
 
32
**
 
33
**
 
34
**
 
35
**
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
#include <qtest.h>
 
42
 
 
43
#include <QSignalSpy>
 
44
 
 
45
#include <QtQml/qqmlengine.h>
 
46
#include <QtQml/qqmlcomponent.h>
 
47
#include <QtQml/qqmlincubator.h>
 
48
#include <private/qquickloader_p.h>
 
49
#include "testhttpserver.h"
 
50
#include "../../shared/util.h"
 
51
 
 
52
#define SERVER_PORT 14450
 
53
 
 
54
class PeriodicIncubationController : public QObject,
 
55
    public QQmlIncubationController
 
56
{
 
57
public:
 
58
    PeriodicIncubationController() {
 
59
        incubated = false;
 
60
        startTimer(16);
 
61
    }
 
62
 
 
63
    bool incubated;
 
64
 
 
65
protected:
 
66
    virtual void timerEvent(QTimerEvent *) {
 
67
        incubateFor(15);
 
68
    }
 
69
 
 
70
    virtual void incubatingObjectCountChanged(int count) {
 
71
        if (count)
 
72
            incubated = true;
 
73
    }
 
74
};
 
75
 
 
76
class tst_QQuickLoader : public QQmlDataTest
 
77
 
 
78
{
 
79
    Q_OBJECT
 
80
public:
 
81
    tst_QQuickLoader();
 
82
 
 
83
private slots:
 
84
    void sourceOrComponent();
 
85
    void sourceOrComponent_data();
 
86
    void clear();
 
87
    void urlToComponent();
 
88
    void componentToUrl();
 
89
    void anchoredLoader();
 
90
    void sizeLoaderToItem();
 
91
    void sizeItemToLoader();
 
92
    void noResize();
 
93
    void networkRequestUrl();
 
94
    void failNetworkRequest();
 
95
    void networkComponent();
 
96
    void active();
 
97
    void initialPropertyValues_data();
 
98
    void initialPropertyValues();
 
99
    void initialPropertyValuesBinding();
 
100
    void initialPropertyValuesError_data();
 
101
    void initialPropertyValuesError();
 
102
 
 
103
    void deleteComponentCrash();
 
104
    void nonItem();
 
105
    void vmeErrors();
 
106
    void creationContext();
 
107
    void QTBUG_16928();
 
108
    void implicitSize();
 
109
    void QTBUG_17114();
 
110
    void asynchronous_data();
 
111
    void asynchronous();
 
112
    void asynchronous_clear();
 
113
    void simultaneousSyncAsync();
 
114
    void loadedSignal();
 
115
 
 
116
    void parented();
 
117
    void sizeBound();
 
118
 
 
119
private:
 
120
    QQmlEngine engine;
 
121
};
 
122
 
 
123
 
 
124
tst_QQuickLoader::tst_QQuickLoader()
 
125
{
 
126
}
 
127
 
 
128
void tst_QQuickLoader::sourceOrComponent()
 
129
{
 
130
    QFETCH(QString, sourceOrComponent);
 
131
    QFETCH(QString, sourceDefinition);
 
132
    QFETCH(QUrl, sourceUrl);
 
133
    QFETCH(QString, errorString);
 
134
 
 
135
    bool error = !errorString.isEmpty();
 
136
    if (error)
 
137
        QTest::ignoreMessage(QtWarningMsg, errorString.toUtf8().constData());
 
138
 
 
139
    QQmlComponent component(&engine);
 
140
    component.setData(QByteArray(
 
141
            "import QtQuick 2.0\n"
 
142
            "Loader {\n"
 
143
            "   property int onItemChangedCount: 0\n"
 
144
            "   property int onSourceChangedCount: 0\n"
 
145
            "   property int onSourceComponentChangedCount: 0\n"
 
146
            "   property int onStatusChangedCount: 0\n"
 
147
            "   property int onProgressChangedCount: 0\n"
 
148
            "   property int onLoadedCount: 0\n")
 
149
            + sourceDefinition.toUtf8()
 
150
            + QByteArray(
 
151
            "   onItemChanged: onItemChangedCount += 1\n"
 
152
            "   onSourceChanged: onSourceChangedCount += 1\n"
 
153
            "   onSourceComponentChanged: onSourceComponentChangedCount += 1\n"
 
154
            "   onStatusChanged: onStatusChangedCount += 1\n"
 
155
            "   onProgressChanged: onProgressChangedCount += 1\n"
 
156
            "   onLoaded: onLoadedCount += 1\n"
 
157
            "}")
 
158
        , dataDirectoryUrl());
 
159
 
 
160
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
161
    QVERIFY(loader != 0);
 
162
    QCOMPARE(loader->item() == 0, error);
 
163
    QCOMPARE(loader->source(), sourceUrl);
 
164
    QCOMPARE(loader->progress(), 1.0);
 
165
 
 
166
    QCOMPARE(loader->status(), error ? QQuickLoader::Error : QQuickLoader::Ready);
 
167
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), error ? 0: 1);
 
168
 
 
169
    if (!error) {
 
170
        bool sourceComponentIsChildOfLoader = false;
 
171
        for (int ii = 0; ii < loader->children().size(); ++ii) {
 
172
            QQmlComponent *c = qobject_cast<QQmlComponent*>(loader->children().at(ii));
 
173
            if (c && c == loader->sourceComponent()) {
 
174
                sourceComponentIsChildOfLoader = true;
 
175
            }
 
176
        }
 
177
        QVERIFY(sourceComponentIsChildOfLoader);
 
178
    }
 
179
 
 
180
    if (sourceOrComponent == "component") {
 
181
        QCOMPARE(loader->property("onSourceComponentChangedCount").toInt(), 1);
 
182
        QCOMPARE(loader->property("onSourceChangedCount").toInt(), 0);
 
183
    } else {
 
184
        QCOMPARE(loader->property("onSourceComponentChangedCount").toInt(), 0);
 
185
        QCOMPARE(loader->property("onSourceChangedCount").toInt(), 1);
 
186
    }
 
187
    QCOMPARE(loader->property("onStatusChangedCount").toInt(), 1);
 
188
    QCOMPARE(loader->property("onProgressChangedCount").toInt(), 1);
 
189
 
 
190
    QCOMPARE(loader->property("onItemChangedCount").toInt(), error ? 0 : 1);
 
191
    QCOMPARE(loader->property("onLoadedCount").toInt(), error ? 0 : 1);
 
192
 
 
193
    delete loader;
 
194
}
 
195
 
 
196
void tst_QQuickLoader::sourceOrComponent_data()
 
197
{
 
198
    QTest::addColumn<QString>("sourceOrComponent");
 
199
    QTest::addColumn<QString>("sourceDefinition");
 
200
    QTest::addColumn<QUrl>("sourceUrl");
 
201
    QTest::addColumn<QString>("errorString");
 
202
 
 
203
    QTest::newRow("source") << "source" << "source: 'Rect120x60.qml'\n" << testFileUrl("Rect120x60.qml") << "";
 
204
    QTest::newRow("sourceComponent") << "component" << "Component { id: comp; Rectangle { width: 100; height: 50 } }\n sourceComponent: comp\n" << QUrl() << "";
 
205
    QTest::newRow("invalid source") << "source" << "source: 'IDontExist.qml'\n" << testFileUrl("IDontExist.qml")
 
206
            << QString(testFileUrl("IDontExist.qml").toString() + ": File not found");
 
207
}
 
208
 
 
209
void tst_QQuickLoader::clear()
 
210
{
 
211
    {
 
212
        QQmlComponent component(&engine);
 
213
        component.setData(QByteArray(
 
214
                    "import QtQuick 2.0\n"
 
215
                    " Loader { id: loader\n"
 
216
                    "  source: 'Rect120x60.qml'\n"
 
217
                    "  Timer { interval: 200; running: true; onTriggered: loader.source = '' }\n"
 
218
                    " }")
 
219
                , dataDirectoryUrl());
 
220
        QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
221
        QVERIFY(loader != 0);
 
222
        QVERIFY(loader->item());
 
223
        QCOMPARE(loader->progress(), 1.0);
 
224
        QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
225
 
 
226
        QTRY_VERIFY(loader->item() == 0);
 
227
        QCOMPARE(loader->progress(), 0.0);
 
228
        QCOMPARE(loader->status(), QQuickLoader::Null);
 
229
        QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
 
230
 
 
231
        delete loader;
 
232
    }
 
233
    {
 
234
        QQmlComponent component(&engine, testFileUrl("/SetSourceComponent.qml"));
 
235
        QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
236
        QVERIFY(item);
 
237
 
 
238
        QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
 
239
        QVERIFY(loader);
 
240
        QVERIFY(loader->item());
 
241
        QCOMPARE(loader->progress(), 1.0);
 
242
        QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
243
 
 
244
        loader->setSourceComponent(0);
 
245
 
 
246
        QVERIFY(loader->item() == 0);
 
247
        QCOMPARE(loader->progress(), 0.0);
 
248
        QCOMPARE(loader->status(), QQuickLoader::Null);
 
249
        QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
 
250
 
 
251
        delete item;
 
252
    }
 
253
    {
 
254
        QQmlComponent component(&engine, testFileUrl("/SetSourceComponent.qml"));
 
255
        QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
256
        QVERIFY(item);
 
257
 
 
258
        QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
 
259
        QVERIFY(loader);
 
260
        QVERIFY(loader->item());
 
261
        QCOMPARE(loader->progress(), 1.0);
 
262
        QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
263
 
 
264
        QMetaObject::invokeMethod(item, "clear");
 
265
 
 
266
        QVERIFY(loader->item() == 0);
 
267
        QCOMPARE(loader->progress(), 0.0);
 
268
        QCOMPARE(loader->status(), QQuickLoader::Null);
 
269
        QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
 
270
 
 
271
        delete item;
 
272
    }
 
273
}
 
274
 
 
275
void tst_QQuickLoader::urlToComponent()
 
276
{
 
277
    QQmlComponent component(&engine);
 
278
    component.setData(QByteArray("import QtQuick 2.0\n"
 
279
                "Loader {\n"
 
280
                " id: loader\n"
 
281
                " Component { id: myComp; Rectangle { width: 10; height: 10 } }\n"
 
282
                " source: \"Rect120x60.qml\"\n"
 
283
                " Timer { interval: 100; running: true; onTriggered: loader.sourceComponent = myComp }\n"
 
284
                "}" )
 
285
            , dataDirectoryUrl());
 
286
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
287
    QTest::qWait(200);
 
288
    QTRY_VERIFY(loader != 0);
 
289
    QVERIFY(loader->item());
 
290
    QCOMPARE(loader->progress(), 1.0);
 
291
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
292
    QCOMPARE(loader->width(), 10.0);
 
293
    QCOMPARE(loader->height(), 10.0);
 
294
 
 
295
    delete loader;
 
296
}
 
297
 
 
298
void tst_QQuickLoader::componentToUrl()
 
299
{
 
300
    QQmlComponent component(&engine, testFileUrl("/SetSourceComponent.qml"));
 
301
    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
302
    QVERIFY(item);
 
303
 
 
304
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
 
305
    QVERIFY(loader);
 
306
    QVERIFY(loader->item());
 
307
    QCOMPARE(loader->progress(), 1.0);
 
308
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
309
 
 
310
    loader->setSource(testFileUrl("/Rect120x60.qml"));
 
311
    QVERIFY(loader->item());
 
312
    QCOMPARE(loader->progress(), 1.0);
 
313
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
314
    QCOMPARE(loader->width(), 120.0);
 
315
    QCOMPARE(loader->height(), 60.0);
 
316
 
 
317
    delete item;
 
318
}
 
319
 
 
320
void tst_QQuickLoader::anchoredLoader()
 
321
{
 
322
    QQmlComponent component(&engine, testFileUrl("/AnchoredLoader.qml"));
 
323
    QQuickItem *rootItem = qobject_cast<QQuickItem*>(component.create());
 
324
    QVERIFY(rootItem != 0);
 
325
    QQuickItem *loader = rootItem->findChild<QQuickItem*>("loader");
 
326
    QQuickItem *sourceElement = rootItem->findChild<QQuickItem*>("sourceElement");
 
327
 
 
328
    QVERIFY(loader != 0);
 
329
    QVERIFY(sourceElement != 0);
 
330
 
 
331
    QCOMPARE(rootItem->width(), 300.0);
 
332
    QCOMPARE(rootItem->height(), 200.0);
 
333
 
 
334
    QCOMPARE(loader->width(), 300.0);
 
335
    QCOMPARE(loader->height(), 200.0);
 
336
 
 
337
    QCOMPARE(sourceElement->width(), 300.0);
 
338
    QCOMPARE(sourceElement->height(), 200.0);
 
339
}
 
340
 
 
341
void tst_QQuickLoader::sizeLoaderToItem()
 
342
{
 
343
    QQmlComponent component(&engine, testFileUrl("/SizeToItem.qml"));
 
344
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
345
    QVERIFY(loader != 0);
 
346
    QCOMPARE(loader->width(), 120.0);
 
347
    QCOMPARE(loader->height(), 60.0);
 
348
 
 
349
    // Check resize
 
350
    QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
 
351
    QVERIFY(rect);
 
352
    rect->setWidth(150);
 
353
    rect->setHeight(45);
 
354
    QCOMPARE(loader->width(), 150.0);
 
355
    QCOMPARE(loader->height(), 45.0);
 
356
 
 
357
    // Check explicit width
 
358
    loader->setWidth(200.0);
 
359
    QCOMPARE(loader->width(), 200.0);
 
360
    QCOMPARE(rect->width(), 200.0);
 
361
    rect->setWidth(100.0); // when rect changes ...
 
362
    QCOMPARE(rect->width(), 100.0); // ... it changes
 
363
    QCOMPARE(loader->width(), 200.0); // ... but loader stays the same
 
364
 
 
365
    // Check explicit height
 
366
    loader->setHeight(200.0);
 
367
    QCOMPARE(loader->height(), 200.0);
 
368
    QCOMPARE(rect->height(), 200.0);
 
369
    rect->setHeight(100.0); // when rect changes ...
 
370
    QCOMPARE(rect->height(), 100.0); // ... it changes
 
371
    QCOMPARE(loader->height(), 200.0); // ... but loader stays the same
 
372
 
 
373
    // Switch mode
 
374
    loader->setWidth(180);
 
375
    loader->setHeight(30);
 
376
    QCOMPARE(rect->width(), 180.0);
 
377
    QCOMPARE(rect->height(), 30.0);
 
378
 
 
379
    delete loader;
 
380
}
 
381
 
 
382
void tst_QQuickLoader::sizeItemToLoader()
 
383
{
 
384
    QQmlComponent component(&engine, testFileUrl("/SizeToLoader.qml"));
 
385
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
386
    QVERIFY(loader != 0);
 
387
    QCOMPARE(loader->width(), 200.0);
 
388
    QCOMPARE(loader->height(), 80.0);
 
389
 
 
390
    QQuickItem *rect = qobject_cast<QQuickItem*>(loader->item());
 
391
    QVERIFY(rect);
 
392
    QCOMPARE(rect->width(), 200.0);
 
393
    QCOMPARE(rect->height(), 80.0);
 
394
 
 
395
    // Check resize
 
396
    loader->setWidth(180);
 
397
    loader->setHeight(30);
 
398
    QCOMPARE(rect->width(), 180.0);
 
399
    QCOMPARE(rect->height(), 30.0);
 
400
 
 
401
    // Switch mode
 
402
    loader->resetWidth(); // reset explicit size
 
403
    loader->resetHeight();
 
404
    rect->setWidth(160);
 
405
    rect->setHeight(45);
 
406
    QCOMPARE(loader->width(), 160.0);
 
407
    QCOMPARE(loader->height(), 45.0);
 
408
 
 
409
    delete loader;
 
410
}
 
411
 
 
412
void tst_QQuickLoader::noResize()
 
413
{
 
414
    QQmlComponent component(&engine, testFileUrl("/NoResize.qml"));
 
415
    QQuickItem* item = qobject_cast<QQuickItem*>(component.create());
 
416
    QVERIFY(item != 0);
 
417
    QCOMPARE(item->width(), 200.0);
 
418
    QCOMPARE(item->height(), 80.0);
 
419
 
 
420
    delete item;
 
421
}
 
422
 
 
423
void tst_QQuickLoader::networkRequestUrl()
 
424
{
 
425
    TestHTTPServer server(SERVER_PORT);
 
426
    QVERIFY(server.isValid());
 
427
    server.serveDirectory(dataDirectory());
 
428
 
 
429
    QQmlComponent component(&engine);
 
430
    component.setData(QByteArray("import QtQuick 2.0\nLoader { property int signalCount : 0; source: \"http://127.0.0.1:14450/Rect120x60.qml\"; onLoaded: signalCount += 1 }"), testFileUrl("../dummy.qml"));
 
431
    if (component.isError())
 
432
        qDebug() << component.errors();
 
433
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
434
    QVERIFY(loader != 0);
 
435
 
 
436
    QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
 
437
 
 
438
    QVERIFY(loader->item());
 
439
    QCOMPARE(loader->progress(), 1.0);
 
440
    QCOMPARE(loader->property("signalCount").toInt(), 1);
 
441
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
442
 
 
443
    delete loader;
 
444
}
 
445
 
 
446
/* XXX Component waits until all dependencies are loaded.  Is this actually possible? */
 
447
void tst_QQuickLoader::networkComponent()
 
448
{
 
449
    TestHTTPServer server(SERVER_PORT);
 
450
    QVERIFY(server.isValid());
 
451
    server.serveDirectory(dataDirectory(), TestHTTPServer::Delay);
 
452
 
 
453
    QQmlComponent component(&engine);
 
454
    component.setData(QByteArray(
 
455
                "import QtQuick 2.0\n"
 
456
                "import \"http://127.0.0.1:14450/\" as NW\n"
 
457
                "Item {\n"
 
458
                " Component { id: comp; NW.Rect120x60 {} }\n"
 
459
                " Loader { sourceComponent: comp } }")
 
460
            , dataDirectory());
 
461
 
 
462
    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
463
    QVERIFY(item);
 
464
 
 
465
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::children().at(1));
 
466
    QVERIFY(loader);
 
467
    QTRY_VERIFY(loader->status() == QQuickLoader::Ready);
 
468
 
 
469
    QVERIFY(loader->item());
 
470
    QCOMPARE(loader->progress(), 1.0);
 
471
    QCOMPARE(loader->status(), QQuickLoader::Ready);
 
472
    QCOMPARE(static_cast<QQuickItem*>(loader)->children().count(), 1);
 
473
 
 
474
    delete loader;
 
475
}
 
476
 
 
477
void tst_QQuickLoader::failNetworkRequest()
 
478
{
 
479
    TestHTTPServer server(SERVER_PORT);
 
480
    QVERIFY(server.isValid());
 
481
    server.serveDirectory(dataDirectory());
 
482
 
 
483
    QTest::ignoreMessage(QtWarningMsg, "http://127.0.0.1:14450/IDontExist.qml: File not found");
 
484
 
 
485
    QQmlComponent component(&engine);
 
486
    component.setData(QByteArray("import QtQuick 2.0\nLoader { property int did_load: 123; source: \"http://127.0.0.1:14450/IDontExist.qml\"; onLoaded: did_load=456 }"), QUrl::fromLocalFile("http://127.0.0.1:14450/dummy.qml"));
 
487
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
488
    QVERIFY(loader != 0);
 
489
 
 
490
    QTRY_VERIFY(loader->status() == QQuickLoader::Error);
 
491
 
 
492
    QVERIFY(loader->item() == 0);
 
493
    QCOMPARE(loader->progress(), 1.0);
 
494
    QCOMPARE(loader->property("did_load").toInt(), 123);
 
495
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
 
496
 
 
497
    delete loader;
 
498
}
 
499
 
 
500
void tst_QQuickLoader::active()
 
501
{
 
502
    // check that the item isn't instantiated until active is set to true
 
503
    {
 
504
        QQmlComponent component(&engine, testFileUrl("active.1.qml"));
 
505
        QObject *object = component.create();
 
506
        QVERIFY(object != 0);
 
507
        QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
508
 
 
509
        QVERIFY(loader->active() == false); // set manually to false
 
510
        QVERIFY(loader->item() == 0);
 
511
        QMetaObject::invokeMethod(object, "doSetSourceComponent");
 
512
        QVERIFY(loader->item() == 0);
 
513
        QMetaObject::invokeMethod(object, "doSetSource");
 
514
        QVERIFY(loader->item() == 0);
 
515
        QMetaObject::invokeMethod(object, "doSetActive");
 
516
        QVERIFY(loader->item() != 0);
 
517
 
 
518
        delete object;
 
519
    }
 
520
 
 
521
    // check that the status is Null if active is set to false
 
522
    {
 
523
        QQmlComponent component(&engine, testFileUrl("active.2.qml"));
 
524
        QObject *object = component.create();
 
525
        QVERIFY(object != 0);
 
526
        QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
527
 
 
528
        QVERIFY(loader->active() == true); // active is true by default
 
529
        QCOMPARE(loader->status(), QQuickLoader::Ready);
 
530
        int currStatusChangedCount = loader->property("statusChangedCount").toInt();
 
531
        QMetaObject::invokeMethod(object, "doSetInactive");
 
532
        QCOMPARE(loader->status(), QQuickLoader::Null);
 
533
        QCOMPARE(loader->property("statusChangedCount").toInt(), (currStatusChangedCount+1));
 
534
 
 
535
        delete object;
 
536
    }
 
537
 
 
538
    // check that the source is not cleared if active is set to false
 
539
    {
 
540
        QQmlComponent component(&engine, testFileUrl("active.3.qml"));
 
541
        QObject *object = component.create();
 
542
        QVERIFY(object != 0);
 
543
        QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
544
 
 
545
        QVERIFY(loader->active() == true); // active is true by default
 
546
        QVERIFY(!loader->source().isEmpty());
 
547
        int currSourceChangedCount = loader->property("sourceChangedCount").toInt();
 
548
        QMetaObject::invokeMethod(object, "doSetInactive");
 
549
        QVERIFY(!loader->source().isEmpty());
 
550
        QCOMPARE(loader->property("sourceChangedCount").toInt(), currSourceChangedCount);
 
551
 
 
552
        delete object;
 
553
    }
 
554
 
 
555
    // check that the sourceComponent is not cleared if active is set to false
 
556
    {
 
557
        QQmlComponent component(&engine, testFileUrl("active.4.qml"));
 
558
        QObject *object = component.create();
 
559
        QVERIFY(object != 0);
 
560
        QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
561
 
 
562
        QVERIFY(loader->active() == true); // active is true by default
 
563
        QVERIFY(loader->sourceComponent() != 0);
 
564
        int currSourceComponentChangedCount = loader->property("sourceComponentChangedCount").toInt();
 
565
        QMetaObject::invokeMethod(object, "doSetInactive");
 
566
        QVERIFY(loader->sourceComponent() != 0);
 
567
        QCOMPARE(loader->property("sourceComponentChangedCount").toInt(), currSourceComponentChangedCount);
 
568
 
 
569
        delete object;
 
570
    }
 
571
 
 
572
    // check that the item is released if active is set to false
 
573
    {
 
574
        QQmlComponent component(&engine, testFileUrl("active.5.qml"));
 
575
        QObject *object = component.create();
 
576
        QVERIFY(object != 0);
 
577
        QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
578
 
 
579
        QVERIFY(loader->active() == true); // active is true by default
 
580
        QVERIFY(loader->item() != 0);
 
581
        int currItemChangedCount = loader->property("itemChangedCount").toInt();
 
582
        QMetaObject::invokeMethod(object, "doSetInactive");
 
583
        QVERIFY(loader->item() == 0);
 
584
        QCOMPARE(loader->property("itemChangedCount").toInt(), (currItemChangedCount+1));
 
585
 
 
586
        delete object;
 
587
    }
 
588
 
 
589
    // check that the activeChanged signal is emitted correctly
 
590
    {
 
591
        QQmlComponent component(&engine, testFileUrl("active.6.qml"));
 
592
        QObject *object = component.create();
 
593
        QVERIFY(object != 0);
 
594
        QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
595
 
 
596
        QVERIFY(loader->active() == true); // active is true by default
 
597
        loader->setActive(true);           // no effect
 
598
        QCOMPARE(loader->property("activeChangedCount").toInt(), 0);
 
599
        loader->setActive(false);          // change signal should be emitted
 
600
        QCOMPARE(loader->property("activeChangedCount").toInt(), 1);
 
601
        loader->setActive(false);          // no effect
 
602
        QCOMPARE(loader->property("activeChangedCount").toInt(), 1);
 
603
        loader->setActive(true);           // change signal should be emitted
 
604
        QCOMPARE(loader->property("activeChangedCount").toInt(), 2);
 
605
        loader->setActive(false);          // change signal should be emitted
 
606
        QCOMPARE(loader->property("activeChangedCount").toInt(), 3);
 
607
        QMetaObject::invokeMethod(object, "doSetActive");
 
608
        QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
 
609
        QMetaObject::invokeMethod(object, "doSetActive");
 
610
        QCOMPARE(loader->property("activeChangedCount").toInt(), 4);
 
611
        QMetaObject::invokeMethod(object, "doSetInactive");
 
612
        QCOMPARE(loader->property("activeChangedCount").toInt(), 5);
 
613
        loader->setActive(true);           // change signal should be emitted
 
614
        QCOMPARE(loader->property("activeChangedCount").toInt(), 6);
 
615
 
 
616
        delete object;
 
617
    }
 
618
 
 
619
    // check that the component isn't loaded until active is set to true
 
620
    {
 
621
        QQmlComponent component(&engine, testFileUrl("active.7.qml"));
 
622
        QObject *object = component.create();
 
623
        QVERIFY(object != 0);
 
624
        QCOMPARE(object->property("success").toBool(), true);
 
625
        delete object;
 
626
    }
 
627
 
 
628
    // check that the component is loaded if active is not set (true by default)
 
629
    {
 
630
        QQmlComponent component(&engine, testFileUrl("active.8.qml"));
 
631
        QObject *object = component.create();
 
632
        QVERIFY(object != 0);
 
633
        QCOMPARE(object->property("success").toBool(), true);
 
634
        delete object;
 
635
    }
 
636
}
 
637
 
 
638
void tst_QQuickLoader::initialPropertyValues_data()
 
639
{
 
640
    QTest::addColumn<QUrl>("qmlFile");
 
641
    QTest::addColumn<QStringList>("expectedWarnings");
 
642
    QTest::addColumn<QStringList>("propertyNames");
 
643
    QTest::addColumn<QVariantList>("propertyValues");
 
644
 
 
645
    QTest::newRow("source url with value set in onLoaded, initially active = true") << testFileUrl("initialPropertyValues.1.qml")
 
646
            << QStringList()
 
647
            << (QStringList() << "initialValue" << "behaviorCount")
 
648
            << (QVariantList() << 1 << 1);
 
649
 
 
650
    QTest::newRow("set source with initial property values specified, active = true") << testFileUrl("initialPropertyValues.2.qml")
 
651
            << QStringList()
 
652
            << (QStringList() << "initialValue" << "behaviorCount")
 
653
            << (QVariantList() << 2 << 0);
 
654
 
 
655
    QTest::newRow("set source with initial property values specified, active = false") << testFileUrl("initialPropertyValues.3.qml")
 
656
            << (QStringList() << QString(testFileUrl("initialPropertyValues.3.qml").toString() + QLatin1String(":16: TypeError: Cannot read property 'canary' of null")))
 
657
            << (QStringList())
 
658
            << (QVariantList());
 
659
 
 
660
    QTest::newRow("set source with initial property values specified, active = false, with active set true later") << testFileUrl("initialPropertyValues.4.qml")
 
661
            << QStringList()
 
662
            << (QStringList() << "initialValue" << "behaviorCount")
 
663
            << (QVariantList() << 4 << 0);
 
664
 
 
665
    QTest::newRow("set source without initial property values specified, active = true") << testFileUrl("initialPropertyValues.5.qml")
 
666
            << QStringList()
 
667
            << (QStringList() << "initialValue" << "behaviorCount")
 
668
            << (QVariantList() << 0 << 0);
 
669
 
 
670
    QTest::newRow("set source with initial property values specified with binding, active = true") << testFileUrl("initialPropertyValues.6.qml")
 
671
            << QStringList()
 
672
            << (QStringList() << "initialValue" << "behaviorCount")
 
673
            << (QVariantList() << 6 << 0);
 
674
 
 
675
    QTest::newRow("ensure initial property value semantics mimic createObject") << testFileUrl("initialPropertyValues.7.qml")
 
676
            << QStringList()
 
677
            << (QStringList() << "loaderValue" << "createObjectValue")
 
678
            << (QVariantList() << 1 << 1);
 
679
 
 
680
    QTest::newRow("ensure initial property values aren't disposed prior to component completion") << testFileUrl("initialPropertyValues.8.qml")
 
681
            << QStringList()
 
682
            << (QStringList() << "initialValue")
 
683
            << (QVariantList() << 6);
 
684
}
 
685
 
 
686
void tst_QQuickLoader::initialPropertyValues()
 
687
{
 
688
    QFETCH(QUrl, qmlFile);
 
689
    QFETCH(QStringList, expectedWarnings);
 
690
    QFETCH(QStringList, propertyNames);
 
691
    QFETCH(QVariantList, propertyValues);
 
692
 
 
693
    TestHTTPServer server(SERVER_PORT);
 
694
    QVERIFY(server.isValid());
 
695
    server.serveDirectory(dataDirectory());
 
696
 
 
697
    foreach (const QString &warning, expectedWarnings)
 
698
        QTest::ignoreMessage(QtWarningMsg, warning.toAscii().constData());
 
699
 
 
700
    QQmlComponent component(&engine, qmlFile);
 
701
    QObject *object = component.create();
 
702
    QVERIFY(object != 0);
 
703
    qApp->processEvents();
 
704
    QTest::qWait(50);
 
705
 
 
706
    for (int i = 0; i < propertyNames.size(); ++i)
 
707
        QCOMPARE(object->property(propertyNames.at(i).toAscii().constData()), propertyValues.at(i));
 
708
 
 
709
    delete object;
 
710
}
 
711
 
 
712
void tst_QQuickLoader::initialPropertyValuesBinding()
 
713
{
 
714
    QQmlComponent component(&engine, testFileUrl("initialPropertyValues.binding.qml"));
 
715
    QObject *object = component.create();
 
716
    QVERIFY(object != 0);
 
717
 
 
718
    QVERIFY(object->setProperty("bindable", QVariant(8)));
 
719
    QCOMPARE(object->property("canaryValue").toInt(), 8);
 
720
 
 
721
    delete object;
 
722
}
 
723
 
 
724
void tst_QQuickLoader::initialPropertyValuesError_data()
 
725
{
 
726
    QTest::addColumn<QUrl>("qmlFile");
 
727
    QTest::addColumn<QStringList>("expectedWarnings");
 
728
 
 
729
    QTest::newRow("invalid initial property values object") << testFileUrl("initialPropertyValues.error.1.qml")
 
730
            << (QStringList() << QString(testFileUrl("initialPropertyValues.error.1.qml").toString() + ":6:5: QML Loader: setSource: value is not an object"));
 
731
 
 
732
    QTest::newRow("nonexistent source url") << testFileUrl("initialPropertyValues.error.2.qml")
 
733
            << (QStringList() << QString(testFileUrl("NonexistentSourceComponent.qml").toString() + ": File not found"));
 
734
 
 
735
    QTest::newRow("invalid source url") << testFileUrl("initialPropertyValues.error.3.qml")
 
736
            << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
 
737
 
 
738
    QTest::newRow("invalid initial property values object with invalid property access") << testFileUrl("initialPropertyValues.error.4.qml")
 
739
            << (QStringList() << QString(testFileUrl("initialPropertyValues.error.4.qml").toString() + ":7:5: QML Loader: setSource: value is not an object")
 
740
                              << QString(testFileUrl("initialPropertyValues.error.4.qml").toString() + ":5: TypeError: Cannot read property 'canary' of null"));
 
741
}
 
742
 
 
743
void tst_QQuickLoader::initialPropertyValuesError()
 
744
{
 
745
    QFETCH(QUrl, qmlFile);
 
746
    QFETCH(QStringList, expectedWarnings);
 
747
 
 
748
    foreach (const QString &warning, expectedWarnings)
 
749
        QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
 
750
 
 
751
    QQmlComponent component(&engine, qmlFile);
 
752
    QObject *object = component.create();
 
753
    QVERIFY(object != 0);
 
754
    QQuickLoader *loader = object->findChild<QQuickLoader*>("loader");
 
755
    QVERIFY(loader != 0);
 
756
    QVERIFY(loader->item() == 0);
 
757
    delete object;
 
758
}
 
759
 
 
760
// QTBUG-9241
 
761
void tst_QQuickLoader::deleteComponentCrash()
 
762
{
 
763
    QQmlComponent component(&engine, testFileUrl("crash.qml"));
 
764
    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
765
    QVERIFY(item);
 
766
 
 
767
    item->metaObject()->invokeMethod(item, "setLoaderSource");
 
768
 
 
769
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(item->QQuickItem::childItems().at(0));
 
770
    QVERIFY(loader);
 
771
    QVERIFY(loader->item());
 
772
    QCOMPARE(loader->item()->objectName(), QLatin1String("blue"));
 
773
    QCOMPARE(loader->progress(), 1.0);
 
774
    QCOMPARE(loader->status(), QQuickLoader::Ready);
 
775
    QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
 
776
    QCoreApplication::processEvents();
 
777
    QTRY_COMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
778
    QVERIFY(loader->source() == testFileUrl("BlueRect.qml"));
 
779
 
 
780
    delete item;
 
781
}
 
782
 
 
783
void tst_QQuickLoader::nonItem()
 
784
{
 
785
    QQmlComponent component(&engine, testFileUrl("nonItem.qml"));
 
786
    QString err = testFileUrl("nonItem.qml").toString() + ":3:1: QML Loader: Loader does not support loading non-visual elements.";
 
787
 
 
788
    QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
 
789
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
790
    QVERIFY(loader);
 
791
    QVERIFY(loader->item() == 0);
 
792
 
 
793
    delete loader;
 
794
}
 
795
 
 
796
void tst_QQuickLoader::vmeErrors()
 
797
{
 
798
    QQmlComponent component(&engine, testFileUrl("vmeErrors.qml"));
 
799
    QString err = testFileUrl("VmeError.qml").toString() + ":6: Cannot assign object type QObject with no default method";
 
800
    QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData());
 
801
    QQuickLoader *loader = qobject_cast<QQuickLoader*>(component.create());
 
802
    QVERIFY(loader);
 
803
    QVERIFY(loader->item() == 0);
 
804
 
 
805
    delete loader;
 
806
}
 
807
 
 
808
// QTBUG-13481
 
809
void tst_QQuickLoader::creationContext()
 
810
{
 
811
    QQmlComponent component(&engine, testFileUrl("creationContext.qml"));
 
812
 
 
813
    QObject *o = component.create();
 
814
    QVERIFY(o != 0);
 
815
 
 
816
    QCOMPARE(o->property("test").toBool(), true);
 
817
 
 
818
    delete o;
 
819
}
 
820
 
 
821
void tst_QQuickLoader::QTBUG_16928()
 
822
{
 
823
    QQmlComponent component(&engine, testFileUrl("QTBUG_16928.qml"));
 
824
    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
825
    QVERIFY(item);
 
826
 
 
827
    QCOMPARE(item->width(), 250.);
 
828
    QCOMPARE(item->height(), 250.);
 
829
 
 
830
    delete item;
 
831
}
 
832
 
 
833
void tst_QQuickLoader::implicitSize()
 
834
{
 
835
    QQmlComponent component(&engine, testFileUrl("implicitSize.qml"));
 
836
    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
837
    QVERIFY(item);
 
838
 
 
839
    QCOMPARE(item->width(), 150.);
 
840
    QCOMPARE(item->height(), 150.);
 
841
 
 
842
    QCOMPARE(item->property("implHeight").toReal(), 100.);
 
843
    QCOMPARE(item->property("implWidth").toReal(), 100.);
 
844
 
 
845
    QQuickLoader *loader = item->findChild<QQuickLoader*>("loader");
 
846
    QSignalSpy implWidthSpy(loader, SIGNAL(implicitWidthChanged()));
 
847
    QSignalSpy implHeightSpy(loader, SIGNAL(implicitHeightChanged()));
 
848
 
 
849
    QMetaObject::invokeMethod(item, "changeImplicitSize");
 
850
 
 
851
    QCOMPARE(loader->property("implicitWidth").toReal(), 200.);
 
852
    QCOMPARE(loader->property("implicitHeight").toReal(), 300.);
 
853
 
 
854
    QCOMPARE(implWidthSpy.count(), 1);
 
855
    QCOMPARE(implHeightSpy.count(), 1);
 
856
 
 
857
    delete item;
 
858
}
 
859
 
 
860
void tst_QQuickLoader::QTBUG_17114()
 
861
{
 
862
    QQmlComponent component(&engine, testFileUrl("QTBUG_17114.qml"));
 
863
    QQuickItem *item = qobject_cast<QQuickItem*>(component.create());
 
864
    QVERIFY(item);
 
865
 
 
866
    QCOMPARE(item->property("loaderWidth").toReal(), 32.);
 
867
    QCOMPARE(item->property("loaderHeight").toReal(), 32.);
 
868
 
 
869
    delete item;
 
870
}
 
871
 
 
872
void tst_QQuickLoader::asynchronous_data()
 
873
{
 
874
    QTest::addColumn<QUrl>("qmlFile");
 
875
    QTest::addColumn<QStringList>("expectedWarnings");
 
876
 
 
877
    QTest::newRow("Valid component") << testFileUrl("BigComponent.qml")
 
878
            << QStringList();
 
879
 
 
880
    QTest::newRow("Non-existent component") << testFileUrl("IDoNotExist.qml")
 
881
            << (QStringList() << QString(testFileUrl("IDoNotExist.qml").toString() + ": File not found"));
 
882
 
 
883
    QTest::newRow("Invalid component") << testFileUrl("InvalidSourceComponent.qml")
 
884
            << (QStringList() << QString(testFileUrl("InvalidSourceComponent.qml").toString() + ":5:1: Syntax error"));
 
885
}
 
886
 
 
887
void tst_QQuickLoader::asynchronous()
 
888
{
 
889
    QFETCH(QUrl, qmlFile);
 
890
    QFETCH(QStringList, expectedWarnings);
 
891
 
 
892
    if (!engine.incubationController())
 
893
        engine.setIncubationController(new PeriodicIncubationController);
 
894
    PeriodicIncubationController *controller = static_cast<PeriodicIncubationController*>(engine.incubationController());
 
895
    controller->incubated = false;
 
896
    QQmlComponent component(&engine, testFileUrl("asynchronous.qml"));
 
897
    QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
 
898
    QVERIFY(root);
 
899
 
 
900
    QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
 
901
    QVERIFY(loader);
 
902
 
 
903
    foreach (const QString &warning, expectedWarnings)
 
904
        QTest::ignoreMessage(QtWarningMsg, warning.toUtf8().constData());
 
905
 
 
906
    QVERIFY(!loader->item());
 
907
    QCOMPARE(loader->progress(), 0.0);
 
908
    root->setProperty("comp", qmlFile.toString());
 
909
    QMetaObject::invokeMethod(root, "loadComponent");
 
910
    QVERIFY(!loader->item());
 
911
 
 
912
    if (expectedWarnings.isEmpty()) {
 
913
        QCOMPARE(loader->status(), QQuickLoader::Loading);
 
914
        QVERIFY(!controller->incubated); // asynchronous compilation means not immediately compiled/incubating.
 
915
        QTRY_VERIFY(controller->incubated); // but should start incubating once compilation is complete.
 
916
        QTRY_VERIFY(loader->item());
 
917
        QCOMPARE(loader->progress(), 1.0);
 
918
        QCOMPARE(loader->status(), QQuickLoader::Ready);
 
919
    } else {
 
920
        QTRY_COMPARE(loader->progress(), 1.0);
 
921
        QTRY_COMPARE(loader->status(), QQuickLoader::Error);
 
922
    }
 
923
 
 
924
    delete root;
 
925
}
 
926
 
 
927
void tst_QQuickLoader::asynchronous_clear()
 
928
{
 
929
    if (!engine.incubationController())
 
930
        engine.setIncubationController(new PeriodicIncubationController);
 
931
    QQmlComponent component(&engine, testFileUrl("asynchronous.qml"));
 
932
    QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
 
933
    QVERIFY(root);
 
934
 
 
935
    QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
 
936
    QVERIFY(loader);
 
937
 
 
938
    QVERIFY(!loader->item());
 
939
    root->setProperty("comp", "BigComponent.qml");
 
940
    QMetaObject::invokeMethod(root, "loadComponent");
 
941
    QVERIFY(!loader->item());
 
942
 
 
943
    QCOMPARE(loader->status(), QQuickLoader::Loading);
 
944
    QTRY_COMPARE(engine.incubationController()->incubatingObjectCount(), 1);
 
945
 
 
946
    // clear before component created
 
947
    root->setProperty("comp", "");
 
948
    QMetaObject::invokeMethod(root, "loadComponent");
 
949
    QVERIFY(!loader->item());
 
950
    QCOMPARE(engine.incubationController()->incubatingObjectCount(), 0);
 
951
 
 
952
    QCOMPARE(loader->progress(), 0.0);
 
953
    QCOMPARE(loader->status(), QQuickLoader::Null);
 
954
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 0);
 
955
 
 
956
    // check loading component
 
957
    root->setProperty("comp", "BigComponent.qml");
 
958
    QMetaObject::invokeMethod(root, "loadComponent");
 
959
    QVERIFY(!loader->item());
 
960
 
 
961
    QCOMPARE(loader->status(), QQuickLoader::Loading);
 
962
    QCOMPARE(engine.incubationController()->incubatingObjectCount(), 1);
 
963
 
 
964
    QTRY_VERIFY(loader->item());
 
965
    QCOMPARE(loader->progress(), 1.0);
 
966
    QCOMPARE(loader->status(), QQuickLoader::Ready);
 
967
    QCOMPARE(static_cast<QQuickItem*>(loader)->childItems().count(), 1);
 
968
 
 
969
    delete root;
 
970
}
 
971
 
 
972
void tst_QQuickLoader::simultaneousSyncAsync()
 
973
{
 
974
    if (!engine.incubationController())
 
975
        engine.setIncubationController(new PeriodicIncubationController);
 
976
    PeriodicIncubationController *controller = static_cast<PeriodicIncubationController*>(engine.incubationController());
 
977
    controller->incubated = false;
 
978
    QQmlComponent component(&engine, testFileUrl("simultaneous.qml"));
 
979
    QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
 
980
    QVERIFY(root);
 
981
 
 
982
    QQuickLoader *asyncLoader = root->findChild<QQuickLoader*>("asyncLoader");
 
983
    QQuickLoader *syncLoader = root->findChild<QQuickLoader*>("syncLoader");
 
984
    QVERIFY(asyncLoader);
 
985
    QVERIFY(syncLoader);
 
986
 
 
987
    QVERIFY(!asyncLoader->item());
 
988
    QVERIFY(!syncLoader->item());
 
989
    QMetaObject::invokeMethod(root, "loadComponents");
 
990
    QVERIFY(!asyncLoader->item());
 
991
    QVERIFY(syncLoader->item());
 
992
 
 
993
    QCOMPARE(asyncLoader->status(), QQuickLoader::Loading);
 
994
    QVERIFY(!controller->incubated); // asynchronous compilation means not immediately compiled/incubating.
 
995
    QTRY_VERIFY(controller->incubated); // but should start incubating once compilation is complete.
 
996
    QTRY_VERIFY(asyncLoader->item());
 
997
    QCOMPARE(asyncLoader->progress(), 1.0);
 
998
    QCOMPARE(asyncLoader->status(), QQuickLoader::Ready);
 
999
 
 
1000
    delete root;
 
1001
}
 
1002
 
 
1003
void tst_QQuickLoader::loadedSignal()
 
1004
{
 
1005
    {
 
1006
        // ensure that triggering loading (by setting active = true)
 
1007
        // and then immediately setting active to false, causes the
 
1008
        // loader to be deactivated, including disabling the incubator.
 
1009
        QQmlComponent component(&engine, testFileUrl("loadedSignal.qml"));
 
1010
        QObject *obj = component.create();
 
1011
 
 
1012
        QMetaObject::invokeMethod(obj, "triggerLoading");
 
1013
        QTest::qWait(100); // ensure that loading would have finished if it wasn't deactivated
 
1014
        QCOMPARE(obj->property("loadCount").toInt(), 0);
 
1015
        QVERIFY(obj->property("success").toBool());
 
1016
 
 
1017
        QMetaObject::invokeMethod(obj, "triggerLoading");
 
1018
        QTest::qWait(100);
 
1019
        QCOMPARE(obj->property("loadCount").toInt(), 0);
 
1020
        QVERIFY(obj->property("success").toBool());
 
1021
 
 
1022
        QMetaObject::invokeMethod(obj, "triggerMultipleLoad");
 
1023
        QTest::qWait(100);
 
1024
        QCOMPARE(obj->property("loadCount").toInt(), 1); // only one loaded signal should be emitted.
 
1025
        QVERIFY(obj->property("success").toBool());
 
1026
 
 
1027
        delete obj;
 
1028
    }
 
1029
 
 
1030
    {
 
1031
        // ensure that an error doesn't result in the onLoaded signal being emitted.
 
1032
        QQmlComponent component(&engine, testFileUrl("loadedSignal.2.qml"));
 
1033
        QObject *obj = component.create();
 
1034
 
 
1035
        QMetaObject::invokeMethod(obj, "triggerLoading");
 
1036
        QTest::qWait(100);
 
1037
        QCOMPARE(obj->property("loadCount").toInt(), 0);
 
1038
        QVERIFY(obj->property("success").toBool());
 
1039
 
 
1040
        delete obj;
 
1041
    }
 
1042
}
 
1043
 
 
1044
void tst_QQuickLoader::parented()
 
1045
{
 
1046
    QQmlComponent component(&engine, testFileUrl("parented.qml"));
 
1047
    QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
 
1048
    QVERIFY(root);
 
1049
 
 
1050
    QQuickItem *item = root->findChild<QQuickItem*>("comp");
 
1051
    QVERIFY(item);
 
1052
 
 
1053
    QVERIFY(item->parentItem() == root);
 
1054
 
 
1055
    QCOMPARE(item->width(), 300.);
 
1056
    QCOMPARE(item->height(), 300.);
 
1057
 
 
1058
    delete root;
 
1059
}
 
1060
 
 
1061
void tst_QQuickLoader::sizeBound()
 
1062
{
 
1063
    QQmlComponent component(&engine, testFileUrl("sizebound.qml"));
 
1064
    QQuickItem *root = qobject_cast<QQuickItem*>(component.create());
 
1065
    QVERIFY(root);
 
1066
    QQuickLoader *loader = root->findChild<QQuickLoader*>("loader");
 
1067
    QVERIFY(loader != 0);
 
1068
 
 
1069
    QVERIFY(loader->item());
 
1070
 
 
1071
    QCOMPARE(loader->width(), 50.0);
 
1072
    QCOMPARE(loader->height(), 60.0);
 
1073
 
 
1074
    QMetaObject::invokeMethod(root, "switchComponent");
 
1075
 
 
1076
    QCOMPARE(loader->width(), 80.0);
 
1077
    QCOMPARE(loader->height(), 90.0);
 
1078
 
 
1079
    delete root;
 
1080
}
 
1081
 
 
1082
 
 
1083
QTEST_MAIN(tst_QQuickLoader)
 
1084
 
 
1085
#include "tst_qquickloader.moc"