Merge lp:~zsombi/ubuntu-ui-toolkit/asyncPageCreation into lp:ubuntu-ui-toolkit/staging
- asyncPageCreation
- Merge into staging
Status: | Merged |
---|---|
Approved by: | Cris Dywan |
Approved revision: | 1627 |
Merged at revision: | 1624 |
Proposed branch: | lp:~zsombi/ubuntu-ui-toolkit/asyncPageCreation |
Merge into: | lp:ubuntu-ui-toolkit/staging |
Diff against target: |
505 lines (+343/-13) 8 files modified
documentation/ubuntu-ui-toolkit-common.qdocconf (+1/-1) examples/ubuntu-ui-toolkit-gallery/ubuntu-ui-toolkit-gallery.qml (+1/-2) src/Ubuntu/Components/1.3/AdaptivePageLayout.qml (+81/-7) src/Ubuntu/Components/1.3/PageWrapper.qml (+25/-2) src/Ubuntu/Components/1.3/PageWrapperUtils.js (+167/-0) src/Ubuntu/Components/ComponentModule.pro (+1/-0) tests/unit_x11/tst_components/tst_adaptivepagelayout.qml (+61/-0) tests/unit_x11/tst_components/tst_multicolumnheader.qml (+6/-1) |
To merge this branch: | bzr merge lp:~zsombi/ubuntu-ui-toolkit/asyncPageCreation |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cris Dywan | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+269509@code.launchpad.net |
Commit message
Turn AdaptivePageLayout page creation to be asynchronous.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
Cris Dywan (kalikiana) wrote : | # |
tests/unit_
The fake incubator looks pretty straightforward. Can we link to the upstream docs¹, though? And point out that it's equivalent to using incubateObject or a Loader, which may even get people to use it in their own code.
¹ http://
Zsombor Egri (zsombi) wrote : | # |
> tests/unit_
> tests/unit_
> they don't immediately check the header.
Actually PageStack should behave like did before, loading pages synchronously. We should mark the PageStack deprecated, and instruct people to move away from it from 1.3 onwards. So the only test needed to be adjusted is the tst_multicolumn
>
> The fake incubator looks pretty straightforward. Can we link to the upstream
> docs¹, though? And point out that it's equivalent to using incubateObject or a
> Loader, which may even get people to use it in their own code.
>
> ¹ http://
I did that, however would be nicer if we could link to the d.u.c link. But d.u.c is broken, seems not all Qt docs are taken from qt.io.
- 1623. By Zsombor Egri
-
adapt multicolumn test to async page loading
- 1624. By Zsombor Egri
-
fix async loading to be triggered only when PageWrapper synchronous is not set to avoid breaking PageStack behavior; toolkit gallery title not being set fixed; adapt multicolumnheader test to async loading
Tim Peeters (tpeeters) wrote : | # |
I prefer not to touch 1.2, so that would mean we don't edit 1.2/PageWrapper
Cris Dywan (kalikiana) wrote : | # |
> I prefer not to touch 1.2, so that would mean we don't edit
> 1.2/PageWrapper
> edit.
It's internal.. but I agree for consistency it makes sense.
- 1625. By Zsombor Egri
-
copy PageWrapperUtils.js to 1.3 and have the changes there only.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1625
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 1626. By Zsombor Egri
-
documentation fix
- 1627. By Zsombor Egri
-
staging merge
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:1627
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Cris Dywan (kalikiana) wrote : | # |
Let's get it landed!
Preview Diff
1 | === modified file 'documentation/ubuntu-ui-toolkit-common.qdocconf' |
2 | --- documentation/ubuntu-ui-toolkit-common.qdocconf 2015-07-24 18:00:54 +0000 |
3 | +++ documentation/ubuntu-ui-toolkit-common.qdocconf 2015-09-01 12:00:47 +0000 |
4 | @@ -26,7 +26,7 @@ |
5 | sources.fileextensions = "*.qml *.qdoc *.cpp *.js" |
6 | headers.fileextensions = "*.h" |
7 | # exclude qml files that have the component documented in a separate qdoc file |
8 | -excludefiles = $BLD/../src/Ubuntu/Components/MainView.qml |
9 | +excludefiles += $BLD/../src/Ubuntu/Components/1.3/PageWrapperUtils.js |
10 | outputdir = $BLD/html |
11 | outputformats = HTML |
12 | version = 1.2 |
13 | |
14 | === modified file 'examples/ubuntu-ui-toolkit-gallery/ubuntu-ui-toolkit-gallery.qml' |
15 | --- examples/ubuntu-ui-toolkit-gallery/ubuntu-ui-toolkit-gallery.qml 2015-08-14 10:11:58 +0000 |
16 | +++ examples/ubuntu-ui-toolkit-gallery/ubuntu-ui-toolkit-gallery.qml 2015-09-01 12:00:47 +0000 |
17 | @@ -96,9 +96,8 @@ |
18 | selected: index === widgetList.currentIndex |
19 | onClicked: { |
20 | var source = Qt.resolvedUrl(model.source); |
21 | - var newPage = layout.addPageToNextColumn(mainPage, source); |
22 | + layout.addPageToNextColumn(mainPage, source, {title: model.label}); |
23 | |
24 | - newPage.title = model.label; |
25 | widgetList.currentIndex = index; |
26 | } |
27 | } |
28 | |
29 | === modified file 'src/Ubuntu/Components/1.3/AdaptivePageLayout.qml' |
30 | --- src/Ubuntu/Components/1.3/AdaptivePageLayout.qml 2015-08-27 20:27:45 +0000 |
31 | +++ src/Ubuntu/Components/1.3/AdaptivePageLayout.qml 2015-09-01 12:00:47 +0000 |
32 | @@ -83,6 +83,12 @@ |
33 | } |
34 | \endqml |
35 | |
36 | + \note Observe the use of the \c Page::pageStack property in the example above. |
37 | + The same property is used to share the AdaptivePageLayout instance the Page is |
38 | + used in, therefore the same page can be used in a PageStack or in an AdaptivePageLayout. |
39 | + However implementations must make sure the desired PageStack or AdaptivePageLayout |
40 | + function exists in the instance before using it. |
41 | + |
42 | AdaptivePageLayout supports adaptive column handling. When the number of columns changes at |
43 | runtime the pages are automatically rearranged. |
44 | |
45 | @@ -196,12 +202,72 @@ |
46 | property list<PageColumnsLayout> layouts |
47 | |
48 | /*! |
49 | - \qmlmethod Item addPageToCurrentColumn(Item sourcePage, var page[, var properties]) |
50 | + \qmlmethod object addPageToCurrentColumn(Item sourcePage, var page[, var properties]) |
51 | Adds a \c page to the column the \c sourcePage resides in and removes all pages |
52 | from the higher columns. \c page can be a Component or a file. |
53 | - \c properties is a JSON object containing properties |
54 | - to be set when page is created. \c sourcePage must be active. Returns the |
55 | - instance of the page created. |
56 | + \c properties is a JSON object containing properties to be set when page |
57 | + is created. \c sourcePage must be active. |
58 | + |
59 | + The function creates the new page asynchronously if the new \c page to be |
60 | + added is a Component or a QML document. In this case the function returns |
61 | + an incubator which can be used to track the page creation.For more about |
62 | + incubation in QML and creating components asynchronously, see |
63 | + \l {http://doc.qt.io/qt-5/qml-qtqml-component.html#incubateObject-method} |
64 | + {Component.incubateObject()}. |
65 | + The following example removes an element from the list model whenever the |
66 | + page opened in the second column is closed. Note, the example must be run |
67 | + on desktop or on a device with at least 90 grid units screen width. |
68 | + \qml |
69 | + import QtQuick 2.4 |
70 | + import Ubuntu.Components 1.3 |
71 | + |
72 | + MainView { |
73 | + width: units.gu(90) |
74 | + height: units.gu(70) |
75 | + |
76 | + Component { |
77 | + id: page2Component |
78 | + Page { |
79 | + title: "Second Page" |
80 | + Button { |
81 | + text: "Close me" |
82 | + onClicked: pageStack.removePages(pageStack.primaryPage); |
83 | + } |
84 | + } |
85 | + } |
86 | + |
87 | + AdaptivePageLayout { |
88 | + id: pageLayout |
89 | + anchors.fill: parent |
90 | + primaryPage: Page { |
91 | + title: "Primary Page" |
92 | + ListView { |
93 | + id: listView |
94 | + anchors.fill: parent |
95 | + model: 10 |
96 | + delegate: ListItem { |
97 | + Label { text: modelData } |
98 | + onClicked: { |
99 | + var incubator = pageLayout.addPageToNextColumn(pageLayout.primaryPage, page2Component); |
100 | + if (incubator && incubator.status == Component.Loading) { |
101 | + incubator.onStatusChanged = function(status) { |
102 | + if (status == Component.Ready) { |
103 | + // connect page's destruction to decrement model |
104 | + incubator.object.Component.destruction.connect(function() { |
105 | + listView.model--; |
106 | + }); |
107 | + } |
108 | + } |
109 | + } |
110 | + } |
111 | + } |
112 | + } |
113 | + } |
114 | + } |
115 | + } |
116 | + \endqml |
117 | + |
118 | + \sa {http://doc.qt.io/qt-5/qml-qtqml-component.html#incubateObject-method}{Component.incubateObject} |
119 | */ |
120 | function addPageToCurrentColumn(sourcePage, page, properties) { |
121 | var nextColumn = d.columnForPage(sourcePage) + 1; |
122 | @@ -221,6 +287,7 @@ |
123 | holds \c sourcePage) and all following columns, and then add \c page to the next column. |
124 | If \c sourcePage is located in the |
125 | rightmost column, the new page will be pushed to the same column as \c sourcePage. |
126 | + The return value is the same as in \l addPageToCurrentColumn case. |
127 | */ |
128 | function addPageToNextColumn(sourcePage, page, properties) { |
129 | var nextColumn = d.columnForPage(sourcePage) + 1; |
130 | @@ -304,7 +371,7 @@ |
131 | |
132 | function createWrapper(page, properties) { |
133 | var wrapperComponent = Qt.createComponent("PageWrapper.qml"); |
134 | - var wrapperObject = wrapperComponent.createObject(hiddenPages); |
135 | + var wrapperObject = wrapperComponent.createObject(hiddenPages, {synchronous: false}); |
136 | wrapperObject.pageStack = layout; |
137 | wrapperObject.properties = properties; |
138 | // set reference last because it will trigger creation of the object |
139 | @@ -320,7 +387,14 @@ |
140 | // replace page holder's child |
141 | var holder = body.children[targetColumn]; |
142 | holder.detachCurrentPage(); |
143 | - holder.attachPage(pageWrapper) |
144 | + if ((pageWrapper.incubator && pageWrapper.incubator.status == Component.Ready) || pageWrapper.object) { |
145 | + holder.attachPage(pageWrapper); |
146 | + } else { |
147 | + // asynchronous, connect to page load completion and attach when page is available |
148 | + pageWrapper.pageLoaded.connect(function () { |
149 | + holder.attachPage(pageWrapper); |
150 | + }); |
151 | + } |
152 | } |
153 | |
154 | function getWrapper(page) { |
155 | @@ -378,7 +452,7 @@ |
156 | newWrapper.parentPage = sourcePage; |
157 | newWrapper.column = column; |
158 | d.addWrappedPage(newWrapper); |
159 | - return newWrapper.object; |
160 | + return newWrapper.incubator; |
161 | } |
162 | |
163 | // update the page for the specified column |
164 | |
165 | === modified file 'src/Ubuntu/Components/1.3/PageWrapper.qml' |
166 | --- src/Ubuntu/Components/1.3/PageWrapper.qml 2015-06-15 07:45:34 +0000 |
167 | +++ src/Ubuntu/Components/1.3/PageWrapper.qml 2015-09-01 12:00:47 +0000 |
168 | @@ -15,7 +15,7 @@ |
169 | */ |
170 | |
171 | import QtQuick 2.4 |
172 | -import "../1.2/PageWrapperUtils.js" as Utils |
173 | +import "PageWrapperUtils.js" as Utils |
174 | |
175 | /*! |
176 | \internal |
177 | @@ -66,6 +66,22 @@ |
178 | property Item pageHolder |
179 | |
180 | /*! |
181 | + Instructs to load the page synchronously or not. Used by AdaptivePageLayout. |
182 | + True by default to keep PageStack integrity. |
183 | + */ |
184 | + property bool synchronous: true |
185 | + |
186 | + /*! |
187 | + Incubator for the asynchronous page creation |
188 | + */ |
189 | + property var incubator: null |
190 | + |
191 | + /*! |
192 | + Signal emitted when incubator completes page loading. |
193 | + */ |
194 | + signal pageLoaded() |
195 | + |
196 | + /*! |
197 | Returns true if the current PageWrapper is a child of the given page |
198 | */ |
199 | function childOf(page) { |
200 | @@ -114,7 +130,14 @@ |
201 | if (pageWrapper.object) pageWrapper.object = null; |
202 | Utils.initPage(pageWrapper); |
203 | if (pageWrapper.active && reference) { |
204 | - Utils.activate(pageWrapper); |
205 | + if ((pageWrapper.incubator && pageWrapper.incubator.status == Component.Ready) || pageWrapper.object) { |
206 | + Utils.activate(pageWrapper); |
207 | + } else { |
208 | + // asynchronous, connect page activation |
209 | + pageLoaded.connect(function () { |
210 | + Utils.activate(pageWrapper); |
211 | + }); |
212 | + } |
213 | } |
214 | } |
215 | |
216 | |
217 | === added file 'src/Ubuntu/Components/1.3/PageWrapperUtils.js' |
218 | --- src/Ubuntu/Components/1.3/PageWrapperUtils.js 1970-01-01 00:00:00 +0000 |
219 | +++ src/Ubuntu/Components/1.3/PageWrapperUtils.js 2015-09-01 12:00:47 +0000 |
220 | @@ -0,0 +1,167 @@ |
221 | +/* |
222 | + * Copyright 2015 Canonical Ltd. |
223 | + * |
224 | + * This program is free software; you can redistribute it and/or modify |
225 | + * it under the terms of the GNU Lesser General Public License as published by |
226 | + * the Free Software Foundation; version 3. |
227 | + * |
228 | + * This program is distributed in the hope that it will be useful, |
229 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
230 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
231 | + * GNU Lesser General Public License for more details. |
232 | + * |
233 | + * You should have received a copy of the GNU Lesser General Public License |
234 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
235 | + */ |
236 | + |
237 | +//.pragma library // FIXME: cannot refer to Component.Error if I use this. |
238 | +// FIXME: ideally we would make this a stateless library, but that breaks applications |
239 | +// that rely on accessing context variables in pages that were pushed on a PageStack |
240 | +// by url (PageStack.push("FileName.qml")) because of a Qt bug: |
241 | +// https://bugreports.qt-project.org/browse/QTBUG-31347 |
242 | + |
243 | +/*! |
244 | + \internal |
245 | + Incubator wrapper object. Used when page is loaded asynchronously. |
246 | + */ |
247 | + |
248 | +function Incubator(pageWrapper, pageComponent) { |
249 | + // private variable for QmlIncubatorObject |
250 | + var incubator = null; |
251 | + |
252 | + // public API |
253 | + this.status = Component.Ready; |
254 | + this.object = null; |
255 | + this.onStatusChanged = null; |
256 | + this.forceCompletion = function () { |
257 | + if (incubator) { |
258 | + incubator.forceCompletion(); |
259 | + } |
260 | + } |
261 | + |
262 | + // internal function to catch status changes |
263 | + function incubatorStatusChanged(status) { |
264 | + // update wrapper incubator fields |
265 | + pageWrapper.incubator.status = status; |
266 | + pageWrapper.incubator.object = pageWrapper.object = incubator.object; |
267 | + |
268 | + // emit pageWrapper's pageLoaded signal to complete page activation and loading |
269 | + if (status === Component.Ready) { |
270 | + pageWrapper.pageLoaded(); |
271 | + } |
272 | + |
273 | + // forward state change to the user |
274 | + if (pageWrapper.incubator.onStatusChanged) { |
275 | + // call onStatusChanged |
276 | + pageWrapper.incubator.onStatusChanged(status); |
277 | + } |
278 | + |
279 | + // cleanup of ready or error |
280 | + if (status !== Component.Loading) { |
281 | + pageWrapper.incubator = null; |
282 | + incubator = null; |
283 | + } |
284 | + } |
285 | + |
286 | + if (pageWrapper.properties) { |
287 | + incubator = pageComponent.incubateObject(pageWrapper, pageWrapper.properties); |
288 | + } else { |
289 | + incubator = pageComponent.incubateObject(pageWrapper); |
290 | + } |
291 | + |
292 | + this.status = incubator.status; |
293 | + if (incubator.status != Component.Ready) { |
294 | + incubator.onStatusChanged = incubatorStatusChanged; |
295 | + } else { |
296 | + incubatorStatusChanged(incubator.status); |
297 | + } |
298 | +} |
299 | + |
300 | +/******************************************************* |
301 | + * |
302 | + */ |
303 | +/*! |
304 | + \internal |
305 | + Initialize pageWrapper.object. |
306 | + */ |
307 | +function initPage(pageWrapper) { |
308 | + var pageComponent; |
309 | + |
310 | + if (pageWrapper.reference.createObject) { |
311 | + // page reference is a component |
312 | + pageComponent = pageWrapper.reference; |
313 | + } else if (typeof pageWrapper.reference == "string") { |
314 | + // page reference is a string (url) |
315 | + pageComponent = Qt.createComponent(pageWrapper.reference); |
316 | + } |
317 | + |
318 | + // PageWrapper can override the synchronous loading |
319 | + var synchronous = pageWrapper.hasOwnProperty("synchronous") ? pageWrapper.synchronous : true; |
320 | + |
321 | + if (pageComponent) { |
322 | + if (pageComponent.status === Component.Error) { |
323 | + throw new Error("Error while loading page: " + pageComponent.errorString()); |
324 | + } else { |
325 | + // create the object |
326 | + pageWrapper.incubator = new Incubator(pageWrapper, pageComponent); |
327 | + if (synchronous) { |
328 | + pageWrapper.incubator.forceCompletion(); |
329 | + } |
330 | + pageWrapper.canDestroy = true; |
331 | + } |
332 | + } else { |
333 | + // page reference is an object |
334 | + pageWrapper.object = pageWrapper.reference; |
335 | + pageWrapper.object.parent = pageWrapper; |
336 | + pageWrapper.canDestroy = false; |
337 | + |
338 | + // copy the properties to the page object |
339 | + for (var prop in pageWrapper.properties) { |
340 | + if (pageWrapper.properties.hasOwnProperty(prop)) { |
341 | + pageWrapper.object[prop] = pageWrapper.properties[prop]; |
342 | + } |
343 | + } |
344 | + } |
345 | + |
346 | + return pageWrapper.object; |
347 | +} |
348 | + |
349 | +/*! |
350 | + \internal |
351 | + Create the page object if needed, and make the page object visible. |
352 | + */ |
353 | +function activate(pageWrapper) { |
354 | + if (!pageWrapper.object) { |
355 | + initPage(pageWrapper); |
356 | + } |
357 | + |
358 | + // Having the same page pushed multiple times on a stack changes |
359 | + // the parent of the page object. Change it back here. |
360 | + pageWrapper.object.parent = pageWrapper; |
361 | + |
362 | + // Some page objects are invisible initially. Make visible. |
363 | + |
364 | + pageWrapper.object.visible = true; |
365 | + pageWrapper.active = true; |
366 | +} |
367 | + |
368 | +/*! |
369 | + \internal |
370 | + Hide page object. |
371 | + */ |
372 | +function deactivate(pageWrapper) { |
373 | + pageWrapper.active = false; |
374 | +} |
375 | + |
376 | +/*! |
377 | + \internal |
378 | + Destroy the page object if pageWrapper.canDestroy is true. |
379 | + Do nothing if pageWrapper.canDestroy is false. |
380 | + */ |
381 | +function destroyObject(pageWrapper) { |
382 | + if (pageWrapper.canDestroy) { |
383 | + pageWrapper.object.destroy(); |
384 | + pageWrapper.object = null; |
385 | + pageWrapper.canDestroy = false; |
386 | + } |
387 | +} |
388 | |
389 | === modified file 'src/Ubuntu/Components/ComponentModule.pro' |
390 | --- src/Ubuntu/Components/ComponentModule.pro 2015-08-24 16:02:50 +0000 |
391 | +++ src/Ubuntu/Components/ComponentModule.pro 2015-09-01 12:00:47 +0000 |
392 | @@ -110,6 +110,7 @@ |
393 | 1.3/PageTreeNode.qml \ |
394 | 1.3/pageUtils.js \ |
395 | 1.3/PageWrapper.qml \ |
396 | + 1.3/PageWrapperUtils.js \ |
397 | 1.3/Panel.qml \ |
398 | 1.3/ProgressBar.qml \ |
399 | 1.3/PullToRefresh.qml \ |
400 | |
401 | === modified file 'tests/unit_x11/tst_components/tst_adaptivepagelayout.qml' |
402 | --- tests/unit_x11/tst_components/tst_adaptivepagelayout.qml 2015-08-11 08:30:57 +0000 |
403 | +++ tests/unit_x11/tst_components/tst_adaptivepagelayout.qml 2015-09-01 12:00:47 +0000 |
404 | @@ -69,9 +69,25 @@ |
405 | id: defaults |
406 | } |
407 | |
408 | + Component { |
409 | + id: pageComponent |
410 | + Page { |
411 | + title: "DynamicPage" |
412 | + } |
413 | + } |
414 | + |
415 | UbuntuTestCase { |
416 | + id: testCase |
417 | when: windowShown |
418 | |
419 | + signal pageLoaded() |
420 | + |
421 | + SignalSpy { |
422 | + id: loadedSpy |
423 | + target: testCase |
424 | + signalName: "pageLoaded" |
425 | + } |
426 | + |
427 | function resize_single_column() { |
428 | layout.width = units.gu(40); |
429 | } |
430 | @@ -82,6 +98,11 @@ |
431 | } |
432 | |
433 | function cleanup() { |
434 | + page1.title = "Page1"; |
435 | + page2.title = "Page2"; |
436 | + page3.title = "Page3"; |
437 | + page4.title = "Page4"; |
438 | + loadedSpy.clear(); |
439 | resize_multiple_columns(); |
440 | layout.removePages(page1); |
441 | } |
442 | @@ -185,5 +206,45 @@ |
443 | layout.removePages(page3); |
444 | compare(page2.visible, true, "Adding page to current column pruned that column."); |
445 | } |
446 | + |
447 | + function test_add_page_to_current_data() { |
448 | + return [ |
449 | + {tag: "Synchronously to current column", func: "addPageToCurrentColumn", page: page2, params: {}, sync: true}, |
450 | + {tag: "Synchronously to current column, with params", func: "addPageToCurrentColumn", page: page2, params: {title: "Altered title"}, sync: true}, |
451 | + {tag: "Synchronously to next column", func: "addPageToNextColumn", page: page2, params: {}, sync: true}, |
452 | + {tag: "Synchronously to next column, with params", func: "addPageToNextColumn", page: page2, params: {title: "Altered title"}, sync: true}, |
453 | + {tag: "Asynchronously to current column", func: "addPageToCurrentColumn", page: pageComponent, params: {}, sync: false}, |
454 | + {tag: "Asynchronously to current column, with params", func: "addPageToCurrentColumn", page: pageComponent, params: {title: "Altered title"}, sync: false}, |
455 | + {tag: "Asynchronously to next column", func: "addPageToNextColumn", page: pageComponent, params: {}, sync: false}, |
456 | + {tag: "Asynchronously to next column, with params", func: "addPageToNextColumn", page: pageComponent, params: {title: "Altered title"}, sync: false}, |
457 | + ] |
458 | + } |
459 | + function test_add_page_to_current(data) { |
460 | + var incubator = layout[data.func](layout.primaryPage, data.page, data.params); |
461 | + compare((incubator == null), data.sync); |
462 | + if (incubator) { |
463 | + compare(incubator.status, Component.Loading, "The incubator status is not Component.Loading, but " + incubator.status); |
464 | + // for cleanup, we must wait till the page is added, so we can do proper cleanup |
465 | + incubator.onStatusChanged = function (status) { |
466 | + // test params |
467 | + for (var param in data.params) { |
468 | + compare(incubator.object[param], data.params[param], "parameter '" + param + "' values do not match"); |
469 | + } |
470 | + testCase.pageLoaded(); |
471 | + layout.removePages(layout.primaryPage); |
472 | + } |
473 | + // make sure we wait enough to let additional tests to complete |
474 | + loadedSpy.wait(1500); |
475 | + } |
476 | + } |
477 | + |
478 | + function test_asynchronous_page_loading_incubator_forcecompletion() { |
479 | + var incubator = layout.addPageToCurrentColumn(layout.primaryPage, pageComponent); |
480 | + verify(incubator, "Page added synchronously!"); |
481 | + compare(incubator.status, Component.Loading, "Incubator in different state"); |
482 | + incubator.forceCompletion(); |
483 | + compare(incubator.status, Component.Ready, "Incubator not completed"); |
484 | + verify(incubator.object, "Page object not set"); |
485 | + } |
486 | } |
487 | } |
488 | |
489 | === modified file 'tests/unit_x11/tst_components/tst_multicolumnheader.qml' |
490 | --- tests/unit_x11/tst_components/tst_multicolumnheader.qml 2015-08-27 21:11:36 +0000 |
491 | +++ tests/unit_x11/tst_components/tst_multicolumnheader.qml 2015-09-01 12:00:47 +0000 |
492 | @@ -240,7 +240,12 @@ |
493 | } |
494 | |
495 | function test_header_title_for_external_page() { |
496 | - layout.addPageToNextColumn(rootPage, Qt.resolvedUrl("MyExternalPage.qml")); |
497 | + var incubator = layout.addPageToNextColumn(rootPage, Qt.resolvedUrl("MyExternalPage.qml")); |
498 | + var pageLoaded = false; |
499 | + incubator.onStatusChanged = function (status) { |
500 | + pageLoaded = (incubator.object != null); |
501 | + } |
502 | + tryCompareFunction(function() {return pageLoaded}, true, 1000); |
503 | var n = root.columns === 2 ? 1 : 0 |
504 | compare(get_header(n).config.title, "Page from QML file", |
505 | "Adding external Page does not update the header title."); |
FAILED: Continuous integration, rev:1622 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/2184/ jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-amd64- ci/912 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/914 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/914/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-i386- ci/911
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
deb: http://
UNSTABLE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/2184/ rebuild
http://