Merge lp:~renatofilho/address-book-app/split-contactlist into lp:~phablet-team/address-book-app/staging
- split-contactlist
- Merge into staging
Status: | Merged |
---|---|
Approved by: | Tiago Salem Herrmann |
Approved revision: | 245 |
Merged at revision: | 282 |
Proposed branch: | lp:~renatofilho/address-book-app/split-contactlist |
Merge into: | lp:~phablet-team/address-book-app/staging |
Diff against target: |
392 lines (+178/-137) 4 files modified
src/imports/Ubuntu/Contacts/CMakeLists.txt (+1/-0) src/imports/Ubuntu/Contacts/ContactListModel.qml (+171/-0) src/imports/Ubuntu/Contacts/ContactListView.qml (+5/-137) src/imports/Ubuntu/Contacts/qmldir (+1/-0) |
To merge this branch: | bzr merge lp:~renatofilho/address-book-app/split-contactlist |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tiago Salem Herrmann (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+230992@code.launchpad.net |
Commit message
[Contacts] Split ContactListView in two components (ContactListView and ContactListModel)
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:245
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
- 244. By Renato Araujo Oliveira Filho
-
[Contacts] Split ContactListView in two components (ContactListView and ContactListModel)
Renato Araujo Oliveira Filho (renatofilho) wrote : | # |
Are there any related MPs required for this MP to build/function as expected? NO
Is your branch in sync with latest trunk? YES
Did you perform an exploratory manual test run of your code change and any related functionality on device or emulator? YES
Did you successfully run all tests found in your component's Test Plan on device or emulator? YES
If you changed the UI, was the change specified/approved by design? NO UI CHANGE
If you changed UI labels, did you update the pot file? NO NECESSARY
If you changed the packaging (debian), did you add a core-dev as a reviewer to this MP? NO PACKAGE CHANGE
- 245. By Renato Araujo Oliveira Filho
-
Merged parent branch.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:245
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Tiago Salem Herrmann (tiagosh) wrote : | # |
Looks good. Works as expected.
Preview Diff
1 | === modified file 'src/imports/Ubuntu/Contacts/CMakeLists.txt' | |||
2 | --- src/imports/Ubuntu/Contacts/CMakeLists.txt 2014-08-13 20:52:57 +0000 | |||
3 | +++ src/imports/Ubuntu/Contacts/CMakeLists.txt 2014-08-18 18:28:33 +0000 | |||
4 | @@ -22,6 +22,7 @@ | |||
5 | 22 | ContactDetailWithTypeView.qml | 22 | ContactDetailWithTypeView.qml |
6 | 23 | ContactFetch.qml | 23 | ContactFetch.qml |
7 | 24 | ContactList.js | 24 | ContactList.js |
8 | 25 | ContactListModel.qml | ||
9 | 25 | ContactListView.qml | 26 | ContactListView.qml |
10 | 26 | ContactPreviewPage.qml | 27 | ContactPreviewPage.qml |
11 | 27 | ContactSimpleListView.qml | 28 | ContactSimpleListView.qml |
12 | 28 | 29 | ||
13 | === added file 'src/imports/Ubuntu/Contacts/ContactListModel.qml' | |||
14 | --- src/imports/Ubuntu/Contacts/ContactListModel.qml 1970-01-01 00:00:00 +0000 | |||
15 | +++ src/imports/Ubuntu/Contacts/ContactListModel.qml 2014-08-18 18:28:33 +0000 | |||
16 | @@ -0,0 +1,171 @@ | |||
17 | 1 | /* | ||
18 | 2 | * Copyright (C) 2012-2013 Canonical, Ltd. | ||
19 | 3 | * | ||
20 | 4 | * This program is free software; you can redistribute it and/or modify | ||
21 | 5 | * it under the terms of the GNU General Public License as published by | ||
22 | 6 | * the Free Software Foundation; version 3. | ||
23 | 7 | * | ||
24 | 8 | * This program is distributed in the hope that it will be useful, | ||
25 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | 11 | * GNU General Public License for more details. | ||
28 | 12 | * | ||
29 | 13 | * You should have received a copy of the GNU General Public License | ||
30 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
31 | 15 | */ | ||
32 | 16 | |||
33 | 17 | import QtQuick 2.2 | ||
34 | 18 | import QtContacts 5.0 | ||
35 | 19 | |||
36 | 20 | ContactModel { | ||
37 | 21 | id: root | ||
38 | 22 | |||
39 | 23 | property var externalFilter: null | ||
40 | 24 | property string filterTerm: "" | ||
41 | 25 | property bool onlyFavorites: false | ||
42 | 26 | property var view: null | ||
43 | 27 | |||
44 | 28 | /* internal */ | ||
45 | 29 | property bool _clearModel: false | ||
46 | 30 | property list<QtObject> _extraFilters | ||
47 | 31 | property QtObject _timeout | ||
48 | 32 | |||
49 | 33 | |||
50 | 34 | function changeFilter(newFilter) | ||
51 | 35 | { | ||
52 | 36 | if (root.contacts.length > 0) { | ||
53 | 37 | root._clearModel = true | ||
54 | 38 | } | ||
55 | 39 | root.externalFilter = newFilter | ||
56 | 40 | } | ||
57 | 41 | |||
58 | 42 | |||
59 | 43 | filter: { | ||
60 | 44 | if (root._clearModel) { | ||
61 | 45 | return invalidFilter | ||
62 | 46 | } else if (contactsFilter.active) { | ||
63 | 47 | return contactsFilter | ||
64 | 48 | } else { | ||
65 | 49 | return null | ||
66 | 50 | } | ||
67 | 51 | } | ||
68 | 52 | |||
69 | 53 | _extraFilters: [ | ||
70 | 54 | InvalidFilter { | ||
71 | 55 | id: invalidFilter | ||
72 | 56 | }, | ||
73 | 57 | DetailFilter { | ||
74 | 58 | id: favouritesFilter | ||
75 | 59 | |||
76 | 60 | detail: ContactDetail.Favorite | ||
77 | 61 | field: Favorite.Favorite | ||
78 | 62 | value: true | ||
79 | 63 | matchFlags: DetailFilter.MatchExactly | ||
80 | 64 | }, | ||
81 | 65 | UnionFilter { | ||
82 | 66 | id: contactTermFilter | ||
83 | 67 | |||
84 | 68 | property string value: "" | ||
85 | 69 | |||
86 | 70 | DetailFilter { | ||
87 | 71 | detail: ContactDetail.DisplayLabel | ||
88 | 72 | field: DisplayLabel.Label | ||
89 | 73 | value: contactTermFilter.value | ||
90 | 74 | matchFlags: DetailFilter.MatchContains | ||
91 | 75 | } | ||
92 | 76 | |||
93 | 77 | DetailFilter { | ||
94 | 78 | detail: ContactDetail.PhoneNumber | ||
95 | 79 | field: PhoneNumber.Number | ||
96 | 80 | value: contactTermFilter.value | ||
97 | 81 | matchFlags: DetailFilter.MatchPhoneNumber | ||
98 | 82 | } | ||
99 | 83 | |||
100 | 84 | DetailFilter { | ||
101 | 85 | detail: ContactDetail.PhoneNumber | ||
102 | 86 | field: PhoneNumber.Number | ||
103 | 87 | value: contactTermFilter.value | ||
104 | 88 | matchFlags: DetailFilter.MatchContains | ||
105 | 89 | } | ||
106 | 90 | }, | ||
107 | 91 | IntersectionFilter { | ||
108 | 92 | id: contactsFilter | ||
109 | 93 | |||
110 | 94 | // avoid runtime warning "depends on non-NOTIFYable properties" | ||
111 | 95 | readonly property alias filtersProxy: contactsFilter.filters | ||
112 | 96 | |||
113 | 97 | property bool active: { | ||
114 | 98 | var filters_ = [] | ||
115 | 99 | if (contactTermFilter.value.length > 0) { | ||
116 | 100 | filters_.push(contactTermFilter) | ||
117 | 101 | } else if (root.onlyFavorites) { | ||
118 | 102 | filters_.push(favouritesFilter) | ||
119 | 103 | } | ||
120 | 104 | |||
121 | 105 | if (root.externalFilter) { | ||
122 | 106 | filters_.push(root.externalFilter) | ||
123 | 107 | } | ||
124 | 108 | |||
125 | 109 | // check if the filter has changed | ||
126 | 110 | var oldFilters = filtersProxy | ||
127 | 111 | if (oldFilters.length !== filters_.length) { | ||
128 | 112 | contactsFilter.filters = filters_ | ||
129 | 113 | } else { | ||
130 | 114 | for(var i=0; i < oldFilters.length; i++) { | ||
131 | 115 | if (filters_.indexOf(oldFilters[i]) === -1) { | ||
132 | 116 | contactsFilter.filters = filters_ | ||
133 | 117 | } | ||
134 | 118 | } | ||
135 | 119 | } | ||
136 | 120 | |||
137 | 121 | return (filters_.length > 0) | ||
138 | 122 | } | ||
139 | 123 | } | ||
140 | 124 | ] | ||
141 | 125 | |||
142 | 126 | _timeout: Timer { | ||
143 | 127 | id: contactSearchTimeout | ||
144 | 128 | |||
145 | 129 | running: false | ||
146 | 130 | repeat: false | ||
147 | 131 | interval: 300 | ||
148 | 132 | onTriggered: { | ||
149 | 133 | if (root.view) { | ||
150 | 134 | view.positionViewAtBeginning() | ||
151 | 135 | } | ||
152 | 136 | |||
153 | 137 | root.changeFilter(root.externalFilter) | ||
154 | 138 | contactTermFilter.value = root.filterTerm | ||
155 | 139 | |||
156 | 140 | // manually update if autoUpdate is disabled | ||
157 | 141 | if (!root.autoUpdate) { | ||
158 | 142 | root.update() | ||
159 | 143 | } | ||
160 | 144 | } | ||
161 | 145 | } | ||
162 | 146 | |||
163 | 147 | onFilterTermChanged: contactSearchTimeout.restart() | ||
164 | 148 | |||
165 | 149 | onErrorChanged: { | ||
166 | 150 | if (error) { | ||
167 | 151 | console.error("Contact List error:" + error) | ||
168 | 152 | } | ||
169 | 153 | } | ||
170 | 154 | |||
171 | 155 | onContactsChanged: { | ||
172 | 156 | //WORKAROUND: clear the model before start populate it with the new contacts | ||
173 | 157 | //otherwise the model will wait for all contacts before show any new contact | ||
174 | 158 | |||
175 | 159 | //after all contacts get removed we can populate the model again, this will show | ||
176 | 160 | //new contacts as soon as it arrives in the model | ||
177 | 161 | if (root._clearModel && contacts.length === 0) { | ||
178 | 162 | root._clearModel = false | ||
179 | 163 | // do a new update if autoUpdate is false | ||
180 | 164 | if (!root.autoUpdate) { | ||
181 | 165 | root.update() | ||
182 | 166 | } | ||
183 | 167 | |||
184 | 168 | } | ||
185 | 169 | } | ||
186 | 170 | } | ||
187 | 171 | |||
188 | 0 | 172 | ||
189 | === modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml' | |||
190 | --- src/imports/Ubuntu/Contacts/ContactListView.qml 2014-08-12 23:51:38 +0000 | |||
191 | +++ src/imports/Ubuntu/Contacts/ContactListView.qml 2014-08-18 18:28:33 +0000 | |||
192 | @@ -52,7 +52,7 @@ | |||
193 | 52 | This property holds a string that will be used to filter contacts on the list | 52 | This property holds a string that will be used to filter contacts on the list |
194 | 53 | By default this is set to empty | 53 | By default this is set to empty |
195 | 54 | */ | 54 | */ |
197 | 55 | property string filterTerm: "" | 55 | property alias filterTerm: contactsModel.filterTerm |
198 | 56 | /*! | 56 | /*! |
199 | 57 | \qmlproperty Filter filter | 57 | \qmlproperty Filter filter |
200 | 58 | 58 | ||
201 | @@ -60,7 +60,7 @@ | |||
202 | 60 | 60 | ||
203 | 61 | \sa Filter | 61 | \sa Filter |
204 | 62 | */ | 62 | */ |
206 | 63 | property var filter: null | 63 | property alias filter: contactsModel.externalFilter |
207 | 64 | /*! | 64 | /*! |
208 | 65 | \qmlproperty bool showAvatar | 65 | \qmlproperty bool showAvatar |
209 | 66 | 66 | ||
210 | @@ -285,10 +285,7 @@ | |||
211 | 285 | } | 285 | } |
212 | 286 | function changeFilter(newFilter) | 286 | function changeFilter(newFilter) |
213 | 287 | { | 287 | { |
218 | 288 | if (root.count > 0) { | 288 | contactsModel.changeFilter(newFilter) |
215 | 289 | contactsModel._clearModel = true | ||
216 | 290 | } | ||
217 | 291 | root.filter = newFilter | ||
219 | 292 | } | 289 | } |
220 | 293 | function reset() | 290 | function reset() |
221 | 294 | { | 291 | { |
222 | @@ -324,8 +321,6 @@ | |||
223 | 324 | contactsModel.update() | 321 | contactsModel.update() |
224 | 325 | } | 322 | } |
225 | 326 | 323 | ||
226 | 327 | onFilterTermChanged: contactSearchTimeout.restart() | ||
227 | 328 | |||
228 | 329 | // colapse contacts if the keyboard appears | 324 | // colapse contacts if the keyboard appears |
229 | 330 | Connections { | 325 | Connections { |
230 | 331 | target: Qt.inputMethod | 326 | target: Qt.inputMethod |
231 | @@ -341,7 +336,7 @@ | |||
232 | 341 | id: view | 336 | id: view |
233 | 342 | 337 | ||
234 | 343 | property bool showFavourites: true | 338 | property bool showFavourites: true |
236 | 344 | property bool favouritesIsSelected: false | 339 | property alias favouritesIsSelected: contactsModel.onlyFavorites |
237 | 345 | 340 | ||
238 | 346 | function getSectionText(index) { | 341 | function getSectionText(index) { |
239 | 347 | var tag = listModel.contacts[index].tag.tag | 342 | var tag = listModel.contacts[index].tag.tag |
240 | @@ -488,139 +483,12 @@ | |||
241 | 488 | onContactDisappeared: root.contactDisappeared(contact) | 483 | onContactDisappeared: root.contactDisappeared(contact) |
242 | 489 | clip: true | 484 | clip: true |
243 | 490 | 485 | ||
339 | 491 | InvalidFilter { | 486 | listModel: ContactListModel { |
245 | 492 | id: invalidFilter | ||
246 | 493 | } | ||
247 | 494 | |||
248 | 495 | DetailFilter { | ||
249 | 496 | id: favouritesFilter | ||
250 | 497 | |||
251 | 498 | detail: ContactDetail.Favorite | ||
252 | 499 | field: Favorite.Favorite | ||
253 | 500 | value: true | ||
254 | 501 | matchFlags: DetailFilter.MatchExactly | ||
255 | 502 | } | ||
256 | 503 | |||
257 | 504 | UnionFilter { | ||
258 | 505 | id: contactTermFilter | ||
259 | 506 | |||
260 | 507 | property string value: "" | ||
261 | 508 | |||
262 | 509 | DetailFilter { | ||
263 | 510 | detail: ContactDetail.DisplayLabel | ||
264 | 511 | field: DisplayLabel.Label | ||
265 | 512 | value: contactTermFilter.value | ||
266 | 513 | matchFlags: DetailFilter.MatchContains | ||
267 | 514 | } | ||
268 | 515 | |||
269 | 516 | DetailFilter { | ||
270 | 517 | detail: ContactDetail.PhoneNumber | ||
271 | 518 | field: PhoneNumber.Number | ||
272 | 519 | value: contactTermFilter.value | ||
273 | 520 | matchFlags: DetailFilter.MatchPhoneNumber | ||
274 | 521 | } | ||
275 | 522 | |||
276 | 523 | DetailFilter { | ||
277 | 524 | detail: ContactDetail.PhoneNumber | ||
278 | 525 | field: PhoneNumber.Number | ||
279 | 526 | value: contactTermFilter.value | ||
280 | 527 | matchFlags: DetailFilter.MatchContains | ||
281 | 528 | } | ||
282 | 529 | } | ||
283 | 530 | |||
284 | 531 | |||
285 | 532 | IntersectionFilter { | ||
286 | 533 | id: contactsFilter | ||
287 | 534 | |||
288 | 535 | // avoid runtime warning "depends on non-NOTIFYable properties" | ||
289 | 536 | readonly property alias filtersProxy: contactsFilter.filters | ||
290 | 537 | |||
291 | 538 | property bool active: { | ||
292 | 539 | var filters_ = [] | ||
293 | 540 | if (contactTermFilter.value.length > 0) { | ||
294 | 541 | filters_.push(contactTermFilter) | ||
295 | 542 | } else if (view.favouritesIsSelected) { | ||
296 | 543 | filters_.push(favouritesFilter) | ||
297 | 544 | } | ||
298 | 545 | |||
299 | 546 | if (root.filter) { | ||
300 | 547 | filters_.push(root.filter) | ||
301 | 548 | } | ||
302 | 549 | |||
303 | 550 | // check if the filter has changed | ||
304 | 551 | var oldFilters = filtersProxy | ||
305 | 552 | if (oldFilters.length !== filters_.length) { | ||
306 | 553 | contactsFilter.filters = filters_ | ||
307 | 554 | } else { | ||
308 | 555 | for(var i=0; i < oldFilters.length; i++) { | ||
309 | 556 | if (filters_.indexOf(oldFilters[i]) === -1) { | ||
310 | 557 | contactsFilter.filters = filters_ | ||
311 | 558 | } | ||
312 | 559 | } | ||
313 | 560 | } | ||
314 | 561 | |||
315 | 562 | return (filters_.length > 0) | ||
316 | 563 | } | ||
317 | 564 | } | ||
318 | 565 | |||
319 | 566 | Timer { | ||
320 | 567 | id: contactSearchTimeout | ||
321 | 568 | |||
322 | 569 | running: false | ||
323 | 570 | repeat: false | ||
324 | 571 | interval: 300 | ||
325 | 572 | onTriggered: { | ||
326 | 573 | view.positionViewAtBeginning() | ||
327 | 574 | |||
328 | 575 | root.changeFilter(root.filter) | ||
329 | 576 | contactTermFilter.value = root.filterTerm | ||
330 | 577 | |||
331 | 578 | // manually update if autoUpdate is disabled | ||
332 | 579 | if (!root.autoUpdate) { | ||
333 | 580 | contactsModel.update() | ||
334 | 581 | } | ||
335 | 582 | } | ||
336 | 583 | } | ||
337 | 584 | |||
338 | 585 | listModel: ContactModel { | ||
340 | 586 | id: contactsModel | 487 | id: contactsModel |
341 | 587 | 488 | ||
342 | 588 | property bool _clearModel: false | ||
343 | 589 | |||
344 | 590 | manager: root.manager | 489 | manager: root.manager |
345 | 591 | sortOrders: root.sortOrders | 490 | sortOrders: root.sortOrders |
346 | 592 | fetchHint: root.fetchHint | 491 | fetchHint: root.fetchHint |
347 | 593 | filter: { | ||
348 | 594 | if (contactsModel._clearModel) { | ||
349 | 595 | return invalidFilter | ||
350 | 596 | } else if (contactsFilter.active) { | ||
351 | 597 | return contactsFilter | ||
352 | 598 | } else { | ||
353 | 599 | return null | ||
354 | 600 | } | ||
355 | 601 | } | ||
356 | 602 | |||
357 | 603 | onErrorChanged: { | ||
358 | 604 | if (error) { | ||
359 | 605 | console.error("Contact List error:" + error) | ||
360 | 606 | } | ||
361 | 607 | } | ||
362 | 608 | |||
363 | 609 | onContactsChanged: { | ||
364 | 610 | //WORKAROUND: clear the model before start populate it with the new contacts | ||
365 | 611 | //otherwise the model will wait for all contacts before show any new contact | ||
366 | 612 | |||
367 | 613 | //after all contacts get removed we can populate the model again, this will show | ||
368 | 614 | //new contacts as soon as it arrives in the model | ||
369 | 615 | if (contactsModel._clearModel && contacts.length === 0) { | ||
370 | 616 | contactsModel._clearModel = false | ||
371 | 617 | // do a new update if autoUpdate is false | ||
372 | 618 | if (!contactsModel.autoUpdate) { | ||
373 | 619 | contactsModel.update() | ||
374 | 620 | } | ||
375 | 621 | |||
376 | 622 | } | ||
377 | 623 | } | ||
378 | 624 | } | 492 | } |
379 | 625 | } | 493 | } |
380 | 626 | 494 | ||
381 | 627 | 495 | ||
382 | === modified file 'src/imports/Ubuntu/Contacts/qmldir' | |||
383 | --- src/imports/Ubuntu/Contacts/qmldir 2014-08-13 20:52:57 +0000 | |||
384 | +++ src/imports/Ubuntu/Contacts/qmldir 2014-08-18 18:28:33 +0000 | |||
385 | @@ -6,6 +6,7 @@ | |||
386 | 6 | ContactDetailOnlineAccountTypeModel 0.1 ContactDetailOnlineAccountTypeModel.qml | 6 | ContactDetailOnlineAccountTypeModel 0.1 ContactDetailOnlineAccountTypeModel.qml |
387 | 7 | ContactDetailPhoneNumberTypeModel 0.1 ContactDetailPhoneNumberTypeModel.qml | 7 | ContactDetailPhoneNumberTypeModel 0.1 ContactDetailPhoneNumberTypeModel.qml |
388 | 8 | ContactFetch 0.1 ContactFetch.qml | 8 | ContactFetch 0.1 ContactFetch.qml |
389 | 9 | ContactListModel 0.1 ContactListModel.qml | ||
390 | 9 | ContactListView 0.1 ContactListView.qml | 10 | ContactListView 0.1 ContactListView.qml |
391 | 10 | ContactPreviewPage 0.1 ContactPreviewPage.qml | 11 | ContactPreviewPage 0.1 ContactPreviewPage.qml |
392 | 11 | ListItemWithActions 0.1 ListItemWithActions.qml | 12 | ListItemWithActions 0.1 ListItemWithActions.qml |
FAILED: Continuous integration, rev:244 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- ci/285/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/3613 jenkins. qa.ubuntu. com/job/ generic- mediumtests- utopic/ 2829 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- amd64-ci/ 285 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- armhf-ci/ 285 jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- armhf-ci/ 285/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ phablet- team-address- book-app- staging- utopic- i386-ci/ 285 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- mako/3498 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/4860 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/4860/ artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 11560 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-utopic/ 2294 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/3113 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/3113/ artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/phablet- team-address- book-app- staging- ci/285/ rebuild
http://