Merge lp:~renatofilho/address-book-app/release-2014-07-17 into lp:address-book-app
- release-2014-07-17
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Bill Filler |
Approved revision: | 240 |
Merged at revision: | 252 |
Proposed branch: | lp:~renatofilho/address-book-app/release-2014-07-17 |
Merge into: | lp:address-book-app |
Diff against target: |
994 lines (+484/-123) 13 files modified
CMakeLists.txt (+8/-0) debian/control (+1/-1) src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml (+3/-5) src/imports/ContactEdit/ContactEditor.qml (+1/-1) src/imports/ContactList/ContactListPage.qml (+41/-23) src/imports/Ubuntu/Contacts/ContactDelegate.qml (+6/-6) src/imports/Ubuntu/Contacts/ContactListView.qml (+111/-78) src/imports/Ubuntu/Contacts/ContactSimpleListView.qml (+4/-1) src/imports/Ubuntu/Contacts/FastScroll.qml (+9/-3) src/imports/Ubuntu/Contacts/ListItemWithActions.qml (+9/-4) tests/autopilot/address_book_app/tests/__init__.py (+2/-0) tests/qml/CMakeLists.txt (+8/-1) tests/qml/tst_ListWithActions.qml (+281/-0) |
To merge this branch: | bzr merge lp:~renatofilho/address-book-app/release-2014-07-17 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Bill Filler (community) | Needs Fixing | ||
Gustavo Pichorim Boiko (community) | Approve | ||
Review via email: mp+227255@code.launchpad.net |
Commit message
[Contacts] Fixed delete action activation.
[ContactEditPage] Make sure that the address book combo box is visible when creating a new contact from a external app using the uri handler.
[ContatListPage] Update ContactListPage "+ Create New" button visuals.
[Contacts] Export header property on ContactListView
[ContactListVie
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:228
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
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? YES
If you changed the packaging (debian), did you add a core-dev as a reviewer to this MP? NO PACKAGE CHANGE
Gustavo Pichorim Boiko (boiko) wrote : | # |
Did you perform an exploratory manual test run of the code change and any related functionality on device or emulator?
Yes
Did CI run pass? If not, please explain why.
Yes
Have you checked that submitter has accurately filled out the submitter checklist and has taken no shortcut?
Yes
Code looks good and works as expected
Bill Filler (bfiller) wrote : | # |
Not working for me, a few issues:
1) swipe to delete on contacts list page still doesn't work
2) Address book combo is not displayed when creating a new contact directly from address book app. Works only via url handler now.
3) "create new" when called from url handler doesn't ensure the contact list is visible and scrolled to the top.
-- If you previously had app open and list scrolled down it should ensure it's scrolled to top so you can see "+ create new" button
-- If you previously had app open and viewing favorites, it should reset to top of "All" list. Currently it stays on favorites.
4) Fast scroll and release on letter "A" and a lot of times the "A" icon gets stuck visible even though the fast scroll list has disappeared
5) Contact list should collapse any expansions when you start scrolling, currently the contact stays expanded
- 229. By Renato Araujo Oliveira Filho
-
Fixed swipe to delete.
- 230. By Renato Araujo Oliveira Filho
-
Fixed addressbook visibility when creating a new contact.
- 231. By Renato Araujo Oliveira Filho
-
Make sure that the list scroll back to begginer when app is invoked by other app.
- 232. By Renato Araujo Oliveira Filho
-
Fixed fast scroll disappear while jumping into the letters.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:232
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
- 233. By Renato Araujo Oliveira Filho
-
Reset contact list when the address-book app is called from another app.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:233
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
- 234. By Renato Araujo Oliveira Filho
-
colllapse contact if the user starts scrolling the list.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:234
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
- 235. By Renato Araujo Oliveira Filho
-
Fixed focus problem in search field.
- 236. By Renato Araujo Oliveira Filho
-
Make sure that the fast scroll letter disappear with the alphabetical list.
- 237. By Renato Araujo Oliveira Filho
-
Updated save icon on contact indicator.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:236
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:237
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
Bill Filler (bfiller) wrote : | # |
Only problem is see now is this:
>5) Contact list should collapse any expansions when you start scrolling, currently the contact >stays expanded
During manual scrolling the list is collapsed as it should be. The problem now is if the keyboard is visible and you try to expand a row that is right above keyboard. It starts to expand, then scrolls up so it's visible, and then the scrolling causes it to collapse.
To reproduce:
- search for contacts
- select a contact that is directly above keyboard
- notice that it expands and then collapses before you can see it
- it should expand and scroll into view
If we can't detect the different kinds of scrolls then lets not autocollapse for now.
- 238. By Renato Araujo Oliveira Filho
-
Only auto collapse the contact when flick starts.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:238
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
- 239. By Renato Araujo Oliveira Filho
-
Fixed list flicking stop during the item expansion animation
- 240. By Renato Araujo Oliveira Filho
-
Avoid to stop the contact list view while collapsing the contact.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:240
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
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://
Bill Filler (bfiller) wrote : | # |
going to land this MR but still one problem you can fix later.
If contact expanded it works fine when you flick up. But when you flick down the contact usually gets stuck at the bottom and the flick doesn't continue. Sometimes it works but mostly not.
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-07-16 12:56:19 +0000 |
3 | +++ CMakeLists.txt 2014-07-23 23:51:06 +0000 |
4 | @@ -21,6 +21,13 @@ |
5 | find_program(INTLTOOL_MERGE intltool-merge) |
6 | find_program(INTLTOOL_EXTRACT intltool-extract) |
7 | |
8 | +if(NOT INTLTOOL_MERGE) |
9 | + message(FATAL_ERROR "intltool-merge not found. Try install intltool package;") |
10 | +endif() |
11 | +if(NOT INTLTOOL_EXTRACT) |
12 | + message(FATAL_ERROR "intltool-extract not found. Try install intltool package;") |
13 | +endif() |
14 | + |
15 | set(ADDRESS_BOOK_APP_DIR ${CMAKE_INSTALL_DATADIR}/address-book-app) |
16 | set(ADDRESS_BOOK_APP_FULL_DIR ${CMAKE_INSTALL_FULL_DATADIR}/address-book-app) |
17 | set(ADDRESS_BOOK_APP_NAME "Address Book") |
18 | @@ -34,6 +41,7 @@ |
19 | option(INSTALL_TESTS "Install the tests on make install" on) |
20 | option(INSTALL_COMPONENTS "Install the Ubuntu contact components" on) |
21 | option(CLICK_MODE "Installs to a contained location" off) |
22 | +option(USE_XVFB "Use XVFB to run qml tests" on) |
23 | |
24 | # Tests |
25 | enable_testing() |
26 | |
27 | === modified file 'debian/control' |
28 | --- debian/control 2014-07-09 17:22:14 +0000 |
29 | +++ debian/control 2014-07-23 23:51:06 +0000 |
30 | @@ -41,7 +41,7 @@ |
31 | qtdeclarative5-ubuntu-content0.1, |
32 | qtdeclarative5-ubuntu-history0.1, |
33 | qtdeclarative5-ubuntu-keyboard-extensions0.1, |
34 | - qtdeclarative5-ubuntu-telephony-phonenumber0.1, |
35 | + qtdeclarative5-ubuntu-telephony-phonenumber0.1 (>= 0.1+14.10.20140715.1), |
36 | ${misc:Depends}, |
37 | ${shlibs:Depends}, |
38 | Description: Address Book application |
39 | |
40 | === modified file 'src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml' |
41 | --- src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-06-12 22:55:20 +0000 |
42 | +++ src/imports/ContactEdit/ContactDetailSyncTargetEditor.qml 2014-07-23 23:51:06 +0000 |
43 | @@ -24,7 +24,7 @@ |
44 | ContactDetailBase { |
45 | id: root |
46 | |
47 | - property bool active: false |
48 | + property alias active: sourceModel.autoUpdate |
49 | |
50 | function save() { |
51 | // only changes the target sync for new contacts |
52 | @@ -54,9 +54,8 @@ |
53 | property bool isNewContact: contact && contact.contactId === "qtcontacts:::" |
54 | property real myHeight: sources.containerHeight + units.gu(4) + label.height |
55 | |
56 | - detail: contact ? contact.detail(ContactDetail.SyncTarget) : null |
57 | - implicitHeight: isNewContact && sources.model && (sources.model.contacts.length > 1) ? myHeight : 0 |
58 | - |
59 | + detail: root.contact ? contact.detail(ContactDetail.SyncTarget) : null |
60 | + implicitHeight: root.isNewContact && sources.model && (sources.model.contacts.length > 1) ? myHeight : 0 |
61 | |
62 | ContactModel { |
63 | id: sourceModel |
64 | @@ -118,6 +117,5 @@ |
65 | sourceModel.update() |
66 | } |
67 | } |
68 | - |
69 | } |
70 | |
71 | |
72 | === modified file 'src/imports/ContactEdit/ContactEditor.qml' |
73 | --- src/imports/ContactEdit/ContactEditor.qml 2014-07-11 17:27:03 +0000 |
74 | +++ src/imports/ContactEdit/ContactEditor.qml 2014-07-23 23:51:06 +0000 |
75 | @@ -381,7 +381,7 @@ |
76 | action: Action { |
77 | objectName: "save" |
78 | |
79 | - iconName: "save" |
80 | + iconName: "ok" |
81 | text: i18n.tr("Save") |
82 | enabled: !nameEditor.isEmpty() || !phonesEditor.isEmpty() |
83 | onTriggered: contactEditor.save() |
84 | |
85 | === modified file 'src/imports/ContactList/ContactListPage.qml' |
86 | --- src/imports/ContactList/ContactListPage.qml 2014-07-16 21:46:54 +0000 |
87 | +++ src/imports/ContactList/ContactListPage.qml 2014-07-23 23:51:06 +0000 |
88 | @@ -139,6 +139,7 @@ |
89 | { |
90 | newPhoneToAdd = phoneNumber |
91 | state = "newphone" |
92 | + contactList.reset() |
93 | } |
94 | |
95 | title: i18n.tr("Contacts") |
96 | @@ -193,30 +194,45 @@ |
97 | } |
98 | } |
99 | |
100 | - Button { |
101 | - id: addNewContactButton |
102 | - objectName: "addNewContact" |
103 | - |
104 | - text: i18n.tr("+ New Contact") |
105 | - anchors { |
106 | - top: parent.top |
107 | - left: parent.left |
108 | - right: parent.right |
109 | - margins: visible ? units.gu(2) : 0 |
110 | - } |
111 | - height: visible ? units.gu(4) : 0 |
112 | - visible: false |
113 | - onClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd) |
114 | - } |
115 | - |
116 | flickable: null //contactList.fastScrolling ? null : contactList.view |
117 | ContactsUI.ContactListView { |
118 | id: contactList |
119 | objectName: "contactListView" |
120 | |
121 | + header: Rectangle { |
122 | + id: addNewContactButton |
123 | + objectName: "addNewContact" |
124 | + |
125 | + anchors { |
126 | + left: parent.left |
127 | + right: parent.right |
128 | + } |
129 | + height: visible ? units.gu(8) : 0 |
130 | + color: Theme.palette.normal.background |
131 | + |
132 | + Rectangle { |
133 | + anchors.fill: parent |
134 | + color: Theme.palette.selected.background |
135 | + opacity: addNewContactButtonArea.pressed ? 1.0 : 0.0 |
136 | + } |
137 | + |
138 | + Label { |
139 | + anchors.centerIn: parent |
140 | + text: i18n.tr("+ Create New") |
141 | + fontSize: "large" |
142 | + } |
143 | + |
144 | + visible: false |
145 | + MouseArea { |
146 | + id: addNewContactButtonArea |
147 | + |
148 | + anchors.fill: parent |
149 | + onClicked: mainPage.createContactWithPhoneNumber(mainPage.newPhoneToAdd) |
150 | + } |
151 | + } |
152 | + |
153 | anchors { |
154 | - top: addNewContactButton.bottom |
155 | - topMargin: addNewContactButton.visible ? units.gu(2) : 0 |
156 | + top: parent.top |
157 | left: parent.left |
158 | bottom: keyboard.top |
159 | right: parent.right |
160 | @@ -417,7 +433,10 @@ |
161 | visible: mainPage.searching |
162 | iconName: "close" |
163 | text: i18n.tr("Cancel") |
164 | - onTriggered: mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "") |
165 | + onTriggered: { |
166 | + contactList.forceActiveFocus() |
167 | + mainPage.state = (mainPage.state === "newphoneSearching" ? "newphone" : "") |
168 | + } |
169 | } |
170 | } |
171 | } |
172 | @@ -518,11 +537,10 @@ |
173 | } |
174 | ] |
175 | tools: toolbarItemsNormalMode |
176 | - |
177 | - // WORKAROUND: Avoid the gap btw the header and the contact list when the list moves |
178 | - // see bug #1296764 |
179 | onActiveChanged: { |
180 | - contactList.returnToBounds() |
181 | + if (active && addNewContactButton.visible) { |
182 | + contactList.positionViewAtBeginning() |
183 | + } |
184 | } |
185 | |
186 | onSyncEnabledChanged: { |
187 | |
188 | === modified file 'src/imports/Ubuntu/Contacts/ContactDelegate.qml' |
189 | --- src/imports/Ubuntu/Contacts/ContactDelegate.qml 2014-07-10 20:23:11 +0000 |
190 | +++ src/imports/Ubuntu/Contacts/ContactDelegate.qml 2014-07-23 23:51:06 +0000 |
191 | @@ -32,6 +32,7 @@ |
192 | property variant titleFields: [ Name.FirstName, Name.LastName ] |
193 | property bool detailsShown: false |
194 | property int loaderOpacity: 0.0 |
195 | + property bool flicking: false |
196 | |
197 | signal clicked(int index, QtObject contact) |
198 | signal pressAndHold(int index, QtObject contact) |
199 | @@ -181,7 +182,9 @@ |
200 | Behavior on height { |
201 | id: behaviorOnHeight |
202 | |
203 | - enabled: false |
204 | + property bool active: false |
205 | + |
206 | + enabled: active && !root.flicking |
207 | UbuntuNumberAnimation { } |
208 | } |
209 | |
210 | @@ -201,7 +204,7 @@ |
211 | } |
212 | PropertyChanges { |
213 | target: behaviorOnHeight |
214 | - enabled: true |
215 | + active: true |
216 | } |
217 | } |
218 | ] |
219 | @@ -210,10 +213,6 @@ |
220 | from: "expanded" |
221 | to: "" |
222 | SequentialAnimation { |
223 | - UbuntuNumberAnimation { |
224 | - target: root |
225 | - properties: "height, loaderOpacity" |
226 | - } |
227 | PropertyAction { |
228 | target: root |
229 | property: "clip" |
230 | @@ -244,6 +243,7 @@ |
231 | properties: "ListView.delayRemove" |
232 | value: true |
233 | } |
234 | + |
235 | } |
236 | } |
237 | ] |
238 | |
239 | === modified file 'src/imports/Ubuntu/Contacts/ContactListView.qml' |
240 | --- src/imports/Ubuntu/Contacts/ContactListView.qml 2014-07-16 19:31:08 +0000 |
241 | +++ src/imports/Ubuntu/Contacts/ContactListView.qml 2014-07-23 23:51:06 +0000 |
242 | @@ -44,6 +44,8 @@ |
243 | readonly property alias view: view |
244 | readonly property alias count: view.count |
245 | |
246 | + property var header: [] |
247 | + |
248 | /*! |
249 | \qmlproperty string contactStringFilter |
250 | |
251 | @@ -202,6 +204,7 @@ |
252 | This property holds a list with the index of selected items |
253 | */ |
254 | readonly property alias isInSelectionMode: view.isInSelectionMode |
255 | + |
256 | /*! |
257 | This handler is called when the selection mode is finished without be canceled |
258 | */ |
259 | @@ -273,7 +276,7 @@ |
260 | } |
261 | function positionViewAtBeginning() |
262 | { |
263 | - view.positionViewAtBeginning() |
264 | + moveToBegining.restart() |
265 | } |
266 | function changeFilter(newFilter) |
267 | { |
268 | @@ -282,6 +285,16 @@ |
269 | } |
270 | root.filter = newFilter |
271 | } |
272 | + function reset() |
273 | + { |
274 | + if (view.favouritesIsSelected) { |
275 | + root.changeFilter(root.filter) |
276 | + view.favouritesIsSelected = false |
277 | + } else { |
278 | + positionViewAtBeginning() |
279 | + } |
280 | + } |
281 | + |
282 | /*! |
283 | Causes the list to update |
284 | \l autoUpdate |
285 | @@ -405,105 +418,119 @@ |
286 | } |
287 | } |
288 | |
289 | + // WORKAROUND: The SDK header causes the contactY to move to a wrong postion |
290 | + // calling the positionViewAtBeginning after the list created fix that |
291 | + Timer { |
292 | + id: moveToBegining |
293 | + |
294 | + interval: 100 |
295 | + running: false |
296 | + repeat: false |
297 | + onTriggered: view.positionViewAtBeginning() |
298 | + } |
299 | + |
300 | header: Column { |
301 | id: mostCalledView |
302 | |
303 | - function makeItemVisible(item) |
304 | - { |
305 | - var itemY = mostCalledView.y + item.y |
306 | - var areaY = view.contentY |
307 | - if (itemY < areaY) { |
308 | - view.contentY = itemY |
309 | - view.returnToBounds() |
310 | - } |
311 | - } |
312 | - |
313 | anchors { |
314 | left: parent.left |
315 | right: parent.right |
316 | } |
317 | - height: visible ? childrenRect.height : 0 |
318 | - visible: view.favouritesIsSelected && (callerRepeat.count > 0) |
319 | onHeightChanged: { |
320 | if (calledModel.currentIndex != -1) { |
321 | mostCalledView.makeItemVisible(callerRepeat.itemAt(calledModel.currentIndex)) |
322 | } |
323 | } |
324 | - |
325 | - // WORKAROUND: The SDK header causes the contactY to move to a wrong postion |
326 | - // calling the positionViewAtBeginning after the list created fix that |
327 | - Timer { |
328 | - id: moveToBegining |
329 | - |
330 | - interval: 100 |
331 | - running: false |
332 | - repeat: false |
333 | - onTriggered: view.positionViewAtBeginning() |
334 | + Item { |
335 | + id: headerContents |
336 | + anchors { |
337 | + left: parent.left |
338 | + right: parent.right |
339 | + } |
340 | + height: childrenRect.height |
341 | + children: root.header |
342 | } |
343 | |
344 | - Rectangle { |
345 | - color: Theme.palette.normal.background |
346 | + Column { |
347 | + function makeItemVisible(item) |
348 | + { |
349 | + var itemY = mostCalledView.y + item.y |
350 | + var areaY = view.contentY |
351 | + if (itemY < areaY) { |
352 | + view.contentY = itemY |
353 | + view.returnToBounds() |
354 | + } |
355 | + } |
356 | + |
357 | + visible: view.favouritesIsSelected && (callerRepeat.count > 0) |
358 | anchors { |
359 | left: parent.left |
360 | right: parent.right |
361 | - margins: units.gu(1) |
362 | - } |
363 | - height: units.gu(3) |
364 | - Label { |
365 | - anchors.fill: parent |
366 | - verticalAlignment: Text.AlignVCenter |
367 | - text: i18n.tr("Frequently called") |
368 | - font.pointSize: 76 |
369 | - } |
370 | - ListItem.ThinDivider { |
371 | + } |
372 | + height: visible ? childrenRect.height : 0 |
373 | + |
374 | + Rectangle { |
375 | + color: Theme.palette.normal.background |
376 | anchors { |
377 | left: parent.left |
378 | right: parent.right |
379 | - bottom: parent.bottom |
380 | - } |
381 | - } |
382 | - } |
383 | - Repeater { |
384 | - id: callerRepeat |
385 | - |
386 | - model: MostCalledModel { |
387 | - id: calledModel |
388 | - |
389 | - readonly property bool visible: view.favouritesIsSelected |
390 | - |
391 | - onVisibleChanged: { |
392 | - // update the model every time that it became visible |
393 | - // in fact calling update only reloads the model data if it has changed |
394 | - if (visible) { |
395 | - model.update() |
396 | - } |
397 | - } |
398 | - onInfoRequested: root.infoRequested(contact) |
399 | - onDetailClicked: root.detailClicked(contact, detail, action) |
400 | - onAddContactClicked: root.addContactClicked(label) |
401 | - onCurrentIndexChanged: { |
402 | - if (currentIndex !== -1) { |
403 | - view.currentIndex = -1 |
404 | - } |
405 | - } |
406 | - |
407 | - // WORKAROUND: The SDK header causes the contactY to move to a wrong postion |
408 | - // calling the positionViewAtBeginning after the list created fix that |
409 | - onLoaded: moveToBegining.restart() |
410 | - } |
411 | - } |
412 | - |
413 | - Connections { |
414 | - target: view |
415 | - onCurrentIndexChanged: { |
416 | - if (view.currentIndex !== -1) { |
417 | - calledModel.currentIndex = -1 |
418 | + margins: units.gu(1) |
419 | + } |
420 | + height: units.gu(3) |
421 | + Label { |
422 | + anchors.fill: parent |
423 | + verticalAlignment: Text.AlignVCenter |
424 | + text: i18n.tr("Frequently called") |
425 | + font.pointSize: 76 |
426 | + } |
427 | + ListItem.ThinDivider { |
428 | + anchors { |
429 | + left: parent.left |
430 | + right: parent.right |
431 | + bottom: parent.bottom |
432 | + } |
433 | + } |
434 | + } |
435 | + Repeater { |
436 | + id: callerRepeat |
437 | + |
438 | + model: MostCalledModel { |
439 | + id: calledModel |
440 | + |
441 | + readonly property bool visible: view.favouritesIsSelected |
442 | + |
443 | + onVisibleChanged: { |
444 | + // update the model every time that it became visible |
445 | + // in fact calling update only reloads the model data if it has changed |
446 | + if (visible) { |
447 | + model.update() |
448 | + } |
449 | + } |
450 | + onInfoRequested: root.infoRequested(contact) |
451 | + onDetailClicked: root.detailClicked(contact, detail, action) |
452 | + onAddContactClicked: root.addContactClicked(label) |
453 | + onCurrentIndexChanged: { |
454 | + if (currentIndex !== -1) { |
455 | + view.currentIndex = -1 |
456 | + } |
457 | + } |
458 | + |
459 | + // WORKAROUND: The SDK header causes the contactY to move to a wrong postion |
460 | + // calling the positionViewAtBeginning after the list created fix that |
461 | + onLoaded: moveToBegining.restart() |
462 | + } |
463 | + } |
464 | + |
465 | + Connections { |
466 | + target: view |
467 | + onCurrentIndexChanged: { |
468 | + if (view.currentIndex !== -1) { |
469 | + calledModel.currentIndex = -1 |
470 | + } |
471 | } |
472 | } |
473 | } |
474 | } |
475 | - |
476 | - height: Math.min(root.height, contentHeight) |
477 | onError: root.error(message) |
478 | onInfoRequested: root.infoRequested(contact) |
479 | onDetailClicked: root.detailClicked(contact, detail, action) |
480 | @@ -556,6 +583,9 @@ |
481 | IntersectionFilter { |
482 | id: contactsFilter |
483 | |
484 | + // avoid runtime warning "depends on non-NOTIFYable properties" |
485 | + readonly property alias filtersProxy: contactsFilter.filters |
486 | + |
487 | property bool active: { |
488 | var filters_ = [] |
489 | if (contactTermFilter.value.length > 0) { |
490 | @@ -569,7 +599,7 @@ |
491 | } |
492 | |
493 | // check if the filter has changed |
494 | - var oldFilters = contactsFilter.filters |
495 | + var oldFilters = filtersProxy |
496 | if (oldFilters.length !== filters_.length) { |
497 | contactsFilter.filters = filters_ |
498 | } else { |
499 | @@ -650,7 +680,10 @@ |
500 | |
501 | listView: view |
502 | // only enable FastScroll if the we have more than 2 pages of content and sections is enabled |
503 | - enabled: showSections && (view.contentHeight > (view.height * 2)) && (view.height >= minimumHeight) |
504 | + enabled: showSections && |
505 | + (view.contentHeight > (view.height * 2)) && |
506 | + (view.height >= minimumHeight) && |
507 | + (((view.contentY - view.originY) - view.headerItem.height) >= 0) // hearder already invisble |
508 | |
509 | anchors { |
510 | top: view.top |
511 | |
512 | === modified file 'src/imports/Ubuntu/Contacts/ContactSimpleListView.qml' |
513 | --- src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2014-07-15 20:27:57 +0000 |
514 | +++ src/imports/Ubuntu/Contacts/ContactSimpleListView.qml 2014-07-23 23:51:06 +0000 |
515 | @@ -286,6 +286,7 @@ |
516 | dirtyModel.restart() |
517 | } |
518 | |
519 | + onFlickStarted: view.currentIndex = -1 |
520 | listDelegate: ContactDelegate { |
521 | id: contactDelegate |
522 | |
523 | @@ -296,6 +297,7 @@ |
524 | removalAnimation.start() |
525 | } |
526 | |
527 | + flicking: contactListView.flicking |
528 | width: parent.width |
529 | selected: contactListView.multiSelectionEnabled && contactListView.isSelected(contactDelegate) |
530 | defaultAvatarUrl: contactListView.defaultAvatarImageUrl |
531 | @@ -323,6 +325,7 @@ |
532 | } |
533 | } |
534 | |
535 | + |
536 | // used by swipe to delete |
537 | removalAnimation: SequentialAnimation { |
538 | alwaysRunToEnd: true |
539 | @@ -359,6 +362,7 @@ |
540 | return |
541 | // check if we should expand and display the details picker |
542 | } else if (detailToPick !== -1) { |
543 | + //view.highlightFollowsCurrentItem = true |
544 | contactListView.currentIndex = index |
545 | return |
546 | } else if (detailToPick == -1) { |
547 | @@ -384,7 +388,6 @@ |
548 | model: root.listModel |
549 | onContactFetched: contactListView.infoRequested(contact) |
550 | } |
551 | - |
552 | // This is a workaround to make sure the spinner will disappear if the model is empty |
553 | // FIXME: implement a model property to say if the model still busy or not |
554 | Item { |
555 | |
556 | === modified file 'src/imports/Ubuntu/Contacts/FastScroll.qml' |
557 | --- src/imports/Ubuntu/Contacts/FastScroll.qml 2014-07-16 19:31:08 +0000 |
558 | +++ src/imports/Ubuntu/Contacts/FastScroll.qml 2014-07-23 23:51:06 +0000 |
559 | @@ -75,7 +75,7 @@ |
560 | radius: height * 0.3 |
561 | height: pinSize * 2 |
562 | width: height |
563 | - opacity: internal.fastScrolling ? 1.0 : 0.0 |
564 | + opacity: internal.fastScrolling && root.enabled ? 1.0 : 0.0 |
565 | x: -cursor.width - units.gu(3) |
566 | y: { |
567 | if (internal.currentItem) { |
568 | @@ -144,6 +144,8 @@ |
569 | if (isVisible) { |
570 | rail.opacity = 1.0 |
571 | hideTimer.stop() |
572 | + } else if (!root.enabled) { |
573 | + rail.opacity = 0.0 |
574 | } else { |
575 | hideTimer.restart() |
576 | } |
577 | @@ -167,7 +169,7 @@ |
578 | horizontalAlignment: Text.AlignHCenter |
579 | text: internal.fastScrolling && internal.targetSection == modelData ? "" : modelData |
580 | fontSize: "x-small" |
581 | - color: internal.currentItem.text === text ? Theme.palette.selected.foregroundText : Theme.palette.selected.backgroundText |
582 | + color: internal.currentItem && (internal.currentItem.text === text) ? Theme.palette.selected.foregroundText : Theme.palette.selected.backgroundText |
583 | opacity: !internal.modelDirty && Sections.contains(text) ? 1.0 : 0.5 |
584 | } |
585 | } |
586 | @@ -236,6 +238,7 @@ |
587 | if (internal.desireSection != internal.currentSection) { |
588 | var idx = Sections.getIndexFor(internal.desireSection) |
589 | if (idx !== -1) { |
590 | + listView.cancelFlick() |
591 | listView.positionViewAtIndex(idx, ListView.Beginning) |
592 | } |
593 | } |
594 | @@ -290,7 +293,9 @@ |
595 | if (internal.desireSection !== section) { |
596 | internal.desireSection = section |
597 | moveIndicator(section) |
598 | - timerScroll.restart() |
599 | + if (dragArea.pressed) { |
600 | + timerScroll.restart() |
601 | + } |
602 | } |
603 | } |
604 | |
605 | @@ -303,3 +308,4 @@ |
606 | } |
607 | } |
608 | } |
609 | + |
610 | |
611 | === modified file 'src/imports/Ubuntu/Contacts/ListItemWithActions.qml' |
612 | --- src/imports/Ubuntu/Contacts/ListItemWithActions.qml 2014-07-16 20:40:36 +0000 |
613 | +++ src/imports/Ubuntu/Contacts/ListItemWithActions.qml 2014-07-23 23:51:06 +0000 |
614 | @@ -152,6 +152,7 @@ |
615 | leftMargin: units.gu(1) |
616 | bottom: main.bottom |
617 | } |
618 | + visible: rightSideActions.length > 0 |
619 | width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + actionThreshold : 0 |
620 | Row { |
621 | anchors.fill: parent |
622 | @@ -186,6 +187,7 @@ |
623 | |
624 | Rectangle { |
625 | id: main |
626 | + objectName: "mainItem" |
627 | |
628 | anchors { |
629 | top: parent.top |
630 | @@ -238,9 +240,7 @@ |
631 | value: 1.0 |
632 | } |
633 | ScriptAction { |
634 | - script: { |
635 | - root.activeAction.triggered(root) |
636 | - } |
637 | + script: root.activeAction.triggered(root) |
638 | } |
639 | PauseAnimation { |
640 | duration: 500 |
641 | @@ -263,7 +263,7 @@ |
642 | drag { |
643 | target: locked ? null : main |
644 | axis: Drag.XAxis |
645 | - minimumX: -(rightActionsView.width + root.actionThreshold) |
646 | + minimumX: rightActionsView.visible ? -(rightActionsView.width + root.actionThreshold) : 0 |
647 | maximumX: leftActionView.visible ? leftActionView.width : 0 |
648 | } |
649 | |
650 | @@ -278,6 +278,11 @@ |
651 | onClicked: { |
652 | if (main.x === 0) { |
653 | root.itemClicked(mouse) |
654 | + } else if (main.x > 0) { |
655 | + var action = getActionAt(Qt.point(mouse.x, mouse.y)) |
656 | + if (action && action !== -1) { |
657 | + action.triggered(root) |
658 | + } |
659 | } else { |
660 | var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y)) |
661 | if (actionIndex !== -1) { |
662 | |
663 | === modified file 'tests/autopilot/address_book_app/tests/__init__.py' |
664 | --- tests/autopilot/address_book_app/tests/__init__.py 2014-07-07 13:44:45 +0000 |
665 | +++ tests/autopilot/address_book_app/tests/__init__.py 2014-07-23 23:51:06 +0000 |
666 | @@ -61,6 +61,8 @@ |
667 | vcard_data = AddressBookAppTestCase.VCARD_PATH_BIN |
668 | |
669 | os.environ["ADDRESS_BOOK_TEST_DATA"] = vcard_data |
670 | + os.environ["LANG"] = "en_US.UTF-8" |
671 | + os.environ["LANGUAGE"] ="en_US" |
672 | if vcard_data != "": |
673 | print("Using vcard %s" % vcard_data) |
674 | if os.path.exists(self.app_bin): |
675 | |
676 | === modified file 'tests/qml/CMakeLists.txt' |
677 | --- tests/qml/CMakeLists.txt 2014-07-05 22:00:45 +0000 |
678 | +++ tests/qml/CMakeLists.txt 2014-07-23 23:51:06 +0000 |
679 | @@ -9,15 +9,21 @@ |
680 | ) |
681 | |
682 | macro(DECLARE_QML_TEST TST_NAME TST_QML_FILE) |
683 | + if(USE_XVFB) |
684 | + set(COMMAND_PREFIX ${XVFB_RUN_BIN} -a -s "-screen 0 1024x768x24") |
685 | + else() |
686 | + set(COMMAND_PREFIX "") |
687 | + endif() |
688 | add_test(NAME ${TST_NAME} |
689 | WORKING_DIRECTORY ${CMAKE_BINARY_DIR} |
690 | - COMMAND ${XVFB_RUN_BIN} -a -s "-screen 0 1024x768x24" ${QMLTESTRUNNER_BIN} -import ${imports_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE} |
691 | + COMMAND ${COMMAND_PREFIX} ${QMLTESTRUNNER_BIN} -import ${imports_BINARY_DIR} -input ${CMAKE_CURRENT_SOURCE_DIR}/${TST_QML_FILE} |
692 | ) |
693 | endmacro() |
694 | |
695 | if(QMLTESTRUNNER_BIN AND XVFB_RUN_BIN) |
696 | declare_qml_test("contact_editor" tst_ContactEditor.qml) |
697 | declare_qml_test("contact_avatar" tst_ContactAvatar.qml) |
698 | + declare_qml_test("list_with_actions" tst_ListWithActions.qml) |
699 | else() |
700 | if (NOT QMLTESTRUNNER_BIN) |
701 | message(WARNING "Qml tests disabled: qmltestrunner not found") |
702 | @@ -30,5 +36,6 @@ |
703 | ContactUtil.js |
704 | tst_ContactEditor.qml |
705 | tst_ContactAvatar.qml |
706 | + tst_ListWithActions.qml |
707 | ) |
708 | add_custom_target(tst_QmlFiles ALL SOURCES ${QML_TST_FILES}) |
709 | |
710 | === added file 'tests/qml/tst_ListWithActions.qml' |
711 | --- tests/qml/tst_ListWithActions.qml 1970-01-01 00:00:00 +0000 |
712 | +++ tests/qml/tst_ListWithActions.qml 2014-07-23 23:51:06 +0000 |
713 | @@ -0,0 +1,281 @@ |
714 | +/* |
715 | + * Copyright (C) 2014 Canonical, Ltd. |
716 | + * |
717 | + * This program is free software; you can redistribute it and/or modify |
718 | + * it under the terms of the GNU General Public License as published by |
719 | + * the Free Software Foundation; version 3. |
720 | + * |
721 | + * This program is distributed in the hope that it will be useful, |
722 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
723 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
724 | + * GNU General Public License for more details. |
725 | + * |
726 | + * You should have received a copy of the GNU General Public License |
727 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
728 | + */ |
729 | + |
730 | +import QtQuick 2.2 |
731 | +import Ubuntu.Components 0.1 |
732 | +import QtTest 1.0 |
733 | +import Ubuntu.Test 0.1 |
734 | +import Ubuntu.Contacts 0.1 |
735 | + |
736 | +Item { |
737 | + id: root |
738 | + |
739 | + property var itemList: null |
740 | + |
741 | + width: units.gu(40) |
742 | + height: units.gu(80) |
743 | + |
744 | + Component { |
745 | + id: itemListComponent |
746 | + |
747 | + Column { |
748 | + id: itemList |
749 | + |
750 | + readonly property int rightActionsLength: 3 |
751 | + |
752 | + signal actionTriggered(var action) |
753 | + |
754 | + property var signalSpy: SignalSpy { |
755 | + target: itemList |
756 | + signalName: "actionTriggered" |
757 | + } |
758 | + |
759 | + anchors.fill: parent |
760 | + |
761 | + Repeater { |
762 | + model: 5 |
763 | + |
764 | + ListItemWithActions { |
765 | + id: listWithActions |
766 | + objectName: "listWithActions" + index |
767 | + |
768 | + anchors { |
769 | + left: parent.left |
770 | + right: parent.right |
771 | + } |
772 | + height: units.gu(8) |
773 | + triggerActionOnMouseRelease: true |
774 | + Rectangle { |
775 | + anchors.fill: parent |
776 | + color: "blue" |
777 | + } |
778 | + |
779 | + leftSideAction: Action { |
780 | + id: deleteAction |
781 | + objectName: "deleteAction" |
782 | + |
783 | + iconName: "delete" |
784 | + onTriggered: itemList.actionTriggered(deleteAction, value) |
785 | + } |
786 | + |
787 | + rightSideActions: [ |
788 | + Action { |
789 | + id: messageAction |
790 | + |
791 | + iconName: "message" |
792 | + onTriggered: itemList.actionTriggered(messageAction) |
793 | + }, |
794 | + Action { |
795 | + id: shareAction |
796 | + |
797 | + iconName: "share" |
798 | + onTriggered: itemList.actionTriggered(shareAction) |
799 | + }, |
800 | + Action { |
801 | + id: contactAction |
802 | + |
803 | + iconName: "stock_contact" |
804 | + onTriggered: itemList.actionTriggered(contactAction) |
805 | + } |
806 | + ] |
807 | + } |
808 | + } |
809 | + |
810 | + Repeater { |
811 | + model: 5 |
812 | + |
813 | + ListItemWithActions { |
814 | + id: listWithNoRightActions |
815 | + objectName: "listWithNoRightActions" + index |
816 | + |
817 | + anchors { |
818 | + left: parent.left |
819 | + right: parent.right |
820 | + } |
821 | + height: units.gu(8) |
822 | + triggerActionOnMouseRelease: true |
823 | + Rectangle { |
824 | + anchors.fill: parent |
825 | + color: "blue" |
826 | + } |
827 | + |
828 | + leftSideAction: Action { |
829 | + objectName: "deleteAction2" |
830 | + |
831 | + iconName: "delete" |
832 | + onTriggered: itemList.actionTriggered(deleteAction, value) |
833 | + } |
834 | + } |
835 | + } |
836 | + } |
837 | + } |
838 | + |
839 | + UbuntuTestCase { |
840 | + id: listWithActionsTestCase |
841 | + name: 'listWithActionsTestCase' |
842 | + |
843 | + when: windowShown |
844 | + |
845 | + function init() |
846 | + { |
847 | + itemList = itemListComponent.createObject(root) |
848 | + } |
849 | + |
850 | + function cleanup() |
851 | + { |
852 | + itemList.destroy() |
853 | + } |
854 | + |
855 | + function mouseMoveSlowly(item, x, y, dx, dy, steps, stepdelay) { |
856 | + mouseMove(item, x, y); |
857 | + var abs_dx = Math.abs(dx) |
858 | + var abs_dy = Math.abs(dy) |
859 | + var step_dx = dx / steps; |
860 | + var step_dy = dy /steps; |
861 | + |
862 | + var ix = 0; |
863 | + var iy = 0; |
864 | + |
865 | + for (var step=0; step < steps; step++) { |
866 | + if (ix < abs_dx) { |
867 | + ix += step_dx; |
868 | + } |
869 | + if (iy < abs_dy) { |
870 | + iy += step_dy; |
871 | + } |
872 | + mouseMove(item, x + ix, y + iy, stepdelay); |
873 | + } |
874 | + } |
875 | + |
876 | + |
877 | + function swipeToDeleteItem(itemName) |
878 | + { |
879 | + var item = findChild(itemList, itemName) |
880 | + var startX = item.threshold |
881 | + var startY = item.height / 2 |
882 | + var endX = item.width |
883 | + var endY = startY |
884 | + mousePress(item, startX, startY) |
885 | + mouseMoveSlowly(item, |
886 | + startX, startY, |
887 | + endX - startX, endY - startY, |
888 | + 10, 100) |
889 | + mouseRelease(item, endX, endY) |
890 | + tryCompare(item, "swipeState", "LeftToRight") |
891 | + return item |
892 | + } |
893 | + |
894 | + function swipeToLeft(itemName, actionIndex, release) |
895 | + { |
896 | + var item = findChild(itemList, itemName) |
897 | + var startX = item.width - item.threshold |
898 | + var startY = item.height / 2 |
899 | + var endX = 0 |
900 | + var endY = startY |
901 | + |
902 | + if (actionIndex !== -1) |
903 | + endX = startX - ((actionIndex * (item.actionWidth + units.gu(2))) + item.actionThreshold + units.gu(1)) |
904 | + else |
905 | + endX = 0 |
906 | + |
907 | + mousePress(item, startX, startY) |
908 | + mouseMoveSlowly(item, |
909 | + startX, startY, |
910 | + endX - startX, endY - startY, |
911 | + 10, 100) |
912 | + if (release) |
913 | + mouseRelease(item, endX, endY) |
914 | + |
915 | + tryCompare(item, "swipeState", "RightToLeft") |
916 | + return item |
917 | + } |
918 | + |
919 | + function commom_data() |
920 | + { |
921 | + var data = [] |
922 | + data.push({actionIndex: 1, iconName: "message"}) |
923 | + data.push({actionIndex: 2, iconName: "share"}) |
924 | + data.push({actionIndex: 3, iconName: "stock_contact"}) |
925 | + return data |
926 | + } |
927 | + |
928 | + function test_cancelSwipeToDelete() |
929 | + { |
930 | + var item = swipeToDeleteItem("listWithActions2") |
931 | + mouseClick(item, item.width / 2, item.height / 2) |
932 | + compare(itemList.signalSpy.count, 0) |
933 | + } |
934 | + |
935 | + function test_swipeToDelete() |
936 | + { |
937 | + var item = swipeToDeleteItem("listWithActions2") |
938 | + mouseClick(item, item.actionThreshold, item.height / 2) |
939 | + itemList.signalSpy.wait() |
940 | + compare(itemList.signalSpy.count, 1) |
941 | + compare(itemList.signalSpy.signalArguments[0][0].iconName, "delete") |
942 | + } |
943 | + |
944 | + function test_activeRightActions_data() |
945 | + { |
946 | + return commom_data() |
947 | + } |
948 | + |
949 | + function test_activeRightActions(data) |
950 | + { |
951 | + var item = swipeToLeft("listWithActions2", data.actionIndex, false) |
952 | + compare(itemList.signalSpy.count, 0) |
953 | + compare(item.activeAction.iconName, data.iconName) |
954 | + mouseRelease(item, 0, 0) |
955 | + itemList.signalSpy.wait() |
956 | + compare(itemList.signalSpy.count, 1) |
957 | + compare(itemList.signalSpy.signalArguments[0][0].iconName, data.iconName) |
958 | + } |
959 | + |
960 | + function test_lockOnFullSwipe() |
961 | + { |
962 | + var item = swipeToLeft("listWithActions2", -1, true) |
963 | + compare(itemList.signalSpy.count, 0) |
964 | + tryCompare(item, "swipeState", "RightToLeft") |
965 | + } |
966 | + |
967 | + function test_fullSwipeAndClickOnAction_data() |
968 | + { |
969 | + return commom_data() |
970 | + } |
971 | + |
972 | + function test_fullSwipeAndClickOnAction(data) |
973 | + { |
974 | + var item = swipeToLeft("listWithActions2", -1, true) |
975 | + var actionOffset = (itemList.rightActionsLength - data.actionIndex) + 1 |
976 | + var clickX = item.width - ((actionOffset * (item.actionWidth + units.gu(2))) + item.actionWidth / 2) |
977 | + mouseClick(item, clickX, item.height / 2) |
978 | + itemList.signalSpy.wait() |
979 | + compare(itemList.signalSpy.count, 1) |
980 | + compare(itemList.signalSpy.signalArguments[0][0].iconName, data.iconName) |
981 | + } |
982 | + |
983 | + function test_noSwipeWithEmptyRightActions() |
984 | + { |
985 | + var item = findChild(itemList, "listWithNoRightActions2") |
986 | + var startX = item.width - item.threshold |
987 | + var y = item.height / 2 |
988 | + mousePress(item, startX, y) |
989 | + mouseMoveSlowly(item, startX, y, -startX, y, 10, 100) |
990 | + var mainItem = findChild(item, "mainItem") |
991 | + compare(mainItem.x, 0) |
992 | + } |
993 | + } |
994 | +} |
FAILED: Continuous integration, rev:226 jenkins. qa.ubuntu. com/job/ address- book-app- ci/613/ jenkins. qa.ubuntu. com/job/ address- book-app- utopic- amd64-ci/ 66 jenkins. qa.ubuntu. com/job/ address- book-app- utopic- armhf-ci/ 66 jenkins. qa.ubuntu. com/job/ address- book-app- utopic- armhf-ci/ 66/artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ address- book-app- utopic- i386-ci/ 66 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/2160 jenkins. qa.ubuntu. com/job/ generic- mediumtests- utopic/ 1803 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- mako/2375 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/3320 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/3320/ artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 10032 jenkins. qa.ubuntu. com/job/ autopilot- testrunner- otto-utopic/ 1510 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/2017 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- amd64/2017/ artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/address- book-app- ci/613/ rebuild
http://