Merge lp:~zsombi/ubuntu-ui-toolkit/bottomEdgePreloadsContent into lp:ubuntu-ui-toolkit/staging
- bottomEdgePreloadsContent
- Merge into staging
Proposed by
Zsombor Egri
Status: | Superseded |
---|---|
Proposed branch: | lp:~zsombi/ubuntu-ui-toolkit/bottomEdgePreloadsContent |
Merge into: | lp:ubuntu-ui-toolkit/staging |
Diff against target: |
990 lines (+771/-4) 19 files modified
examples/ubuntu-ui-toolkit-gallery/BottomEdgePage.qml (+1/-0) src/Ubuntu/Components/plugin/ucbottomedge.cpp (+58/-0) src/Ubuntu/Components/plugin/ucbottomedge.h (+7/-0) src/Ubuntu/Components/plugin/ucbottomedge_p.h (+9/-0) src/Ubuntu/Test/plugin/uctestcase.cpp (+13/-0) src/Ubuntu/Test/plugin/uctestcase.h (+1/-0) src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro (+4/-2) src/Ubuntu/UbuntuToolkit/asyncloader.cpp (+214/-0) src/Ubuntu/UbuntuToolkit/asyncloader.h (+71/-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 (+30/-0) tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp (+265/-0) tests/unit_x11/tst_asyncloader/tst_asyncloader.pro (+11/-0) tests/unit_x11/tst_bottomedge/tst_bottomedge.cpp (+1/-0) tests/unit_x11/unit_x11.pro (+2/-1) |
To merge this branch: | bzr merge lp:~zsombi/ubuntu-ui-toolkit/bottomEdgePreloadsContent |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu SDK team | Pending | ||
Review via email: mp+285756@code.launchpad.net |
Commit message
BorromEdge.
Description of the change
To post a comment you must log in.
- 1845. By Zsombor Egri
-
remove original asyncloader
- 1846. By Zsombor Egri
-
prereq merge
- 1847. By Zsombor Egri
-
prereq sync
- 1848. By Zsombor Egri
-
adjust AsyncLoader changes
- 1849. By Zsombor Egri
-
API updated
- 1850. By Zsombor Egri
-
remove enum
- 1851. By Zsombor Egri
-
make things nicer and unified
- 1852. By Zsombor Egri
-
use BottomEdge context when creating the content
- 1853. By Zsombor Egri
-
tests added, content handling fixed
- 1854. By Zsombor Egri
-
adjust tests with deprecation warning so those are not shown anymore
- 1855. By Zsombor Egri
-
prereq sync
- 1856. By Zsombor Egri
-
reshape gallery page
- 1857. By Zsombor Egri
-
prereq sync
- 1858. By Zsombor Egri
-
prereq sync
- 1859. By Zsombor Egri
-
turn off logs
- 1860. By Zsombor Egri
-
prereq sync
- 1861. By Zsombor Egri
-
prereq sync
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'examples/ubuntu-ui-toolkit-gallery/BottomEdgePage.qml' |
2 | --- examples/ubuntu-ui-toolkit-gallery/BottomEdgePage.qml 2016-01-13 16:07:58 +0000 |
3 | +++ examples/ubuntu-ui-toolkit-gallery/BottomEdgePage.qml 2016-02-19 14:39:50 +0000 |
4 | @@ -119,6 +119,7 @@ |
5 | flickable: page.flickable |
6 | } |
7 | contentComponent: bottomEdgeContent |
8 | + preloadContent: true |
9 | |
10 | onCommitCompleted: { |
11 | if (contentToLayout.checked && contentToLayout.enabled) { |
12 | |
13 | === modified file 'src/Ubuntu/Components/plugin/ucbottomedge.cpp' |
14 | --- src/Ubuntu/Components/plugin/ucbottomedge.cpp 2016-01-25 12:23:03 +0000 |
15 | +++ src/Ubuntu/Components/plugin/ucbottomedge.cpp 2016-02-19 14:39:50 +0000 |
16 | @@ -37,6 +37,8 @@ |
17 | #include "private/ucswipearea_p.h" |
18 | #include <QtQuick/private/qquickanimation_p.h> |
19 | |
20 | +using namespace UbuntuToolkit; |
21 | + |
22 | Q_LOGGING_CATEGORY(ucBottomEdge, "ubuntu.components.BottomEdge", QtMsgType::QtWarningMsg) |
23 | |
24 | #define LOG qCDebug(ucBottomEdge) << "[BottomEdge]" |
25 | @@ -47,6 +49,7 @@ |
26 | , hint(new UCBottomEdgeHint) |
27 | , contentComponent(Q_NULLPTR) |
28 | , bottomPanel(Q_NULLPTR) |
29 | + , loader(Q_NULLPTR) |
30 | , previousDistance(0.0) |
31 | , dragProgress(0.) |
32 | , status(UCBottomEdge::Hidden) |
33 | @@ -54,6 +57,7 @@ |
34 | , dragDirection(UCBottomEdge::Undefined) |
35 | , defaultRegionsReset(false) |
36 | , mousePressed(false) |
37 | + , preloadContent(false) |
38 | { |
39 | } |
40 | |
41 | @@ -1082,4 +1086,58 @@ |
42 | return d->activeRegion; |
43 | } |
44 | |
45 | +/*! |
46 | + * \qmlproperty bool BottomEdge::preloadContent |
47 | + * If set, all the contents set in the component and in regions will be loaded |
48 | + * in the background, so it will be available before it is revealed. |
49 | + */ |
50 | +bool UCBottomEdge::preloadContent() const |
51 | +{ |
52 | + return d_func()->preloadContent; |
53 | +} |
54 | +void UCBottomEdge::setPreloadContent(bool value) |
55 | +{ |
56 | + Q_D(UCBottomEdge); |
57 | + if (d->preloadContent == value) { |
58 | + return; |
59 | + } |
60 | + d->preloadContent = value; |
61 | + if (!d->preloadContent) { |
62 | + d->loader->reset(); |
63 | + } else { |
64 | + d->preload(); |
65 | + } |
66 | + |
67 | + // TODO: instruct regions to preload |
68 | + Q_EMIT preloadContentChanged(); |
69 | +} |
70 | + |
71 | +void UCBottomEdgePrivate::preload() |
72 | +{ |
73 | + if (!preloadContent) { |
74 | + return; |
75 | + } |
76 | + Q_Q(UCBottomEdge); |
77 | + if (!loader) { |
78 | + loader = new AsyncLoader(q); |
79 | + QObject::connect(loader, SIGNAL(statusChanged(QQmlIncubator::Status,QObject*)), |
80 | + q, SLOT(onLoaderStatusChanged(QQmlIncubator::Status,QObject*))); |
81 | + } |
82 | + // component has priority over the URL! |
83 | + if (contentComponent) { |
84 | + loader->load(contentComponent, new QQmlContext(qmlContext(q))); |
85 | + } else if (contentUrl.isValid()) { |
86 | + loader->load(qmlEngine(q), contentUrl, new QQmlContext(qmlContext(q))); |
87 | + } |
88 | +} |
89 | + |
90 | +void UCBottomEdgePrivate::onLoaderStatusChanged(QQmlIncubator::Status status, QObject *object) |
91 | +{ |
92 | + qDebug() << status << object; |
93 | + if (status == QQmlIncubator::Ready && object) { |
94 | + object->setParent(bottomPanel->m_panel); |
95 | + qobject_cast<QQuickItem*>(object)->setParentItem(bottomPanel->m_panel); |
96 | + } |
97 | +} |
98 | + |
99 | #include "moc_ucbottomedge.cpp" |
100 | |
101 | === modified file 'src/Ubuntu/Components/plugin/ucbottomedge.h' |
102 | --- src/Ubuntu/Components/plugin/ucbottomedge.h 2015-12-11 12:10:54 +0000 |
103 | +++ src/Ubuntu/Components/plugin/ucbottomedge.h 2016-02-19 14:39:50 +0000 |
104 | @@ -42,6 +42,7 @@ |
105 | Q_PROPERTY(QQuickItem* contentItem READ contentItem NOTIFY contentItemChanged FINAL) |
106 | Q_PROPERTY(QQmlListProperty<UCBottomEdgeRegion> regions READ regions NOTIFY regionsChanged FINAL) |
107 | Q_PROPERTY(UCBottomEdgeRegion* activeRegion READ activeRegion NOTIFY activeRegionChanged FINAL) |
108 | + Q_PROPERTY(bool preloadContent READ preloadContent WRITE setPreloadContent NOTIFY preloadContentChanged FINAL DESIGNABLE false) |
109 | |
110 | // overloaded data property to catch regions |
111 | Q_PRIVATE_PROPERTY(UCBottomEdge::d_func(), QQmlListProperty<QObject> data READ data DESIGNABLE false) |
112 | @@ -73,6 +74,8 @@ |
113 | void setFillWindow(bool fill); |
114 | QQmlListProperty<UCBottomEdgeRegion> regions(); |
115 | UCBottomEdgeRegion *activeRegion(); |
116 | + bool preloadContent() const; |
117 | + void setPreloadContent(bool value); |
118 | |
119 | Q_SIGNALS: |
120 | void dragProgressChanged(qreal dragProgress); |
121 | @@ -83,6 +86,7 @@ |
122 | void contentItemChanged(); |
123 | void regionsChanged(); |
124 | void activeRegionChanged(UCBottomEdgeRegion *activeRegion); |
125 | + void preloadContentChanged(); |
126 | |
127 | void commitStarted(); |
128 | void commitCompleted(); |
129 | @@ -109,6 +113,9 @@ |
130 | |
131 | Q_DECLARE_PRIVATE(UCBottomEdge) |
132 | |
133 | +private: |
134 | + Q_PRIVATE_SLOT(d_func(), void onLoaderStatusChanged(QQmlIncubator::Status status, QObject *object)) |
135 | + |
136 | friend class tst_BottomEdge; |
137 | }; |
138 | Q_DECLARE_METATYPE(UCBottomEdge::Status) |
139 | |
140 | === modified file 'src/Ubuntu/Components/plugin/ucbottomedge_p.h' |
141 | --- src/Ubuntu/Components/plugin/ucbottomedge_p.h 2015-12-21 17:49:59 +0000 |
142 | +++ src/Ubuntu/Components/plugin/ucbottomedge_p.h 2016-02-19 14:39:50 +0000 |
143 | @@ -23,6 +23,10 @@ |
144 | #include "ucstyleditembase_p.h" |
145 | #include "ucaction.h" |
146 | |
147 | +#include <AsyncLoader> |
148 | + |
149 | +using namespace UbuntuToolkit; |
150 | + |
151 | class UCBottomEdgeStyle; |
152 | class UCBottomEdgePrivate : public UCStyledItemBasePrivate, protected QQuickItemChangeListener |
153 | { |
154 | @@ -70,6 +74,9 @@ |
155 | void itemChildAdded(QQuickItem *item, QQuickItem *child); |
156 | void itemChildRemoved(QQuickItem *item, QQuickItem *child); |
157 | |
158 | + void preload(); |
159 | + void onLoaderStatusChanged(QQmlIncubator::Status status, QObject *object); |
160 | + |
161 | // members |
162 | QUrl contentUrl; |
163 | QList<UCBottomEdgeRegion*> regions; |
164 | @@ -77,6 +84,7 @@ |
165 | UCBottomEdgeHint *hint; |
166 | QQmlComponent *contentComponent; |
167 | UCBottomEdgeStyle *bottomPanel; |
168 | + UbuntuToolkit::AsyncLoader *loader; |
169 | |
170 | qreal previousDistance; |
171 | qreal dragProgress; |
172 | @@ -93,6 +101,7 @@ |
173 | |
174 | bool defaultRegionsReset:1; |
175 | bool mousePressed:1; |
176 | + bool preloadContent:1; |
177 | |
178 | // status management |
179 | void setOperationStatus(OperationStatus s); |
180 | |
181 | === modified file 'src/Ubuntu/Test/plugin/uctestcase.cpp' |
182 | --- src/Ubuntu/Test/plugin/uctestcase.cpp 2016-01-25 17:12:56 +0000 |
183 | +++ src/Ubuntu/Test/plugin/uctestcase.cpp 2016-02-19 14:39:50 +0000 |
184 | @@ -76,3 +76,16 @@ |
185 | QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); |
186 | } |
187 | } |
188 | + |
189 | +/*! |
190 | + * Same as previous but without column number |
191 | + */ |
192 | +void UbuntuTestCase::ignoreWarning(const QString& fileName, uint line, |
193 | + const QString& message, uint occurences) |
194 | +{ |
195 | + for (uint i = 0; i < occurences; i++) { |
196 | + QString url(QUrl::fromLocalFile(QFileInfo(fileName).absoluteFilePath()).toEncoded()); |
197 | + QString warning(QString("%1:%2 %3").arg(url).arg(line).arg(message)); |
198 | + QTest::ignoreMessage(QtWarningMsg, warning.toUtf8()); |
199 | + } |
200 | +} |
201 | |
202 | === modified file 'src/Ubuntu/Test/plugin/uctestcase.h' |
203 | --- src/Ubuntu/Test/plugin/uctestcase.h 2016-01-25 17:12:56 +0000 |
204 | +++ src/Ubuntu/Test/plugin/uctestcase.h 2016-02-19 14:39:50 +0000 |
205 | @@ -54,6 +54,7 @@ |
206 | } |
207 | |
208 | static void ignoreWarning(const QString& fileName, uint line, uint column, const QString& message, uint occurences=1); |
209 | + static void ignoreWarning(const QString& fileName, uint line, const QString& message, uint occurences=1); |
210 | |
211 | static inline void waitForSignal(QSignalSpy *spy, int timeout = 5000) |
212 | { |
213 | |
214 | === modified file 'src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro' |
215 | --- src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro 2016-02-11 17:19:48 +0000 |
216 | +++ src/Ubuntu/UbuntuToolkit/UbuntuToolkit.pro 2016-02-19 14:39:50 +0000 |
217 | @@ -15,8 +15,10 @@ |
218 | HEADERS += \ |
219 | colorutils.h \ |
220 | ubuntutoolkitglobal.h \ |
221 | - tree.h |
222 | + tree.h \ |
223 | + asyncloader.h |
224 | |
225 | SOURCES += \ |
226 | colorutils.cpp \ |
227 | - tree.cpp |
228 | + tree.cpp \ |
229 | + asyncloader.cpp |
230 | |
231 | === added file 'src/Ubuntu/UbuntuToolkit/asyncloader.cpp' |
232 | --- src/Ubuntu/UbuntuToolkit/asyncloader.cpp 1970-01-01 00:00:00 +0000 |
233 | +++ src/Ubuntu/UbuntuToolkit/asyncloader.cpp 2016-02-19 14:39:50 +0000 |
234 | @@ -0,0 +1,214 @@ |
235 | +/* |
236 | + * Copyright 2016 Canonical Ltd. |
237 | + * |
238 | + * This program is free software; you can redistribute it and/or modify |
239 | + * it under the terms of the GNU Lesser General Public License as published by |
240 | + * the Free Software Foundation; version 3. |
241 | + * |
242 | + * This program is distributed in the hope that it will be useful, |
243 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
244 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
245 | + * GNU Lesser General Public License for more details. |
246 | + * |
247 | + * You should have received a copy of the GNU Lesser General Public License |
248 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
249 | + */ |
250 | + |
251 | +#include <asyncloader.h> |
252 | + |
253 | +#include <QtQml/QQmlContext> |
254 | +#include <QtQml/QQmlComponent> |
255 | +#include <QtQuick/QQuickItem> |
256 | + |
257 | +namespace UbuntuToolkit { |
258 | + |
259 | +AsyncLoader::AsyncLoader(QObject *parent) |
260 | + : QObject(parent) |
261 | + , QQmlIncubator(Asynchronous) |
262 | + , m_component(nullptr) |
263 | + , m_context(nullptr) |
264 | + , m_ownComponent(false) |
265 | +{ |
266 | +} |
267 | + |
268 | +AsyncLoader::~AsyncLoader() |
269 | +{ |
270 | + reset(); |
271 | +} |
272 | + |
273 | +// incubator methods |
274 | +void AsyncLoader::setInitialState(QObject *object) |
275 | +{ |
276 | + emitStatus(Initializing, object); |
277 | +} |
278 | + |
279 | +AsyncLoader::LoadingStatus incubatorToLoadingStatus(QQmlIncubator::Status status) |
280 | +{ |
281 | + switch (status) { |
282 | + case QQmlIncubator::Null: return AsyncLoader::Null; |
283 | + case QQmlIncubator::Ready: return AsyncLoader::Ready; |
284 | + case QQmlIncubator::Loading: return AsyncLoader::Loading; |
285 | + case QQmlIncubator::Error: return AsyncLoader::Error; |
286 | + } |
287 | + // unlikely to be reached, but must satisfy compiler |
288 | + return AsyncLoader::Null; |
289 | +} |
290 | + |
291 | +void AsyncLoader::statusChanged(Status status) |
292 | +{ |
293 | + if (status == QQmlIncubator::Error) { |
294 | + QList<QQmlError> e = errors(); |
295 | + for (int i = 0; i < e.size(); i++) { |
296 | + // remove quotes and any leading/trailing whitespace |
297 | + qWarning().noquote() << e[0].toString().trimmed(); |
298 | + } |
299 | + } |
300 | + if (status != QQmlIncubator::Loading) { |
301 | + detachComponent(); |
302 | + } |
303 | + // we should emit the status change only after we do the cleanup |
304 | + emitStatus(incubatorToLoadingStatus(status)); |
305 | +} |
306 | + |
307 | +// procected methods |
308 | +void AsyncLoader::emitStatus(LoadingStatus status, QObject *object) |
309 | +{ |
310 | + if (m_status == status) { |
311 | + return; |
312 | + } |
313 | + |
314 | + m_status = status; |
315 | + if (!object) { |
316 | + object = this->object(); |
317 | + } |
318 | + Q_EMIT loadingStatus(m_status, object); |
319 | +} |
320 | + |
321 | +void AsyncLoader::detachComponent() |
322 | +{ |
323 | + if (!m_component) { |
324 | + return; |
325 | + } |
326 | + |
327 | + disconnect(m_component, &QQmlComponent::statusChanged, |
328 | + this, &AsyncLoader::onComponentStatusChanged); |
329 | + if (m_ownComponent) { |
330 | + m_component->deleteLater(); |
331 | + } |
332 | + m_component = nullptr; |
333 | + m_ownComponent = false; |
334 | +} |
335 | + |
336 | +void AsyncLoader::onComponentStatusChanged(QQmlComponent::Status status) |
337 | +{ |
338 | + if (status == QQmlComponent::Error) { |
339 | + QString error = m_component->errorString(); |
340 | + // remove quotes and any leading/trailing whitespace |
341 | + qWarning().noquote() << error.trimmed(); |
342 | + detachComponent(); |
343 | + emitStatus(Error); |
344 | + return; |
345 | + } |
346 | + if (status == QQmlComponent::Ready) { |
347 | + m_component->create(*this, m_context); |
348 | + } |
349 | +} |
350 | + |
351 | +/*! |
352 | + * \brief AsyncLoader::load |
353 | + * \param url |
354 | + * \param context |
355 | + * \return bool |
356 | + * The method initiates the loading of a given \e url within a specific \e context. |
357 | + * Returns true on success. |
358 | + * \note If the loading is initiated while there is a previous loading in place, |
359 | + * you must make sure you delete the object from the previous loading before you |
360 | + * trigger the new load. |
361 | + */ |
362 | +bool AsyncLoader::load(const QUrl &url, QQmlContext *context) |
363 | +{ |
364 | + if (!reset()) { |
365 | + return false; |
366 | + } |
367 | + if (url.isEmpty() || !url.isValid() || !context) { |
368 | + emitStatus(Ready); |
369 | + return true; |
370 | + } |
371 | + m_ownComponent = true; |
372 | + return load(new QQmlComponent(context->engine(), url, QQmlComponent::Asynchronous), context); |
373 | +} |
374 | + |
375 | +/*! |
376 | + * \brief AsyncLoader::load |
377 | + * \param component |
378 | + * \param context |
379 | + * \return bool |
380 | + * The method initiates the loading of a \e component within the given \e context. |
381 | + * Returns true on success. |
382 | + * \note If the loading is initiated while there is a previous loading in place, |
383 | + * you must make sure you delete the object from the previous loading before you |
384 | + * trigger the new load. |
385 | + */ |
386 | +bool AsyncLoader::load(QQmlComponent *component, QQmlContext *context) |
387 | +{ |
388 | + if (!reset()) { |
389 | + return false; |
390 | + } |
391 | + if (!component || !context) { |
392 | + emitStatus(Ready); |
393 | + return true; |
394 | + } |
395 | + m_component = component; |
396 | + m_context = context; |
397 | + if (m_component->isLoading()) { |
398 | + emitStatus(Compiling); |
399 | + connect(m_component, &QQmlComponent::statusChanged, |
400 | + this, &AsyncLoader::onComponentStatusChanged, Qt::DirectConnection); |
401 | + } else { |
402 | + onComponentStatusChanged(m_component->status()); |
403 | + } |
404 | + return true; |
405 | +} |
406 | + |
407 | +/*! |
408 | + * \brief AsyncLoader::reset |
409 | + * \return bool |
410 | + * Clears the incubator and emits loadingStatus() signal with \c Reset status. |
411 | + * The loader can be reset only if the status passed \c Loading. Returns true |
412 | + * if the reset was successful, or when the loader status is \c Ready or |
413 | + * \c Error. |
414 | + */ |
415 | +bool AsyncLoader::reset() |
416 | +{ |
417 | + if (m_status < Loading) { |
418 | + return false; |
419 | + } |
420 | + if (m_status >= Ready) { |
421 | + return true; |
422 | + } |
423 | + clear(); |
424 | + // make sure the listeners are getting the reset so they can delete the object |
425 | + emitStatus(Reset); |
426 | + return true; |
427 | +} |
428 | + |
429 | +/*! |
430 | + * \brief AsyncLoader::status |
431 | + * \return LoadingStatus |
432 | + * Returns the status of the loader. |
433 | + */ |
434 | +AsyncLoader::LoadingStatus AsyncLoader::status() |
435 | +{ |
436 | + return m_status; |
437 | +} |
438 | + |
439 | +/*! |
440 | + * \brief AsyncLoader::forceCompletion |
441 | + * Forces loading completion. |
442 | + */ |
443 | +void AsyncLoader::forceCompletion() |
444 | +{ |
445 | + QQmlIncubator::forceCompletion(); |
446 | +} |
447 | + |
448 | +} // namespace UbuntuToolkit |
449 | |
450 | === added file 'src/Ubuntu/UbuntuToolkit/asyncloader.h' |
451 | --- src/Ubuntu/UbuntuToolkit/asyncloader.h 1970-01-01 00:00:00 +0000 |
452 | +++ src/Ubuntu/UbuntuToolkit/asyncloader.h 2016-02-19 14:39:50 +0000 |
453 | @@ -0,0 +1,71 @@ |
454 | +/* |
455 | + * Copyright 2016 Canonical Ltd. |
456 | + * |
457 | + * This program is free software; you can redistribute it and/or modify |
458 | + * it under the terms of the GNU Lesser General Public License as published by |
459 | + * the Free Software Foundation; version 3. |
460 | + * |
461 | + * This program is distributed in the hope that it will be useful, |
462 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
463 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
464 | + * GNU Lesser General Public License for more details. |
465 | + * |
466 | + * You should have received a copy of the GNU Lesser General Public License |
467 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
468 | + */ |
469 | + |
470 | +#ifndef ASYNCLOADER_H |
471 | +#define ASYNCLOADER_H |
472 | + |
473 | +#include <QtQml/QQmlIncubator> |
474 | +#include <QtQml/QQmlComponent> |
475 | +#include <ubuntutoolkitglobal.h> |
476 | + |
477 | +class QQuickItem; |
478 | +class QQmlContext; |
479 | + |
480 | +namespace UbuntuToolkit { |
481 | + |
482 | +class UBUNTUTOOLKIT_EXPORT AsyncLoader : public QObject, protected QQmlIncubator |
483 | +{ |
484 | + Q_OBJECT |
485 | +public: |
486 | + enum LoadingStatus { |
487 | + Null, |
488 | + Compiling, |
489 | + Loading, |
490 | + Initializing, |
491 | + Ready, |
492 | + Error, |
493 | + Reset |
494 | + }; |
495 | + |
496 | + explicit AsyncLoader(QObject *parent = 0); |
497 | + ~AsyncLoader(); |
498 | + |
499 | + bool load(const QUrl &url, QQmlContext *context); |
500 | + bool load(QQmlComponent *component, QQmlContext *context); |
501 | + bool reset(); |
502 | + LoadingStatus status(); |
503 | + void forceCompletion(); |
504 | + |
505 | +Q_SIGNALS: |
506 | + void loadingStatus(LoadingStatus status, QObject *object); |
507 | + |
508 | +protected: |
509 | + void setInitialState(QObject *object) override; |
510 | + void statusChanged(Status status) override; |
511 | + |
512 | + void emitStatus(LoadingStatus status, QObject *object = 0); |
513 | + void onComponentStatusChanged(QQmlComponent::Status status); |
514 | + void detachComponent(); |
515 | + |
516 | + QQmlComponent *m_component = nullptr; |
517 | + QQmlContext *m_context = nullptr; |
518 | + LoadingStatus m_status = Ready; |
519 | + bool m_ownComponent = false; |
520 | +}; |
521 | + |
522 | +} // namespace UbuntuToolkit |
523 | + |
524 | +#endif // ASYNCLOADER_H |
525 | |
526 | === modified file 'tests/unit/plugin_dependency.pri' |
527 | --- tests/unit/plugin_dependency.pri 2015-12-21 12:18:50 +0000 |
528 | +++ tests/unit/plugin_dependency.pri 2016-02-19 14:39:50 +0000 |
529 | @@ -9,6 +9,7 @@ |
530 | LIBS += -L$$PLUGIN_BLD/Components -lUbuntuComponents |
531 | LIBS += -L$$PLUGIN_BLD/Test -lUbuntuTest |
532 | LIBS += -L$${ROOT_BUILD_DIR}/lib -lUbuntuGestures |
533 | +#LIBS += -L$${ROOT_BUILD_DIR}/lib -lUbuntuToolkit |
534 | DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\" |
535 | QMAKE_CXXFLAGS += -Werror |
536 | |
537 | |
538 | === modified file 'tests/unit/test-include.pri' |
539 | --- tests/unit/test-include.pri 2014-11-25 09:58:33 +0000 |
540 | +++ tests/unit/test-include.pri 2016-02-19 14:39:50 +0000 |
541 | @@ -3,6 +3,6 @@ |
542 | |
543 | TEMPLATE = app |
544 | QT += testlib qml quick |
545 | -CONFIG += no_keywords |
546 | +CONFIG += no_keywords c++11 |
547 | |
548 | |
549 | |
550 | === added directory 'tests/unit_x11/tst_asyncloader' |
551 | === added file 'tests/unit_x11/tst_asyncloader/Document.qml' |
552 | --- tests/unit_x11/tst_asyncloader/Document.qml 1970-01-01 00:00:00 +0000 |
553 | +++ tests/unit_x11/tst_asyncloader/Document.qml 2016-02-19 14:39:50 +0000 |
554 | @@ -0,0 +1,31 @@ |
555 | +/* |
556 | + * Copyright 2016 Canonical Ltd. |
557 | + * |
558 | + * This program is free software; you can redistribute it and/or modify |
559 | + * it under the terms of the GNU Lesser General Public License as published by |
560 | + * the Free Software Foundation; version 3. |
561 | + * |
562 | + * This program is distributed in the hope that it will be useful, |
563 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
564 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
565 | + * GNU Lesser General Public License for more details. |
566 | + * |
567 | + * You should have received a copy of the GNU Lesser General Public License |
568 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
569 | + * |
570 | + */ |
571 | + |
572 | +import QtQuick 2.4 |
573 | +import Ubuntu.Components 1.3 |
574 | + |
575 | +Column { |
576 | + anchors.fill: parent |
577 | + spacing: 1 |
578 | + Repeater { |
579 | + model: 500 |
580 | + TextField { |
581 | + width: parent.width |
582 | + } |
583 | + } |
584 | +} |
585 | + |
586 | |
587 | === added file 'tests/unit_x11/tst_asyncloader/FaultyDocument.qml' |
588 | --- tests/unit_x11/tst_asyncloader/FaultyDocument.qml 1970-01-01 00:00:00 +0000 |
589 | +++ tests/unit_x11/tst_asyncloader/FaultyDocument.qml 2016-02-19 14:39:50 +0000 |
590 | @@ -0,0 +1,20 @@ |
591 | +/* |
592 | + * Copyright 2016 Canonical Ltd. |
593 | + * |
594 | + * This program is free software; you can redistribute it and/or modify |
595 | + * it under the terms of the GNU Lesser General Public License as published by |
596 | + * the Free Software Foundation; version 3. |
597 | + * |
598 | + * This program is distributed in the hope that it will be useful, |
599 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
600 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
601 | + * GNU Lesser General Public License for more details. |
602 | + * |
603 | + * You should have received a copy of the GNU Lesser General Public License |
604 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
605 | + * |
606 | + */ |
607 | + |
608 | +import QtQuick 2.4 |
609 | + |
610 | +Label {} |
611 | |
612 | === added file 'tests/unit_x11/tst_asyncloader/HeavyDocument.qml' |
613 | --- tests/unit_x11/tst_asyncloader/HeavyDocument.qml 1970-01-01 00:00:00 +0000 |
614 | +++ tests/unit_x11/tst_asyncloader/HeavyDocument.qml 2016-02-19 14:39:50 +0000 |
615 | @@ -0,0 +1,31 @@ |
616 | +/* |
617 | + * Copyright 2016 Canonical Ltd. |
618 | + * |
619 | + * This program is free software; you can redistribute it and/or modify |
620 | + * it under the terms of the GNU Lesser General Public License as published by |
621 | + * the Free Software Foundation; version 3. |
622 | + * |
623 | + * This program is distributed in the hope that it will be useful, |
624 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
625 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
626 | + * GNU Lesser General Public License for more details. |
627 | + * |
628 | + * You should have received a copy of the GNU Lesser General Public License |
629 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
630 | + * |
631 | + */ |
632 | + |
633 | +import QtQuick 2.4 |
634 | +import Ubuntu.Components 1.3 |
635 | + |
636 | +Column { |
637 | + anchors.fill: parent |
638 | + spacing: units.dp(1) |
639 | + Repeater { |
640 | + model: 500 |
641 | + TextField { |
642 | + width: parent.width |
643 | + } |
644 | + } |
645 | +} |
646 | + |
647 | |
648 | === added file 'tests/unit_x11/tst_asyncloader/TestApp.qml' |
649 | --- tests/unit_x11/tst_asyncloader/TestApp.qml 1970-01-01 00:00:00 +0000 |
650 | +++ tests/unit_x11/tst_asyncloader/TestApp.qml 2016-02-19 14:39:50 +0000 |
651 | @@ -0,0 +1,30 @@ |
652 | +/* |
653 | + * Copyright 2016 Canonical Ltd. |
654 | + * |
655 | + * This program is free software; you can redistribute it and/or modify |
656 | + * it under the terms of the GNU Lesser General Public License as published by |
657 | + * the Free Software Foundation; version 3. |
658 | + * |
659 | + * This program is distributed in the hope that it will be useful, |
660 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
661 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
662 | + * GNU Lesser General Public License for more details. |
663 | + * |
664 | + * You should have received a copy of the GNU Lesser General Public License |
665 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
666 | + * |
667 | + */ |
668 | + |
669 | +import QtQuick 2.4 |
670 | +//import Ubuntu.Components 1.3 |
671 | + |
672 | +//MainView { |
673 | +// width: units.gu(40) |
674 | +// height: units.gu(71) |
675 | + |
676 | +// applicationName: "Document" |
677 | +//} |
678 | + |
679 | +Item { |
680 | + |
681 | +} |
682 | |
683 | === added file 'tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp' |
684 | --- tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp 1970-01-01 00:00:00 +0000 |
685 | +++ tests/unit_x11/tst_asyncloader/tst_asyncloader.cpp 2016-02-19 14:39:50 +0000 |
686 | @@ -0,0 +1,265 @@ |
687 | +/* |
688 | + * Copyright 2016 Canonical Ltd. |
689 | + * |
690 | + * This program is free software; you can redistribute it and/or modify |
691 | + * it under the terms of the GNU Lesser General Public License as published by |
692 | + * the Free Software Foundation; version 3. |
693 | + * |
694 | + * This program is distributed in the hope that it will be useful, |
695 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
696 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
697 | + * GNU Lesser General Public License for more details. |
698 | + * |
699 | + * You should have received a copy of the GNU Lesser General Public License |
700 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
701 | + * |
702 | + */ |
703 | + |
704 | +#include <QtTest/QtTest> |
705 | +#include "uctestcase.h" |
706 | +#include "uctestextras.h" |
707 | +#include <AsyncLoader> |
708 | +#include <functional> |
709 | +#include <QtQml/QQmlEngine> |
710 | + |
711 | +class LoaderSpy : public QObject |
712 | +{ |
713 | + Q_OBJECT |
714 | +public: |
715 | + UbuntuToolkit::AsyncLoader *m_loader; |
716 | + QScopedPointer<QObject> m_object; |
717 | + bool m_done = false; |
718 | + bool m_error = false; |
719 | + QList<UbuntuToolkit::AsyncLoader::LoadingStatus> m_statusList; |
720 | +public: |
721 | + LoaderSpy(UbuntuToolkit::AsyncLoader *loader) |
722 | + : QObject(0) |
723 | + , m_loader(loader) |
724 | + { |
725 | + connect(loader, &UbuntuToolkit::AsyncLoader::loadingStatus, |
726 | + this, &LoaderSpy::onLoadingStatusChanged); |
727 | + } |
728 | + |
729 | +protected Q_SLOTS: |
730 | + virtual void onLoadingStatusChanged(UbuntuToolkit::AsyncLoader::LoadingStatus status, QObject *object) |
731 | + { |
732 | + m_statusList << status; |
733 | + if (status == UbuntuToolkit::AsyncLoader::Ready) { |
734 | + m_done = true; |
735 | + m_object.reset(object); |
736 | + } |
737 | + if (status == UbuntuToolkit::AsyncLoader::Error) { |
738 | + m_error = true; |
739 | + } |
740 | + } |
741 | +}; |
742 | + |
743 | +class ResetLoaderSpy : public LoaderSpy |
744 | +{ |
745 | + Q_OBJECT |
746 | +public: |
747 | + bool m_reset = false; |
748 | +public: |
749 | + ResetLoaderSpy(UbuntuToolkit::AsyncLoader *loader) |
750 | + : LoaderSpy(loader) |
751 | + { |
752 | + } |
753 | + |
754 | + void onLoadingStatusChanged(UbuntuToolkit::AsyncLoader::LoadingStatus status, QObject *object) override |
755 | + { |
756 | + if (status == UbuntuToolkit::AsyncLoader::Loading) { |
757 | + m_loader->reset(); |
758 | + m_reset = true; |
759 | + } |
760 | + LoaderSpy::onLoadingStatusChanged(status, object); |
761 | + } |
762 | +}; |
763 | + |
764 | +class SecondLoaderSpy : public LoaderSpy |
765 | +{ |
766 | + Q_OBJECT |
767 | +public: |
768 | + bool m_loadResult = false; |
769 | +public: |
770 | + SecondLoaderSpy(UbuntuToolkit::AsyncLoader *loader, UbuntuToolkit::AsyncLoader::LoadingStatus loadAt, |
771 | + const QUrl &url, QQmlContext *context) |
772 | + : LoaderSpy(loader) |
773 | + , m_loadAt(loadAt) |
774 | + , m_url(url) |
775 | + , m_context(context) |
776 | + { |
777 | + } |
778 | + |
779 | + void onLoadingStatusChanged(UbuntuToolkit::AsyncLoader::LoadingStatus status, QObject *object) override |
780 | + { |
781 | + if (status == (UbuntuToolkit::AsyncLoader::LoadingStatus)m_loadAt) { |
782 | + m_loadAt = -1; |
783 | + delete object; |
784 | + object = nullptr; |
785 | + m_loadResult = m_loader->load(m_url, m_context); |
786 | + } |
787 | + LoaderSpy::onLoadingStatusChanged(status, object); |
788 | + } |
789 | + |
790 | +private: |
791 | + int m_loadAt; |
792 | + QUrl m_url; |
793 | + QQmlContext *m_context; |
794 | +}; |
795 | + |
796 | +/******************************************************************** |
797 | + * Test |
798 | + ********************************************************************/ |
799 | +class tst_AsyncLoader : public QObject |
800 | +{ |
801 | + Q_OBJECT |
802 | +private Q_SLOTS: |
803 | + |
804 | + void test_load_data() |
805 | + { |
806 | + QTest::addColumn<bool>("loadAsDocument"); |
807 | + QTest::addColumn<QString>("document"); |
808 | + QTest::addColumn<int>("mode"); |
809 | + QTest::addColumn< QList<int> >("statuses"); |
810 | + |
811 | + QTest::newRow("document") << true << "Document.qml" << (int)QQmlComponent::Asynchronous |
812 | + << (QList<int>() |
813 | + << UbuntuToolkit::AsyncLoader::Compiling |
814 | + << UbuntuToolkit::AsyncLoader::Loading |
815 | + << UbuntuToolkit::AsyncLoader::Initializing |
816 | + << UbuntuToolkit::AsyncLoader::Ready |
817 | + ); |
818 | + QTest::newRow("component, asynchronous") << false << "Document.qml" << (int)QQmlComponent::Asynchronous |
819 | + << (QList<int>() |
820 | + << UbuntuToolkit::AsyncLoader::Compiling |
821 | + << UbuntuToolkit::AsyncLoader::Loading |
822 | + << UbuntuToolkit::AsyncLoader::Initializing |
823 | + << UbuntuToolkit::AsyncLoader::Ready |
824 | + ); |
825 | + QTest::newRow("component, synchronous") << false << "Document.qml" << (int)QQmlComponent::PreferSynchronous |
826 | + << (QList<int>() |
827 | + << UbuntuToolkit::AsyncLoader::Loading |
828 | + << UbuntuToolkit::AsyncLoader::Initializing |
829 | + << UbuntuToolkit::AsyncLoader::Ready |
830 | + ); |
831 | + } |
832 | + void test_load() |
833 | + { |
834 | + QFETCH(bool, loadAsDocument); |
835 | + QFETCH(QString, document); |
836 | + QFETCH(int, mode); |
837 | + QFETCH(QList<int>, statuses); |
838 | + |
839 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
840 | + UbuntuToolkit::AsyncLoader loader; |
841 | + LoaderSpy spy(&loader); |
842 | + QScopedPointer<QQmlComponent> component; |
843 | + |
844 | + if (loadAsDocument) { |
845 | + loader.load(QUrl::fromLocalFile(document), view->rootContext()); |
846 | + } else { |
847 | + // create a component |
848 | + component.reset(new QQmlComponent(view->engine(), QUrl::fromLocalFile(document), (QQmlComponent::CompilationMode)mode)); |
849 | + loader.load(component.data(), view->rootContext()); |
850 | + } |
851 | + QTRY_VERIFY_WITH_TIMEOUT(spy.m_object != nullptr, 2000); |
852 | + // check the statuses |
853 | + QCOMPARE(spy.m_statusList.length(), statuses.length()); |
854 | + for (int i = 0; i < spy.m_statusList.length(); i++) { |
855 | + QVERIFY2((int)spy.m_statusList[i] == statuses[i], (QString(" Status at index %1 differs").arg(i)).toLocal8Bit().constData()); |
856 | + } |
857 | + } |
858 | + |
859 | + void test_load_with_error() |
860 | + { |
861 | + QUrl document = QUrl::fromLocalFile("FaultyDocument.qml"); |
862 | + UbuntuTestCase::ignoreWarning("FaultyDocument.qml", 20, "Label is not a type"); |
863 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
864 | + UbuntuToolkit::AsyncLoader loader; |
865 | + LoaderSpy spy(&loader); |
866 | + loader.load(document, view->rootContext()); |
867 | + QTRY_VERIFY_WITH_TIMEOUT(spy.m_error == true, 2000); |
868 | + } |
869 | + |
870 | + void test_load_and_cancel_data() |
871 | + { |
872 | + QTest::addColumn<bool>("loadAsDocument"); |
873 | + QTest::addColumn<QString>("document"); |
874 | + QTest::addColumn<int>("mode"); |
875 | + |
876 | + QTest::newRow("document") << true << "HeavyDocument.qml" << (int)QQmlComponent::Asynchronous; |
877 | + QTest::newRow("component, asynchronous") << false << "HeavyDocument.qml" << (int)QQmlComponent::Asynchronous; |
878 | + QTest::newRow("component, synchronous") << false << "HeavyDocument.qml" << (int)QQmlComponent::PreferSynchronous; |
879 | + } |
880 | + void test_load_and_cancel() |
881 | + { |
882 | + QFETCH(bool, loadAsDocument); |
883 | + QFETCH(QString, document); |
884 | + QFETCH(int, mode); |
885 | + |
886 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
887 | + UbuntuToolkit::AsyncLoader loader; |
888 | + ResetLoaderSpy spy(&loader); |
889 | + QScopedPointer<QQmlComponent> component; |
890 | + |
891 | + if (loadAsDocument) { |
892 | + loader.load(QUrl::fromLocalFile(document), view->rootContext()); |
893 | + } else { |
894 | + // create a component |
895 | + component.reset(new QQmlComponent(view->engine(), QUrl::fromLocalFile(document), (QQmlComponent::CompilationMode)mode)); |
896 | + loader.load(component.data(), view->rootContext()); |
897 | + } |
898 | + if (loader.status() < UbuntuToolkit::AsyncLoader::Loading) { |
899 | + // cannot reset yet! |
900 | + QVERIFY(!loader.reset()); |
901 | + } |
902 | + QTRY_VERIFY_WITH_TIMEOUT(spy.m_reset, 2000); |
903 | + } |
904 | + |
905 | + void test_second_load_scenarios_data() |
906 | + { |
907 | + QTest::addColumn<QString> ("doc1"); |
908 | + QTest::addColumn<QString> ("doc2"); |
909 | + QTest::addColumn<int> ("when"); |
910 | + QTest::addColumn<bool> ("success"); |
911 | + |
912 | + QTest::newRow("status = Compiling") |
913 | + << "Document.qml" << "HeavyDocument.qml" |
914 | + << (int)UbuntuToolkit::AsyncLoader::Compiling << false; |
915 | + QTest::newRow("status = Loading") |
916 | + << "Document.qml" << "HeavyDocument.qml" |
917 | + << (int)UbuntuToolkit::AsyncLoader::Loading << true; |
918 | + QTest::newRow("status = Initializing") |
919 | + << "Document.qml" << "HeavyDocument.qml" |
920 | + << (int)UbuntuToolkit::AsyncLoader::Initializing << true; |
921 | + QTest::newRow("status = Ready") |
922 | + << "Document.qml" << "HeavyDocument.qml" |
923 | + << (int)UbuntuToolkit::AsyncLoader::Ready << true; |
924 | + QTest::newRow("status = Error") |
925 | + << "FaultyDocument.qml" << "HeavyDocument.qml" |
926 | + << (int)UbuntuToolkit::AsyncLoader::Error << true; |
927 | + } |
928 | + void test_second_load_scenarios() |
929 | + { |
930 | + QFETCH(QString, doc1); |
931 | + QFETCH(QString, doc2); |
932 | + QFETCH(int, when); |
933 | + QFETCH(bool, success); |
934 | + |
935 | + QScopedPointer<UbuntuTestCase> view(new UbuntuTestCase("TestApp.qml")); |
936 | + UbuntuToolkit::AsyncLoader loader; |
937 | + if (when == (int)UbuntuToolkit::AsyncLoader::Error) { |
938 | + UbuntuTestCase::ignoreWarning("FaultyDocument.qml", 20, "Label is not a type"); |
939 | + } |
940 | + |
941 | + SecondLoaderSpy spy(&loader, (UbuntuToolkit::AsyncLoader::LoadingStatus)when, QUrl::fromLocalFile(doc2), view->rootContext()); |
942 | + // load the first document |
943 | + QVERIFY(loader.load(QUrl::fromLocalFile(doc1), view->rootContext())); |
944 | + QTRY_VERIFY_WITH_TIMEOUT(spy.m_object != nullptr, 4000); |
945 | + QCOMPARE(spy.m_loadResult, success); |
946 | + } |
947 | +}; |
948 | + |
949 | +QTEST_MAIN(tst_AsyncLoader) |
950 | + |
951 | +#include "tst_asyncloader.moc" |
952 | |
953 | === added file 'tests/unit_x11/tst_asyncloader/tst_asyncloader.pro' |
954 | --- tests/unit_x11/tst_asyncloader/tst_asyncloader.pro 1970-01-01 00:00:00 +0000 |
955 | +++ tests/unit_x11/tst_asyncloader/tst_asyncloader.pro 2016-02-19 14:39:50 +0000 |
956 | @@ -0,0 +1,11 @@ |
957 | +include(../test-include.pri) |
958 | +QT += core-private qml-private quick-private gui-private UbuntuToolkit |
959 | + |
960 | +SOURCES += \ |
961 | + tst_asyncloader.cpp |
962 | + |
963 | +DISTFILES += \ |
964 | + Document.qml \ |
965 | + TestApp.qml \ |
966 | + HeavyDocument.qml \ |
967 | + FaultyDocument.qml |
968 | |
969 | === modified file 'tests/unit_x11/tst_bottomedge/tst_bottomedge.cpp' |
970 | --- tests/unit_x11/tst_bottomedge/tst_bottomedge.cpp 2016-02-10 10:57:20 +0000 |
971 | +++ tests/unit_x11/tst_bottomedge/tst_bottomedge.cpp 2016-02-19 14:39:50 +0000 |
972 | @@ -137,6 +137,7 @@ |
973 | QCOMPARE(test->regionAt("testItem", 0)->m_from, 0.33); |
974 | QCOMPARE(test->regionAt("testItem", 0)->m_to, 1.0); |
975 | QVERIFY(!test->testItem()->activeRegion()); |
976 | + QVERIFY(!test->testItem()->preloadContent()); |
977 | } |
978 | |
979 | void test_height_moves_when_reparented() |
980 | |
981 | === modified file 'tests/unit_x11/unit_x11.pro' |
982 | --- tests/unit_x11/unit_x11.pro 2015-11-23 16:12:16 +0000 |
983 | +++ tests/unit_x11/unit_x11.pro 2016-02-19 14:39:50 +0000 |
984 | @@ -17,4 +17,5 @@ |
985 | tst_subtheming \ |
986 | tst_swipearea \ |
987 | tst_touchregistry \ |
988 | - tst_bottomedge |
989 | + tst_bottomedge \ |
990 | + tst_asyncloader |