Merge lp:~zsombi/ubuntu-ui-toolkit/asyncLoader into lp:ubuntu-ui-toolkit/staging
- asyncLoader
- Merge into staging
Status: | Merged |
---|---|
Approved by: | Zsombor Egri |
Approved revision: | 1872 |
Merged at revision: | 1876 |
Proposed branch: | lp:~zsombi/ubuntu-ui-toolkit/asyncLoader |
Merge into: | lp:ubuntu-ui-toolkit/staging |
Diff against target: |
910 lines (+778/-4) 18 files modified
debian/control (+10/-0) debian/libubuntutoolkit5-dev.install (+2/-0) debian/libubuntutoolkit5-private-dev.install (+1/-0) src/Ubuntu/Test/plugin/uctestcase.cpp (+13/-0) src/Ubuntu/Test/plugin/uctestcase.h (+1/-0) src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro (+5/-2) src/Ubuntu/UbuntuToolkit/asyncloader.cpp (+222/-0) src/Ubuntu/UbuntuToolkit/asyncloader.h (+63/-0) src/Ubuntu/UbuntuToolkit/asyncloader_p.h (+54/-0) tests/unit/plugin_dependency.pri (+1/-0) tests/unit/test-include.pri (+1/-1) tests/unit_x11/tst_asyncloader/Document.qml (+31/-0) tests/unit_x11/tst_asyncloader/FaultyDocument.qml (+20/-0) tests/unit_x11/tst_asyncloader/HeavyDocument.qml (+31/-0) tests/unit_x11/tst_asyncloader/TestApp.qml (+22/-0) tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp (+288/-0) tests/unit_x11/tst_asyncloader/tst_asyncloader.pro (+11/-0) tests/unit_x11/unit_x11.pro (+2/-1) |
To merge this branch: | bzr merge lp:~zsombi/ubuntu-ui-toolkit/asyncLoader |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
ubuntu-sdk-build-bot | continuous-integration | Approve | |
Benjamin Zeller | Approve | ||
Review via email: mp+286502@code.launchpad.net |
Commit message
Asynchronous loader (AsyncLoader) using incubator, prerequisite for BottomEdge preloading its content.
Description of the change
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1864
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1864
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1864
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1864
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1865
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1865
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1865
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1865
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1865
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1866
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1866
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1866
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1866
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1866
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Benjamin Zeller (zeller-benjamin) wrote : | # |
A few inline comments, but looks good already.
Zsombor Egri (zsombi) wrote : | # |
Replied back, will provide the fixes next.
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1869
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1869
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1869
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1869
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1869
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Benjamin Zeller (zeller-benjamin) wrote : | # |
You need to add the -private-dev package for the new UbuntuToolkit:
=== modified file 'debian/control'
--- debian/control 2016-02-11 16:17:46 +0000
+++ debian/control 2016-02-25 15:50:04 +0000
@@ -139,6 +139,16 @@
This package contains the development files for
Ubuntu toolkit common library
+Package: libubuntutoolki
+Architecture: any
+Multi-Arch: same
+Pre-Depends: dpkg (>= 1.15.6~), ${misc:Pre-Depends}
+Depends: ${misc:Depends},
+ ${shlibs:Depends},
+Description: Ubuntu toolkit common library private development files
+ This package contains the private development files for
+ Ubuntu toolkit common library
+
Package: ubuntu-
Architecture: any
Multi-Arch: foreign
=== added file 'debian/
--- debian/
+++ debian/
@@ -0,0 +1,1 @@
+usr/include/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1871
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Benjamin Zeller (zeller-benjamin) wrote : | # |
Perfect, can go in now!
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
None: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
FAILED: Continuous integration, rev:1871
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 1872. By Zsombor Egri
-
staging sync
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
SUCCESS: https:/
None: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
ubuntu-sdk-build-bot (ubuntu-sdk-build-bot) wrote : | # |
PASSED: Continuous integration, rev:1872
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2016-02-11 16:17:46 +0000 |
3 | +++ debian/control 2016-03-01 10:45:34 +0000 |
4 | @@ -139,6 +139,16 @@ |
5 | This package contains the development files for |
6 | Ubuntu toolkit common library |
7 | |
8 | +Package: libubuntutoolkit5-private-dev |
9 | +Architecture: any |
10 | +Multi-Arch: same |
11 | +Pre-Depends: dpkg (>= 1.15.6~), ${misc:Pre-Depends} |
12 | +Depends: ${misc:Depends}, |
13 | + ${shlibs:Depends}, |
14 | +Description: Ubuntu toolkit common library private development files |
15 | + This package contains the private development files for |
16 | + Ubuntu toolkit common library |
17 | + |
18 | Package: ubuntu-ui-toolkit-theme |
19 | Architecture: any |
20 | Multi-Arch: foreign |
21 | |
22 | === modified file 'debian/libubuntutoolkit5-dev.install' |
23 | --- debian/libubuntutoolkit5-dev.install 2016-02-12 08:52:18 +0000 |
24 | +++ debian/libubuntutoolkit5-dev.install 2016-03-01 10:45:34 +0000 |
25 | @@ -1,3 +1,5 @@ |
26 | +usr/include/*/qt5/UbuntuToolkit/AsyncLoader |
27 | +usr/include/*/qt5/UbuntuToolkit/asyncloader.h |
28 | usr/include/*/qt5/UbuntuToolkit/ColorUtils |
29 | usr/include/*/qt5/UbuntuToolkit/colorutils.h |
30 | usr/include/*/qt5/UbuntuToolkit/Tree |
31 | |
32 | === added file 'debian/libubuntutoolkit5-private-dev.install' |
33 | --- debian/libubuntutoolkit5-private-dev.install 1970-01-01 00:00:00 +0000 |
34 | +++ debian/libubuntutoolkit5-private-dev.install 2016-03-01 10:45:34 +0000 |
35 | @@ -0,0 +1,1 @@ |
36 | +usr/include/*/qt5/UbuntuToolkit/*/UbuntuToolkit/private/*_p.h |
37 | |
38 | === modified file 'src/Ubuntu/Test/plugin/uctestcase.cpp' |
39 | --- src/Ubuntu/Test/plugin/uctestcase.cpp 2016-01-25 17:12:56 +0000 |
40 | +++ src/Ubuntu/Test/plugin/uctestcase.cpp 2016-03-01 10:45:34 +0000 |
41 | @@ -76,3 +76,16 @@ |
42 | QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); |
43 | } |
44 | } |
45 | + |
46 | +/*! |
47 | + * Same as previous but without column number |
48 | + */ |
49 | +void UbuntuTestCase::ignoreWarning(const QString& fileName, uint line, |
50 | + const QString& message, uint occurences) |
51 | +{ |
52 | + for (uint i = 0; i < occurences; i++) { |
53 | + QString url(QUrl::fromLocalFile(QFileInfo(fileName).absoluteFilePath()).toEncoded()); |
54 | + QString warning(QString("%1:%2 %3").arg(url).arg(line).arg(message)); |
55 | + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); |
56 | + } |
57 | +} |
58 | |
59 | === modified file 'src/Ubuntu/Test/plugin/uctestcase.h' |
60 | --- src/Ubuntu/Test/plugin/uctestcase.h 2016-01-25 17:12:56 +0000 |
61 | +++ src/Ubuntu/Test/plugin/uctestcase.h 2016-03-01 10:45:34 +0000 |
62 | @@ -54,6 +54,7 @@ |
63 | } |
64 | |
65 | static void ignoreWarning(const QString& fileName, uint line, uint column, const QString& message, uint occurences=1); |
66 | + static void ignoreWarning(const QString& fileName, uint line, const QString& message, uint occurences=1); |
67 | |
68 | static inline void waitForSignal(QSignalSpy *spy, int timeout = 5000) |
69 | { |
70 | |
71 | === modified file 'src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro' |
72 | --- src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro 2016-02-11 17:19:48 +0000 |
73 | +++ src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro 2016-03-01 10:45:34 +0000 |
74 | @@ -15,8 +15,11 @@ |
75 | HEADERS += \ |
76 | colorutils.h \ |
77 | ubuntutoolkitglobal.h \ |
78 | - tree.h |
79 | + tree.h \ |
80 | + asyncloader.h \ |
81 | + asyncloader_p.h |
82 | |
83 | SOURCES += \ |
84 | colorutils.cpp \ |
85 | - tree.cpp |
86 | + tree.cpp \ |
87 | + asyncloader.cpp |
88 | |
89 | === added file 'src/Ubuntu/UbuntuToolkit/asyncloader.cpp' |
90 | --- src/Ubuntu/UbuntuToolkit/asyncloader.cpp 1970-01-01 00:00:00 +0000 |
91 | +++ src/Ubuntu/UbuntuToolkit/asyncloader.cpp 2016-03-01 10:45:34 +0000 |
92 | @@ -0,0 +1,222 @@ |
93 | +/* |
94 | + * Copyright 2016 Canonical Ltd. |
95 | + * |
96 | + * This program is free software; you can redistribute it and/or modify |
97 | + * it under the terms of the GNU Lesser General Public License as published by |
98 | + * the Free Software Foundation; version 3. |
99 | + * |
100 | + * This program is distributed in the hope that it will be useful, |
101 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
102 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
103 | + * GNU Lesser General Public License for more details. |
104 | + * |
105 | + * You should have received a copy of the GNU Lesser General Public License |
106 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
107 | + * |
108 | + * Author: Zsombor Egri <zsombor.egri@canonical.com> |
109 | + */ |
110 | + |
111 | +#include "asyncloader_p.h" |
112 | + |
113 | +#include <QtQml/QQmlContext> |
114 | +#include <QtQml/QQmlComponent> |
115 | +#include <QtQuick/QQuickItem> |
116 | + |
117 | +namespace UbuntuToolkit { |
118 | + |
119 | +AsyncLoader::AsyncLoader(QObject *parent) |
120 | + : QObject(*(new AsyncLoaderPrivate), parent) |
121 | +{ |
122 | +} |
123 | + |
124 | +AsyncLoader::~AsyncLoader() |
125 | +{ |
126 | + reset(); |
127 | +} |
128 | + |
129 | +// incubator methods |
130 | +void AsyncLoaderPrivate::setInitialState(QObject *object) |
131 | +{ |
132 | + emitStatus(AsyncLoader::Initializing, object); |
133 | +} |
134 | + |
135 | +AsyncLoader::LoadingStatus incubatorToLoadingStatus(QQmlIncubator::Status status) |
136 | +{ |
137 | + switch (status) { |
138 | + case QQmlIncubator::Null: return AsyncLoader::Null; |
139 | + case QQmlIncubator::Ready: return AsyncLoader::Ready; |
140 | + case QQmlIncubator::Loading: return AsyncLoader::Loading; |
141 | + case QQmlIncubator::Error: return AsyncLoader::Error; |
142 | + } |
143 | + // unlikely to be reached, but must satisfy compiler |
144 | + return AsyncLoader::Null; |
145 | +} |
146 | + |
147 | +void AsyncLoaderPrivate::statusChanged(Status status) |
148 | +{ |
149 | + if (status == QQmlIncubator::Error) { |
150 | + QList<QQmlError> e = errors(); |
151 | + for (int i = 0; i < e.size(); i++) { |
152 | + // remove quotes and any leading/trailing whitespace |
153 | + qWarning().noquote() << e[0].toString().trimmed(); |
154 | + } |
155 | + } |
156 | + if (status != QQmlIncubator::Loading) { |
157 | + detachComponent(); |
158 | + } |
159 | + // we should emit the status change only after we do the cleanup |
160 | + emitStatus(incubatorToLoadingStatus(status)); |
161 | +} |
162 | + |
163 | +// procected methods |
164 | +void AsyncLoaderPrivate::emitStatus(AsyncLoader::LoadingStatus status, QObject *object) |
165 | +{ |
166 | + if (this->status == status) { |
167 | + return; |
168 | + } |
169 | + |
170 | + this->status = status; |
171 | + if (!object) { |
172 | + object = this->object(); |
173 | + } |
174 | + Q_EMIT q_func()->loadingStatus(this->status, object); |
175 | +} |
176 | + |
177 | +void AsyncLoaderPrivate::detachComponent() |
178 | +{ |
179 | + if (!component) { |
180 | + return; |
181 | + } |
182 | + |
183 | + Q_Q(AsyncLoader); |
184 | + if (componentHandler) { |
185 | + QObject::disconnect(*componentHandler); |
186 | + } |
187 | + componentHandler.reset(); |
188 | + if (ownComponent) { |
189 | + component->deleteLater(); |
190 | + } |
191 | + component = nullptr; |
192 | + ownComponent = false; |
193 | +} |
194 | + |
195 | +void AsyncLoaderPrivate::onComponentStatusChanged(QQmlComponent::Status status) |
196 | +{ |
197 | + if (status == QQmlComponent::Error) { |
198 | + QString error = component->errorString(); |
199 | + // remove quotes and any leading/trailing whitespace |
200 | + qWarning().noquote() << error.trimmed(); |
201 | + detachComponent(); |
202 | + emitStatus(AsyncLoader::Error); |
203 | + return; |
204 | + } |
205 | + if (status == QQmlComponent::Ready) { |
206 | + component->create(*this, context); |
207 | + } |
208 | +} |
209 | + |
210 | +/*! |
211 | + * \brief AsyncLoader::load |
212 | + * \param url |
213 | + * \param context |
214 | + * \return bool |
215 | + * The method initiates the loading of a given \e url within a specific \e context. |
216 | + * Returns true on success. |
217 | + * \note If the loading is initiated while there is a previous loading in place, |
218 | + * you must make sure you delete the object from the previous loading before you |
219 | + * trigger the new load. |
220 | + */ |
221 | +bool AsyncLoader::load(const QUrl &url, QQmlContext *context) |
222 | +{ |
223 | + if (!reset() || !context) { |
224 | + return false; |
225 | + } |
226 | + Q_D(AsyncLoader); |
227 | + if (url.isEmpty() || !url.isValid()) { |
228 | + d->emitStatus(Ready); |
229 | + return false; |
230 | + } |
231 | + d->ownComponent = true; |
232 | + return load(new QQmlComponent(context->engine(), url, QQmlComponent::Asynchronous), context); |
233 | +} |
234 | + |
235 | +/*! |
236 | + * \brief AsyncLoader::load |
237 | + * \param component |
238 | + * \param context |
239 | + * \return bool |
240 | + * The method initiates the loading of a \e component within the given \e context. |
241 | + * Returns true on success. |
242 | + * \note If the loading is initiated while there is a previous loading in place, |
243 | + * you must make sure you delete the object from the previous loading before you |
244 | + * trigger the new load. |
245 | + */ |
246 | +bool AsyncLoader::load(QQmlComponent *component, QQmlContext *context) |
247 | +{ |
248 | + if (!reset() || !context) { |
249 | + return false; |
250 | + } |
251 | + Q_D(AsyncLoader); |
252 | + if (!component) { |
253 | + d->emitStatus(Ready); |
254 | + return false; |
255 | + } |
256 | + d->component = component; |
257 | + d->context = context; |
258 | + if (d->component->isLoading()) { |
259 | + d->emitStatus(Compiling); |
260 | + auto callback = [d] (QQmlComponent::Status status) { |
261 | + d->onComponentStatusChanged(status); |
262 | + }; |
263 | + |
264 | + d->componentHandler.reset(new QMetaObject::Connection); |
265 | + *(d->componentHandler) = QObject::connect(d->component, &QQmlComponent::statusChanged, callback); |
266 | + } else { |
267 | + d->onComponentStatusChanged(d->component->status()); |
268 | + } |
269 | + return true; |
270 | +} |
271 | + |
272 | +/*! |
273 | + * \brief AsyncLoader::reset |
274 | + * \return bool |
275 | + * Clears the incubator and emits loadingStatus() signal with \c Reset status. |
276 | + * The loader can be reset only if the status passed \c Loading. Returns true |
277 | + * if the reset was successful, or when the loader status is \c Ready or |
278 | + * \c Error. |
279 | + */ |
280 | +bool AsyncLoader::reset() |
281 | +{ |
282 | + Q_D(AsyncLoader); |
283 | + if (d->status < Loading) { |
284 | + return false; |
285 | + } |
286 | + if (d->status >= Ready) { |
287 | + return true; |
288 | + } |
289 | + d->clear(); |
290 | + // make sure the listeners are getting the reset so they can delete the object |
291 | + d->emitStatus(Reset); |
292 | + return true; |
293 | +} |
294 | + |
295 | +/*! |
296 | + * \brief AsyncLoader::status |
297 | + * \return LoadingStatus |
298 | + * Returns the status of the loader. |
299 | + */ |
300 | +AsyncLoader::LoadingStatus AsyncLoader::status() |
301 | +{ |
302 | + return d_func()->status; |
303 | +} |
304 | + |
305 | +/*! |
306 | + * \brief AsyncLoader::forceCompletion |
307 | + * Forces loading completion. |
308 | + */ |
309 | +void AsyncLoader::forceCompletion() |
310 | +{ |
311 | + d_func()->forceCompletion(); |
312 | +} |
313 | + |
314 | +} // namespace UbuntuToolkit |
315 | |
316 | === added file 'src/Ubuntu/UbuntuToolkit/asyncloader.h' |
317 | --- src/Ubuntu/UbuntuToolkit/asyncloader.h 1970-01-01 00:00:00 +0000 |
318 | +++ src/Ubuntu/UbuntuToolkit/asyncloader.h 2016-03-01 10:45:34 +0000 |
319 | @@ -0,0 +1,63 @@ |
320 | +/* |
321 | + * Copyright 2016 Canonical Ltd. |
322 | + * |
323 | + * This program is free software; you can redistribute it and/or modify |
324 | + * it under the terms of the GNU Lesser General Public License as published by |
325 | + * the Free Software Foundation; version 3. |
326 | + * |
327 | + * This program is distributed in the hope that it will be useful, |
328 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
329 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
330 | + * GNU Lesser General Public License for more details. |
331 | + * |
332 | + * You should have received a copy of the GNU Lesser General Public License |
333 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
334 | + * |
335 | + * Author: Zsombor Egri <zsombor.egri@canonical.com> |
336 | + */ |
337 | + |
338 | +#ifndef ASYNCLOADER_H |
339 | +#define ASYNCLOADER_H |
340 | + |
341 | +#include <QtQml/QQmlComponent> |
342 | +#include <ubuntutoolkitglobal.h> |
343 | + |
344 | +class QQuickItem; |
345 | +class QQmlContext; |
346 | + |
347 | +namespace UbuntuToolkit { |
348 | + |
349 | +class AsyncLoaderPrivate; |
350 | +class UBUNTUTOOLKIT_EXPORT AsyncLoader : public QObject |
351 | +{ |
352 | + Q_OBJECT |
353 | +public: |
354 | + enum LoadingStatus { |
355 | + Null, |
356 | + Compiling, |
357 | + Loading, |
358 | + Initializing, |
359 | + Ready, |
360 | + Error, |
361 | + Reset |
362 | + }; |
363 | + |
364 | + explicit AsyncLoader(QObject *parent = 0); |
365 | + ~AsyncLoader(); |
366 | + |
367 | + bool load(const QUrl &url, QQmlContext *context); |
368 | + bool load(QQmlComponent *component, QQmlContext *context); |
369 | + bool reset(); |
370 | + LoadingStatus status(); |
371 | + void forceCompletion(); |
372 | + |
373 | +Q_SIGNALS: |
374 | + void loadingStatus(LoadingStatus status, QObject *object); |
375 | + |
376 | +protected: |
377 | + Q_DECLARE_PRIVATE(AsyncLoader) |
378 | +}; |
379 | + |
380 | +} // namespace UbuntuToolkit |
381 | + |
382 | +#endif // ASYNCLOADER_H |
383 | |
384 | === added file 'src/Ubuntu/UbuntuToolkit/asyncloader_p.h' |
385 | --- src/Ubuntu/UbuntuToolkit/asyncloader_p.h 1970-01-01 00:00:00 +0000 |
386 | +++ src/Ubuntu/UbuntuToolkit/asyncloader_p.h 2016-03-01 10:45:34 +0000 |
387 | @@ -0,0 +1,54 @@ |
388 | +/* |
389 | + * Copyright 2016 Canonical Ltd. |
390 | + * |
391 | + * This program is free software; you can redistribute it and/or modify |
392 | + * it under the terms of the GNU Lesser General Public License as published by |
393 | + * the Free Software Foundation; version 3. |
394 | + * |
395 | + * This program is distributed in the hope that it will be useful, |
396 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
397 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
398 | + * GNU Lesser General Public License for more details. |
399 | + * |
400 | + * You should have received a copy of the GNU Lesser General Public License |
401 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
402 | + * |
403 | + * Author: Zsombor Egri <zsombor.egri@canonical.com> |
404 | + */ |
405 | + |
406 | +#ifndef ASYNCLOADER_P_H |
407 | +#define ASYNCLOADER_P_H |
408 | + |
409 | +#include <QtCore/private/qobject_p.h> |
410 | +#include <QtQml/QQmlIncubator> |
411 | +#include <AsyncLoader> |
412 | + |
413 | +namespace UbuntuToolkit { |
414 | + |
415 | +class AsyncLoaderPrivate : public QObjectPrivate, public QQmlIncubator |
416 | +{ |
417 | + Q_DECLARE_PUBLIC(AsyncLoader) |
418 | +public: |
419 | + AsyncLoaderPrivate() |
420 | + : QObjectPrivate() |
421 | + , QQmlIncubator(Asynchronous) |
422 | + {} |
423 | + |
424 | + QSharedPointer<QMetaObject::Connection> componentHandler; |
425 | + QQmlComponent *component = nullptr; |
426 | + QQmlContext *context = nullptr; |
427 | + AsyncLoader::LoadingStatus status = AsyncLoader::Ready; |
428 | + bool ownComponent = false; |
429 | + |
430 | + void setInitialState(QObject *object) override; |
431 | + void statusChanged(Status status) override; |
432 | + |
433 | + void emitStatus(AsyncLoader::LoadingStatus status, QObject *object = 0); |
434 | + void onComponentStatusChanged(QQmlComponent::Status status); |
435 | + void detachComponent(); |
436 | +}; |
437 | + |
438 | +} // namespace UbuntuToolkit |
439 | + |
440 | +#endif // ASYNCLOADER_P_H |
441 | + |
442 | |
443 | === modified file 'tests/unit/plugin_dependency.pri' |
444 | --- tests/unit/plugin_dependency.pri 2015-12-21 12:18:50 +0000 |
445 | +++ tests/unit/plugin_dependency.pri 2016-03-01 10:45:34 +0000 |
446 | @@ -9,6 +9,7 @@ |
447 | LIBS += -L$$PLUGIN_BLD/Components -lUbuntuComponents |
448 | LIBS += -L$$PLUGIN_BLD/Test -lUbuntuTest |
449 | LIBS += -L$${ROOT_BUILD_DIR}/lib -lUbuntuGestures |
450 | +#LIBS += -L$${ROOT_BUILD_DIR}/lib -lUbuntuToolkit |
451 | DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\" |
452 | QMAKE_CXXFLAGS += -Werror |
453 | |
454 | |
455 | === modified file 'tests/unit/test-include.pri' |
456 | --- tests/unit/test-include.pri 2016-02-25 11:56:23 +0000 |
457 | +++ tests/unit/test-include.pri 2016-03-01 10:45:34 +0000 |
458 | @@ -3,6 +3,6 @@ |
459 | |
460 | TEMPLATE = app |
461 | QT += testlib qml quick |
462 | -CONFIG += no_keywords C++11 |
463 | +CONFIG += no_keywords c++11 |
464 | |
465 | |
466 | |
467 | === added directory 'tests/unit_x11/tst_asyncloader' |
468 | === added file 'tests/unit_x11/tst_asyncloader/Document.qml' |
469 | --- tests/unit_x11/tst_asyncloader/Document.qml 1970-01-01 00:00:00 +0000 |
470 | +++ tests/unit_x11/tst_asyncloader/Document.qml 2016-03-01 10:45:34 +0000 |
471 | @@ -0,0 +1,31 @@ |
472 | +/* |
473 | + * Copyright 2016 Canonical Ltd. |
474 | + * |
475 | + * This program is free software; you can redistribute it and/or modify |
476 | + * it under the terms of the GNU Lesser General Public License as published by |
477 | + * the Free Software Foundation; version 3. |
478 | + * |
479 | + * This program is distributed in the hope that it will be useful, |
480 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
481 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
482 | + * GNU Lesser General Public License for more details. |
483 | + * |
484 | + * You should have received a copy of the GNU Lesser General Public License |
485 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
486 | + * |
487 | + */ |
488 | + |
489 | +import QtQuick 2.4 |
490 | +import Ubuntu.Components 1.3 |
491 | + |
492 | +Column { |
493 | + anchors.fill: parent |
494 | + spacing: 1 |
495 | + Repeater { |
496 | + model: 500 |
497 | + TextField { |
498 | + width: parent.width |
499 | + } |
500 | + } |
501 | +} |
502 | + |
503 | |
504 | === added file 'tests/unit_x11/tst_asyncloader/FaultyDocument.qml' |
505 | --- tests/unit_x11/tst_asyncloader/FaultyDocument.qml 1970-01-01 00:00:00 +0000 |
506 | +++ tests/unit_x11/tst_asyncloader/FaultyDocument.qml 2016-03-01 10:45:34 +0000 |
507 | @@ -0,0 +1,20 @@ |
508 | +/* |
509 | + * Copyright 2016 Canonical Ltd. |
510 | + * |
511 | + * This program is free software; you can redistribute it and/or modify |
512 | + * it under the terms of the GNU Lesser General Public License as published by |
513 | + * the Free Software Foundation; version 3. |
514 | + * |
515 | + * This program is distributed in the hope that it will be useful, |
516 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
517 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
518 | + * GNU Lesser General Public License for more details. |
519 | + * |
520 | + * You should have received a copy of the GNU Lesser General Public License |
521 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
522 | + * |
523 | + */ |
524 | + |
525 | +import QtQuick 2.4 |
526 | + |
527 | +Label {} |
528 | |
529 | === added file 'tests/unit_x11/tst_asyncloader/HeavyDocument.qml' |
530 | --- tests/unit_x11/tst_asyncloader/HeavyDocument.qml 1970-01-01 00:00:00 +0000 |
531 | +++ tests/unit_x11/tst_asyncloader/HeavyDocument.qml 2016-03-01 10:45:34 +0000 |
532 | @@ -0,0 +1,31 @@ |
533 | +/* |
534 | + * Copyright 2016 Canonical Ltd. |
535 | + * |
536 | + * This program is free software; you can redistribute it and/or modify |
537 | + * it under the terms of the GNU Lesser General Public License as published by |
538 | + * the Free Software Foundation; version 3. |
539 | + * |
540 | + * This program is distributed in the hope that it will be useful, |
541 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
542 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
543 | + * GNU Lesser General Public License for more details. |
544 | + * |
545 | + * You should have received a copy of the GNU Lesser General Public License |
546 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
547 | + * |
548 | + */ |
549 | + |
550 | +import QtQuick 2.4 |
551 | +import Ubuntu.Components 1.3 |
552 | + |
553 | +Column { |
554 | + anchors.fill: parent |
555 | + spacing: units.dp(1) |
556 | + Repeater { |
557 | + model: 500 |
558 | + TextField { |
559 | + width: parent.width |
560 | + } |
561 | + } |
562 | +} |
563 | + |
564 | |
565 | === added file 'tests/unit_x11/tst_asyncloader/TestApp.qml' |
566 | --- tests/unit_x11/tst_asyncloader/TestApp.qml 1970-01-01 00:00:00 +0000 |
567 | +++ tests/unit_x11/tst_asyncloader/TestApp.qml 2016-03-01 10:45:34 +0000 |
568 | @@ -0,0 +1,22 @@ |
569 | +/* |
570 | + * Copyright 2016 Canonical Ltd. |
571 | + * |
572 | + * This program is free software; you can redistribute it and/or modify |
573 | + * it under the terms of the GNU Lesser General Public License as published by |
574 | + * the Free Software Foundation; version 3. |
575 | + * |
576 | + * This program is distributed in the hope that it will be useful, |
577 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
578 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
579 | + * GNU Lesser General Public License for more details. |
580 | + * |
581 | + * You should have received a copy of the GNU Lesser General Public License |
582 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
583 | + * |
584 | + */ |
585 | + |
586 | +import QtQuick 2.4 |
587 | + |
588 | +Item { |
589 | + |
590 | +} |
591 | |
592 | === added file 'tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp' |
593 | --- tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp 1970-01-01 00:00:00 +0000 |
594 | +++ tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp 2016-03-01 10:45:34 +0000 |
595 | @@ -0,0 +1,288 @@ |
596 | +/* |
597 | + * Copyright 2016 Canonical Ltd. |
598 | + * |
599 | + * This program is free software; you can redistribute it and/or modify |
600 | + * it under the terms of the GNU Lesser General Public License as published by |
601 | + * the Free Software Foundation; version 3. |
602 | + * |
603 | + * This program is distributed in the hope that it will be useful, |
604 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
605 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
606 | + * GNU Lesser General Public License for more details. |
607 | + * |
608 | + * You should have received a copy of the GNU Lesser General Public License |
609 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
610 | + * |
611 | + */ |
612 | + |
613 | +#include <QtTest/QtTest> |
614 | +#include "uctestcase.h" |
615 | +#include "uctestextras.h" |
616 | +#include <AsyncLoader> |
617 | +#include <functional> |
618 | +#include <QtQml/QQmlEngine> |
619 | + |
620 | +class LoaderSpy : public QObject |
621 | +{ |
622 | + Q_OBJECT |
623 | +public: |
624 | + UbuntuToolkit::AsyncLoader *m_loader; |
625 | + QScopedPointer<QObject> m_object; |
626 | + bool m_done = false; |
627 | + bool m_error = false; |
628 | + QList<UbuntuToolkit::AsyncLoader::LoadingStatus> m_statusList; |
629 | +public: |
630 | + LoaderSpy(UbuntuToolkit::AsyncLoader *loader) |
631 | + : QObject(0) |
632 | + , m_loader(loader) |
633 | + { |
634 | + connect(loader, &UbuntuToolkit::AsyncLoader::loadingStatus, |
635 | + this, &LoaderSpy::onLoadingStatusChanged); |
636 | + } |
637 | + |
638 | +protected Q_SLOTS: |
639 | + virtual void onLoadingStatusChanged(UbuntuToolkit::AsyncLoader::LoadingStatus status, QObject *object) |
640 | + { |
641 | + m_statusList << status; |
642 | + if (status == UbuntuToolkit::AsyncLoader::Ready) { |
643 | + m_done = true; |
644 | + m_object.reset(object); |
645 | + } |
646 | + if (status == UbuntuToolkit::AsyncLoader::Error) { |
647 | + m_error = true; |
648 | + } |
649 | + } |
650 | +}; |
651 | + |
652 | +class ResetLoaderSpy : public LoaderSpy |
653 | +{ |
654 | + Q_OBJECT |
655 | +public: |
656 | + bool m_reset = false; |
657 | +public: |
658 | + ResetLoaderSpy(UbuntuToolkit::AsyncLoader *loader) |
659 | + : LoaderSpy(loader) |
660 | + { |
661 | + } |
662 | + |
663 | + void onLoadingStatusChanged(UbuntuToolkit::AsyncLoader::LoadingStatus status, QObject *object) override |
664 | + { |
665 | + if (status == UbuntuToolkit::AsyncLoader::Loading) { |
666 | + m_loader->reset(); |
667 | + m_reset = true; |
668 | + } |
669 | + LoaderSpy::onLoadingStatusChanged(status, object); |
670 | + } |
671 | +}; |
672 | + |
673 | +class SecondLoaderSpy : public LoaderSpy |
674 | +{ |
675 | + Q_OBJECT |
676 | +public: |
677 | + bool m_loadResult = false; |
678 | +public: |
679 | + SecondLoaderSpy(UbuntuToolkit::AsyncLoader *loader, UbuntuToolkit::AsyncLoader::LoadingStatus loadAt, |
680 | + const QUrl &url, QQmlContext *context) |
681 | + : LoaderSpy(loader) |
682 | + , m_loadAt(loadAt) |
683 | + , m_url(url) |
684 | + , m_context(context) |
685 | + { |
686 | + } |
687 | + |
688 | + void onLoadingStatusChanged(UbuntuToolkit::AsyncLoader::LoadingStatus status, QObject *object) override |
689 | + { |
690 | + if (status == (UbuntuToolkit::AsyncLoader::LoadingStatus)m_loadAt) { |
691 | + m_loadAt = -1; |
692 | + delete object; |
693 | + object = nullptr; |
694 | + m_loadResult = m_loader->load(m_url, m_context); |
695 | + } |
696 | + LoaderSpy::onLoadingStatusChanged(status, object); |
697 | + } |
698 | + |
699 | +private: |
700 | + int m_loadAt; |
701 | + QUrl m_url; |
702 | + QQmlContext *m_context; |
703 | +}; |
704 | + |
705 | +/******************************************************************** |
706 | + * Test |
707 | + ********************************************************************/ |
708 | +class tst_AsyncLoader : public QObject |
709 | +{ |
710 | + Q_OBJECT |
711 | +private Q_SLOTS: |
712 | + |
713 | + void test_load_data() |
714 | + { |
715 | + QTest::addColumn<bool>("loadAsDocument"); |
716 | + QTest::addColumn<QString>("document"); |
717 | + QTest::addColumn<int>("mode"); |
718 | + QTest::addColumn< QList<int> >("statuses"); |
719 | + |
720 | + QTest::newRow("document") << true << "Document.qml" << (int)QQmlComponent::Asynchronous |
721 | + << (QList<int>() |
722 | + << UbuntuToolkit::AsyncLoader::Compiling |
723 | + << UbuntuToolkit::AsyncLoader::Loading |
724 | + << UbuntuToolkit::AsyncLoader::Initializing |
725 | + << UbuntuToolkit::AsyncLoader::Ready |
726 | + ); |
727 | + QTest::newRow("component, asynchronous") << false << "Document.qml" << (int)QQmlComponent::Asynchronous |
728 | + << (QList<int>() |
729 | + << UbuntuToolkit::AsyncLoader::Compiling |
730 | + << UbuntuToolkit::AsyncLoader::Loading |
731 | + << UbuntuToolkit::AsyncLoader::Initializing |
732 | + << UbuntuToolkit::AsyncLoader::Ready |
733 | + ); |
734 | + QTest::newRow("component, synchronous") << false << "Document.qml" << (int)QQmlComponent::PreferSynchronous |
735 | + << (QList<int>() |
736 | + << UbuntuToolkit::AsyncLoader::Loading |
737 | + << UbuntuToolkit::AsyncLoader::Initializing |
738 | + << UbuntuToolkit::AsyncLoader::Ready |
739 | + ); |
740 | + } |
741 | + void test_load() |
742 | + { |
743 | + QFETCH(bool, loadAsDocument); |
744 | + QFETCH(QString, document); |
745 | + QFETCH(int, mode); |
746 | + QFETCH(QList<int>, statuses); |
747 | + |
748 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
749 | + UbuntuToolkit::AsyncLoader loader; |
750 | + LoaderSpy spy(&loader); |
751 | + QScopedPointer<QQmlComponent> component; |
752 | + |
753 | + if (loadAsDocument) { |
754 | + loader.load(QUrl::fromLocalFile(document), view->rootContext()); |
755 | + } else { |
756 | + // create a component |
757 | + component.reset(new QQmlComponent(view->engine(), QUrl::fromLocalFile(document), (QQmlComponent::CompilationMode)mode)); |
758 | + loader.load(component.data(), view->rootContext()); |
759 | + } |
760 | + QTRY_VERIFY(spy.m_object != nullptr); |
761 | + // check the statuses |
762 | + QCOMPARE(spy.m_statusList.length(), statuses.length()); |
763 | + for (int i = 0; i < spy.m_statusList.length(); i++) { |
764 | + QVERIFY2((int)spy.m_statusList[i] == statuses[i], (QString(" Status at index %1 differs").arg(i)).toLocal8Bit().constData()); |
765 | + } |
766 | + } |
767 | + |
768 | + void test_load_with_error() |
769 | + { |
770 | + QUrl document = QUrl::fromLocalFile("FaultyDocument.qml"); |
771 | + UbuntuTestCase::ignoreWarning("FaultyDocument.qml", 20, "Label is not a type"); |
772 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
773 | + UbuntuToolkit::AsyncLoader loader; |
774 | + LoaderSpy spy(&loader); |
775 | + loader.load(document, view->rootContext()); |
776 | + QTRY_VERIFY(spy.m_error == true); |
777 | + } |
778 | + |
779 | + void test_load_no_context() |
780 | + { |
781 | + UbuntuToolkit::AsyncLoader loader; |
782 | + QVERIFY(!loader.load(nullptr, nullptr)); |
783 | + QVERIFY(!loader.load(QUrl(), nullptr)); |
784 | + } |
785 | + |
786 | + void test_load_invalid_url() |
787 | + { |
788 | + QQmlEngine engine; |
789 | + UbuntuToolkit::AsyncLoader loader; |
790 | + LoaderSpy spy(&loader); |
791 | + QVERIFY(!loader.load(QUrl(), engine.rootContext())); |
792 | + } |
793 | + |
794 | + void test_load_null_component() |
795 | + { |
796 | + QQmlEngine engine; |
797 | + UbuntuToolkit::AsyncLoader loader; |
798 | + LoaderSpy spy(&loader); |
799 | + QVERIFY(!loader.load(nullptr, engine.rootContext())); |
800 | + } |
801 | + |
802 | + void test_load_and_cancel_data() |
803 | + { |
804 | + QTest::addColumn<bool>("loadAsDocument"); |
805 | + QTest::addColumn<QString>("document"); |
806 | + QTest::addColumn<int>("mode"); |
807 | + |
808 | + QTest::newRow("document") << true << "HeavyDocument.qml" << (int)QQmlComponent::Asynchronous; |
809 | + QTest::newRow("component, asynchronous") << false << "HeavyDocument.qml" << (int)QQmlComponent::Asynchronous; |
810 | + QTest::newRow("component, synchronous") << false << "HeavyDocument.qml" << (int)QQmlComponent::PreferSynchronous; |
811 | + } |
812 | + void test_load_and_cancel() |
813 | + { |
814 | + QFETCH(bool, loadAsDocument); |
815 | + QFETCH(QString, document); |
816 | + QFETCH(int, mode); |
817 | + |
818 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
819 | + UbuntuToolkit::AsyncLoader loader; |
820 | + ResetLoaderSpy spy(&loader); |
821 | + QScopedPointer<QQmlComponent> component; |
822 | + |
823 | + if (loadAsDocument) { |
824 | + loader.load(QUrl::fromLocalFile(document), view->rootContext()); |
825 | + } else { |
826 | + // create a component |
827 | + component.reset(new QQmlComponent(view->engine(), QUrl::fromLocalFile(document), (QQmlComponent::CompilationMode)mode)); |
828 | + loader.load(component.data(), view->rootContext()); |
829 | + } |
830 | + if (loader.status() < UbuntuToolkit::AsyncLoader::Loading) { |
831 | + // cannot reset yet! |
832 | + QVERIFY(!loader.reset()); |
833 | + } |
834 | + QTRY_VERIFY(spy.m_reset); |
835 | + } |
836 | + |
837 | + void test_second_load_scenarios_data() |
838 | + { |
839 | + QTest::addColumn<QString> ("doc1"); |
840 | + QTest::addColumn<QString> ("doc2"); |
841 | + QTest::addColumn<int> ("when"); |
842 | + QTest::addColumn<bool> ("success"); |
843 | + |
844 | + QTest::newRow("status = Compiling") |
845 | + << "Document.qml" << "HeavyDocument.qml" |
846 | + << (int)UbuntuToolkit::AsyncLoader::Compiling << false; |
847 | + QTest::newRow("status = Loading") |
848 | + << "Document.qml" << "HeavyDocument.qml" |
849 | + << (int)UbuntuToolkit::AsyncLoader::Loading << true; |
850 | + QTest::newRow("status = Initializing") |
851 | + << "Document.qml" << "HeavyDocument.qml" |
852 | + << (int)UbuntuToolkit::AsyncLoader::Initializing << true; |
853 | + QTest::newRow("status = Ready") |
854 | + << "Document.qml" << "HeavyDocument.qml" |
855 | + << (int)UbuntuToolkit::AsyncLoader::Ready << true; |
856 | + QTest::newRow("status = Error") |
857 | + << "FaultyDocument.qml" << "HeavyDocument.qml" |
858 | + << (int)UbuntuToolkit::AsyncLoader::Error << true; |
859 | + } |
860 | + void test_second_load_scenarios() |
861 | + { |
862 | + QFETCH(QString, doc1); |
863 | + QFETCH(QString, doc2); |
864 | + QFETCH(int, when); |
865 | + QFETCH(bool, success); |
866 | + |
867 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
868 | + UbuntuToolkit::AsyncLoader loader; |
869 | + if (when == (int)UbuntuToolkit::AsyncLoader::Error) { |
870 | + UbuntuTestCase::ignoreWarning("FaultyDocument.qml", 20, "Label is not a type"); |
871 | + } |
872 | + |
873 | + SecondLoaderSpy spy(&loader, (UbuntuToolkit::AsyncLoader::LoadingStatus)when, QUrl::fromLocalFile(doc2), view->rootContext()); |
874 | + // load the first document |
875 | + QVERIFY(loader.load(QUrl::fromLocalFile(doc1), view->rootContext())); |
876 | + QTRY_VERIFY(spy.m_object != nullptr); |
877 | + QCOMPARE(spy.m_loadResult, success); |
878 | + } |
879 | +}; |
880 | + |
881 | +QTEST_MAIN(tst_AsyncLoader) |
882 | + |
883 | +#include "tst_asyncloader.moc" |
884 | |
885 | === added file 'tests/unit_x11/tst_asyncloader/tst_asyncloader.pro' |
886 | --- tests/unit_x11/tst_asyncloader/tst_asyncloader.pro 1970-01-01 00:00:00 +0000 |
887 | +++ tests/unit_x11/tst_asyncloader/tst_asyncloader.pro 2016-03-01 10:45:34 +0000 |
888 | @@ -0,0 +1,11 @@ |
889 | +include(../test-include.pri) |
890 | +QT += core-private qml-private quick-private gui-private UbuntuToolkit |
891 | + |
892 | +SOURCES += \ |
893 | + tst_asyncloader.cpp |
894 | + |
895 | +DISTFILES += \ |
896 | + Document.qml \ |
897 | + TestApp.qml \ |
898 | + HeavyDocument.qml \ |
899 | + FaultyDocument.qml |
900 | |
901 | === modified file 'tests/unit_x11/unit_x11.pro' |
902 | --- tests/unit_x11/unit_x11.pro 2015-11-23 16:12:16 +0000 |
903 | +++ tests/unit_x11/unit_x11.pro 2016-03-01 10:45:34 +0000 |
904 | @@ -17,4 +17,5 @@ |
905 | tst_subtheming \ |
906 | tst_swipearea \ |
907 | tst_touchregistry \ |
908 | - tst_bottomedge |
909 | + tst_bottomedge \ |
910 | + tst_asyncloader |
FAILED: Continuous integration, rev:1864 /jenkins. ubuntu. com/ubuntu- sdk/job/ ubuntu- ui-toolkit- ci-amd64- stable/ 347/ /jenkins. ubuntu. com/ubuntu- sdk/job/ generic- update- mp/1046/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /jenkins. ubuntu. com/ubuntu- sdk/job/ ubuntu- ui-toolkit- ci-amd64- stable/ 347/rebuild
https:/