Merge lp:~tpeeters/ubuntu-ui-toolkit/10-headAnimate into lp:ubuntu-ui-toolkit/staging

Proposed by Tim Peeters
Status: Merged
Approved by: Zsombor Egri
Approved revision: 1213
Merged at revision: 1218
Proposed branch: lp:~tpeeters/ubuntu-ui-toolkit/10-headAnimate
Merge into: lp:ubuntu-ui-toolkit/staging
Prerequisite: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/sourceOverflow
Diff against target: 1044 lines (+391/-124)
16 files modified
modules/Ubuntu/Components/AppHeader.qml (+5/-0)
modules/Ubuntu/Components/Icon10.qml (+1/-1)
modules/Ubuntu/Components/MainView.qml (+1/-0)
modules/Ubuntu/Components/PageStack.qml (+7/-6)
modules/Ubuntu/Components/PageWrapperUtils.js (+3/-1)
modules/Ubuntu/Components/Styles/PageHeadStyle.qml (+2/-0)
modules/Ubuntu/Components/Themes/Ambiance/PageHeadStyle.qml (+166/-29)
tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py (+19/-0)
tests/autopilot/ubuntuuitoolkit/tests/components/test_header.py (+2/-0)
tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.deprecated_TabBar.qml (+61/-0)
tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.new_header.qml (+43/-0)
tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.py (+14/-56)
tests/resources/header/header.qml (+4/-6)
tests/resources/navigation/MyCustomPage.qml (+17/-25)
tests/unit_x11/tst_components/tst_headActions.qml (+13/-0)
tests/unit_x11/tst_components/tst_pagestack_new_header.qml (+33/-0)
To merge this branch: bzr merge lp:~tpeeters/ubuntu-ui-toolkit/10-headAnimate
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Zsombor Egri Pending
Review via email: mp+232201@code.launchpad.net

This proposal supersedes a proposal from 2014-08-22.

Description of the change

Add header animations

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote : Posted in a previous version of this proposal

Looks good, can go in.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'modules/Ubuntu/Components/AppHeader.qml'
2--- modules/Ubuntu/Components/AppHeader.qml 2014-07-17 10:59:18 +0000
3+++ modules/Ubuntu/Components/AppHeader.qml 2014-08-26 11:42:43 +0000
4@@ -37,6 +37,11 @@
5 */
6 property bool animate: true
7
8+ /*!
9+ Animate changing to new title/actions inside the header.
10+ */
11+ property bool animateContents: false
12+
13 Behavior on y {
14 enabled: animate && !(header.flickable && header.flickable.moving)
15 SmoothedAnimation {
16
17=== modified file 'modules/Ubuntu/Components/Icon10.qml'
18--- modules/Ubuntu/Components/Icon10.qml 2014-07-31 14:14:56 +0000
19+++ modules/Ubuntu/Components/Icon10.qml 2014-08-26 11:42:43 +0000
20@@ -83,7 +83,7 @@
21 visible: active
22
23 // Whether or not a color has been set.
24- property bool active: keyColorOut != Qt.rgba(0.0, 0.0, 0.0, 0.0)
25+ property bool active: keyColorOut != Qt.rgba(0.0, 0.0, 0.0, 0.0) && source
26
27 property Image source: active && image.status == Image.Ready ? image : null
28 property color keyColorOut: Qt.rgba(0.0, 0.0, 0.0, 0.0)
29
30=== modified file 'modules/Ubuntu/Components/MainView.qml'
31--- modules/Ubuntu/Components/MainView.qml 2014-08-18 13:34:29 +0000
32+++ modules/Ubuntu/Components/MainView.qml 2014-08-26 11:42:43 +0000
33@@ -341,6 +341,7 @@
34 id: headerItem
35 property real bottomY: headerItem.y + headerItem.height
36 animate: canvas.animate
37+ animateContents: canvas.animate
38
39 title: internal.activePage ? internal.activePage.title : ""
40 flickable: internal.activePage ? internal.activePage.flickable : null
41
42=== modified file 'modules/Ubuntu/Components/PageStack.qml'
43--- modules/Ubuntu/Components/PageStack.qml 2014-08-12 10:03:13 +0000
44+++ modules/Ubuntu/Components/PageStack.qml 2014-08-26 11:42:43 +0000
45@@ -163,7 +163,6 @@
46 function push(page, properties) {
47 if (internal.stack.size() > 0) internal.stack.top().active = false;
48 internal.stack.push(internal.createWrapper(page, properties));
49- internal.stack.top().active = true;
50 internal.stackUpdated();
51 }
52
53@@ -181,8 +180,6 @@
54 if (internal.stack.top().canDestroy) internal.stack.top().destroyObject();
55 internal.stack.pop();
56 internal.stackUpdated();
57-
58- if (internal.stack.size() > 0) internal.stack.top().active = true;
59 }
60
61 /*!
62@@ -216,9 +213,13 @@
63 }
64
65 function stackUpdated() {
66- pageStack.depth =+ stack.size();
67- if (pageStack.depth > 0) currentPage = stack.top().object;
68- else currentPage = null;
69+ pageStack.depth = stack.size();
70+ if (pageStack.depth > 0) {
71+ internal.stack.top().active = true;
72+ currentPage = stack.top().object;
73+ } else {
74+ currentPage = null;
75+ }
76 }
77 }
78
79
80=== modified file 'modules/Ubuntu/Components/PageWrapperUtils.js'
81--- modules/Ubuntu/Components/PageWrapperUtils.js 2013-05-24 13:51:12 +0000
82+++ modules/Ubuntu/Components/PageWrapperUtils.js 2014-08-26 11:42:43 +0000
83@@ -101,8 +101,10 @@
84 */
85 function destroyObject(pageWrapper) {
86 if (pageWrapper.canDestroy) {
87- pageWrapper.object.destroy();
88 pageWrapper.object = null;
89+ // Rely on garbage collector to destroy the object after all
90+ // (other) references are gone. PageHeadStyle uses actions etc.
91+ // of the page to show a fade-out animation after it was popped.
92 pageWrapper.canDestroy = false;
93 }
94 }
95
96=== modified file 'modules/Ubuntu/Components/Styles/PageHeadStyle.qml'
97--- modules/Ubuntu/Components/Styles/PageHeadStyle.qml 2014-06-26 14:24:41 +0000
98+++ modules/Ubuntu/Components/Styles/PageHeadStyle.qml 2014-08-26 11:42:43 +0000
99@@ -53,7 +53,9 @@
100 property int fontWeight
101
102 /*!
103+ \deprecated
104 The color of the title text.
105+ Use \l Page.head.foregroundColor instead.
106 */
107 property color textColor
108
109
110=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/PageHeadStyle.qml'
111--- modules/Ubuntu/Components/Themes/Ambiance/PageHeadStyle.qml 2014-08-26 11:42:42 +0000
112+++ modules/Ubuntu/Components/Themes/Ambiance/PageHeadStyle.qml 2014-08-26 11:42:43 +0000
113@@ -29,9 +29,127 @@
114 textColor: styledItem.config.foregroundColor
115 textLeftMargin: units.gu(2)
116 maximumNumberOfActions: 3
117+ objectName: "PageHeadStyle"
118+
119+ // workaround because autopilot cannot select the SequentalAnimation
120+ // Needed in AppHeader.wait_for_animation() autopilot proxy object and
121+ // in tst_pagestack_new_header.qml unit test.
122+ property bool animating: changeAnimation.running
123
124 implicitHeight: headerStyle.contentHeight + separator.height + separatorBottom.height
125
126+ Component.onCompleted: buffer.update()
127+
128+ Object {
129+ id: buffer
130+
131+ property PageHeadConfiguration config
132+ property string title
133+ property Item pageStack: null
134+ property int pageStackDepth: 0
135+ property var tabsModel: null
136+
137+ function update() {
138+ buffer.config = styledItem.config;
139+ buffer.title = styledItem.title;
140+ buffer.pageStack = styledItem.pageStack;
141+ buffer.pageStackDepth = buffer.pageStack ? buffer.pageStack.depth : 0;
142+ buffer.tabsModel = styledItem.tabsModel ? styledItem.tabsModel : null;
143+ }
144+
145+ // Calling changeAnimation.start() a second time has no effect,
146+ // so below we can call it whenever something changes.
147+ Connections {
148+ target: styledItem
149+ onConfigChanged: buffer.updateConfigAndTitle()
150+ onTitleChanged: buffer.updateConfigAndTitle()
151+ onPageStackChanged: buffer.updateConfigAndTitle()
152+ onTabsModelChanged: buffer.updateConfigAndTitle()
153+ }
154+
155+ function updateConfigAndTitle() {
156+ if (styledItem.animateContents) {
157+ changeAnimation.start();
158+ } else {
159+ buffer.update();
160+ }
161+ }
162+
163+ SequentialAnimation {
164+ id: changeAnimation
165+ objectName: "changeAnimation"
166+ ParallelAnimation {
167+ UbuntuNumberAnimation {
168+ target: foreground
169+ property: "opacity"
170+ from: 1.0
171+ to: 0.0
172+ }
173+ UbuntuNumberAnimation {
174+ target: leftButtonContainer
175+ property: "opacity"
176+ from: 1.0
177+ to: 0.0
178+ }
179+ UbuntuNumberAnimation {
180+ target: actionsContainer
181+ property: "opacity"
182+ from: 1.0
183+ to: 0.0
184+ }
185+ UbuntuNumberAnimation {
186+ target: leftAnchor
187+ properties: "anchors.leftMargin"
188+ from: 0.0
189+ to: -units.gu(5)
190+ }
191+ UbuntuNumberAnimation {
192+ target: rightAnchor
193+ properties: "anchors.rightMargin"
194+ from: 0
195+ to: -units.gu(5)
196+ }
197+ }
198+ ScriptAction {
199+ script: {
200+ buffer.update();
201+ }
202+ }
203+ ParallelAnimation {
204+ UbuntuNumberAnimation {
205+ target: foreground
206+ property: "opacity"
207+ from: 0.0
208+ to: 1.0
209+ }
210+ UbuntuNumberAnimation {
211+ target: leftButtonContainer
212+ property: "opacity"
213+ from: 0.0
214+ to: 1.0
215+ }
216+ UbuntuNumberAnimation {
217+ target: actionsContainer
218+ property: "opacity"
219+ from: 0.0
220+ to: 1.0
221+ }
222+ UbuntuNumberAnimation {
223+ target: leftAnchor
224+ properties: "anchors.leftMargin"
225+ from: -units.gu(5)
226+ to: 0
227+ }
228+ UbuntuNumberAnimation {
229+ target: rightAnchor
230+ properties: "anchors.rightMargin"
231+ from: -units.gu(5)
232+ to: 0
233+ }
234+ }
235+ }
236+ }
237+
238 // FIXME: Workaround to get sectionsRepeater.count in autopilot tests,
239 // see also FIXME in AppHeader where this property is used.
240 property alias __sections_repeater_for_autopilot: sectionsRepeater
241@@ -46,7 +164,7 @@
242 source: headerStyle.separatorSource
243 height: sectionsRow.visible ? units.gu(3) : units.gu(2)
244
245- property PageHeadSections sections: styledItem.config.sections
246+ property PageHeadSections sections: buffer.config.sections
247
248 Row {
249 id: sectionsRow
250@@ -121,9 +239,30 @@
251 }
252
253 Item {
254+ id: leftAnchor
255+ anchors {
256+ top: parent.top
257+ bottom: parent.bottom
258+ left: parent.left
259+ leftMargin: 0
260+ }
261+ width: 0
262+ }
263+ Item {
264+ id: rightAnchor
265+ anchors {
266+ top: parent.top
267+ bottom: parent.bottom
268+ right: parent.right
269+ rightMargin: 0
270+ }
271+ width: 0
272+ }
273+
274+ Item {
275 id: leftButtonContainer
276 anchors {
277- left: parent.left
278+ left: leftAnchor.right
279 top: parent.top
280 leftMargin: width > 0 ? units.gu(1) : 0
281 }
282@@ -133,10 +272,10 @@
283 PageHeadButton {
284 id: customBackButton
285 objectName: "customBackButton"
286- action: styledItem.config.backAction
287- visible: null !== styledItem.config.backAction &&
288- styledItem.config.backAction.visible
289- color: styledItem.config.foregroundColor
290+ action: buffer.config.backAction
291+ visible: null !== buffer.config.backAction &&
292+ buffer.config.backAction.visible
293+ color: buffer.config.foregroundColor
294 }
295
296 PageHeadButton {
297@@ -144,16 +283,14 @@
298 objectName: "backButton"
299
300 iconName: "back"
301- visible: styledItem.pageStack !== null &&
302- styledItem.pageStack !== undefined &&
303- styledItem.pageStack.depth > 1 &&
304- !styledItem.config.backAction
305+ visible: buffer.pageStackDepth > 1 &&
306+ !buffer.config.backAction
307
308 text: "back"
309- color: styledItem.config.foregroundColor
310+ color: buffer.config.foregroundColor
311
312 onTriggered: {
313- styledItem.pageStack.pop();
314+ buffer.pageStack.pop();
315 }
316 }
317
318@@ -162,12 +299,11 @@
319 objectName: "tabsButton"
320
321 iconName: "navigation-menu"
322- visible: styledItem.tabsModel !== null &&
323- styledItem.tabsModel !== undefined &&
324+ visible: buffer.tabsModel !== null &&
325 !backButton.visible &&
326 !customBackButton.visible
327- text: visible ? styledItem.tabsModel.count + " tabs" : ""
328- color: styledItem.config.foregroundColor
329+ text: visible ? buffer.tabsModel.count + " tabs" : ""
330+ color: buffer.config.foregroundColor
331
332 onTriggered: PopupUtils.open(tabsPopoverComponent, tabsButton)
333
334@@ -187,11 +323,11 @@
335 right: parent.right
336 }
337 Repeater {
338- model: styledItem.tabsModel
339+ model: buffer.tabsModel
340 AbstractButton {
341 objectName: "tabButton" + index
342 onClicked: {
343- styledItem.tabsModel.selectedIndex = index;
344+ buffer.tabsModel.selectedIndex = index;
345 tabsPopover.hide();
346 }
347 implicitHeight: units.gu(6) + bottomDividerLine.height
348@@ -224,7 +360,7 @@
349 ListItem.ThinDivider {
350 id: bottomDividerLine
351 anchors.bottom: parent.bottom
352- visible: index < styledItem.tabsModel.count - 1
353+ visible: index < buffer.tabsModel.count - 1
354 }
355 }
356 }
357@@ -238,12 +374,12 @@
358 id: foreground
359 anchors {
360 left: leftButtonContainer.right
361- right: actionsContainer.left
362 top: parent.top
363 // don't keep a margin if there is already a button with spacing
364 leftMargin: leftButtonContainer.width > 0 ? 0 : headerStyle.textLeftMargin
365 }
366 height: headerStyle.contentHeight
367+ width: parent.width - leftButtonContainer.width - actionsContainer.width
368
369 Label {
370 objectName: "header_title_label"
371@@ -254,10 +390,10 @@
372 right: parent.right
373 verticalCenter: parent.verticalCenter
374 }
375- text: styledItem.title
376+ text: buffer.title
377 font.weight: headerStyle.fontWeight
378 fontSize: headerStyle.fontSize
379- color: headerStyle.textColor
380+ color: buffer.config.foregroundColor
381 elide: Text.ElideRight
382 }
383
384@@ -267,7 +403,7 @@
385 // when the bindings below is no longer active
386 id: contentsContainer
387 anchors.fill: parent
388- visible: styledItem.contents || styledItem.config.contents
389+ visible: styledItem.contents || buffer.config.contents
390 }
391 Binding {
392 target: styledItem.contents
393@@ -282,17 +418,17 @@
394 when: styledItem.contents
395 }
396 Binding {
397- target: styledItem.config.contents
398+ target: buffer.config.contents
399 property: "parent"
400 value: contentsContainer
401- when: styledItem.config.contents && !styledItem.contents
402+ when: buffer.config.contents && !styledItem.contents
403 }
404 }
405
406 Row {
407 id: actionsContainer
408
409- property var visibleActions: getVisibleActions(styledItem.config.actions)
410+ property var visibleActions: getVisibleActions(buffer.config.actions)
411 function getVisibleActions(actions) {
412 var visibleActionList = [];
413 for (var i in actions) {
414@@ -316,7 +452,7 @@
415
416 anchors {
417 top: parent.top
418- right: parent.right
419+ right: rightAnchor.left
420 rightMargin: units.gu(1)
421 }
422 width: childrenRect.width
423@@ -328,7 +464,7 @@
424 id: actionButton
425 objectName: action.objectName + "_header_button"
426 action: actionsContainer.visibleActions[index]
427- color: styledItem.config.foregroundColor
428+ color: buffer.config.foregroundColor
429 }
430 }
431
432@@ -337,8 +473,9 @@
433 objectName: "actions_overflow_button"
434 visible: numberOfSlots.requested > numberOfSlots.right
435 iconName: "contextual-menu"
436- color: styledItem.config.foregroundColor
437+ color: buffer.config.foregroundColor
438 height: actionsContainer.height
439+
440 onTriggered: PopupUtils.open(actionsOverflowPopoverComponent, actionsOverflowButton)
441
442 Component {
443
444=== modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py'
445--- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py 2014-08-20 06:45:28 +0000
446+++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_header.py 2014-08-26 11:42:43 +0000
447@@ -67,6 +67,7 @@
448 raise _common.ToolkitException('Old header has no sections')
449
450 try:
451+ self.wait_for_animation()
452 object_name = "section_button_" + str(index)
453 button = self.select_single(objectName=object_name)
454 except dbus.StateNotFoundError:
455@@ -79,6 +80,7 @@
456 if self.useDeprecatedToolbar:
457 raise _common.ToolkitException('Old header has no sections')
458
459+ self.wait_for_animation()
460 sectionsProperties = self.select_single(
461 'QQuickItem', objectName='sectionsProperties')
462 return sectionsProperties.selectedIndex
463@@ -89,12 +91,14 @@
464 if self.useDeprecatedToolbar:
465 raise _common.ToolkitException('Old header has no back button')
466 try:
467+ self.wait_for_animation()
468 back_button = self.select_single(objectName='backButton')
469 except dbus.StateNotFoundError:
470 raise _common.ToolkitException('Missing back button in header')
471 if not back_button.visible:
472 raise _common.ToolkitException('Back button in header not visible')
473 self.pointing_device.click_object(back_button)
474+ self.wait_for_animation()
475
476 def click_custom_back_button(self):
477 self._show_if_not_visible()
478@@ -103,6 +107,7 @@
479 raise _common.ToolkitException(
480 'Old header has no custom back button')
481 try:
482+ self.wait_for_animation()
483 custom_back_button = self.select_single(
484 objectName='customBackButton')
485 except dbus.StateNotFoundError:
486@@ -112,6 +117,7 @@
487 raise _common.ToolkitException(
488 'Custom back button in header not visible')
489 self.pointing_device.click_object(custom_back_button)
490+ self.wait_for_animation()
491
492 def _get_animating(self):
493 if self.useDeprecatedToolbar:
494@@ -120,6 +126,14 @@
495 else:
496 return False
497
498+ def wait_for_animation(self):
499+ try:
500+ style = self.select_single(objectName='PageHeadStyle')
501+ style.animating.wait_for(False)
502+ except dbus.StateNotFoundError:
503+ raise _common.ToolkitException(
504+ 'AppHeader is not using the new PageHeadStyle')
505+
506 @autopilot_logging.log_action(logger.info)
507 def switch_to_next_tab(self):
508 """Open the next tab.
509@@ -143,6 +157,7 @@
510 self._get_animating().wait_for(False)
511
512 def _switch_to_next_tab_in_drawer(self):
513+ self.wait_for_animation()
514 tabs_model_properties = self.select_single(
515 'QQuickItem', objectName='tabsModelProperties')
516 next_tab_index = (tabs_model_properties.selectedIndex
517@@ -167,6 +182,7 @@
518 self._switch_to_tab_in_drawer_by_index(index)
519
520 def _switch_to_tab_in_drawer_by_index(self, index):
521+ self.wait_for_animation()
522 try:
523 tabs_drawer_button = self.select_single(objectName='tabsButton')
524 except dbus.StateNotFoundError:
525@@ -187,6 +203,7 @@
526 "Tab button {0} not found.".format(index))
527
528 self.pointing_device.click_object(tab_button)
529+ self.wait_for_animation()
530
531 def click_action_button(self, action_object_name):
532 """Click an action button of the header.
533@@ -200,8 +217,10 @@
534
535 button = self._get_action_button(action_object_name)
536 self.pointing_device.click_object(button)
537+ self.wait_for_animation()
538
539 def _get_action_button(self, action_object_name):
540+ self.wait_for_animation()
541 try:
542 object_name = action_object_name + "_header_button"
543 button = self.select_single(objectName=object_name)
544
545=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/components/test_header.py'
546--- tests/autopilot/ubuntuuitoolkit/tests/components/test_header.py 2014-07-31 08:21:14 +0000
547+++ tests/autopilot/ubuntuuitoolkit/tests/components/test_header.py 2014-08-26 11:42:43 +0000
548@@ -81,6 +81,7 @@
549 objectName='push_button')
550 self.pointing_device.move_to_object(pushButton)
551 self.pointing_device.click()
552+ self.header.wait_for_animation()
553
554 self.assertEqual(label.visible, False)
555 headerContents = self.header.select_single(
556@@ -94,6 +95,7 @@
557 objectName='push_button')
558 self.pointing_device.move_to_object(pushButton)
559 self.pointing_device.click()
560+ self.header.wait_for_animation()
561
562 headerContents = self.header.select_single(
563 objectName='orange_header_contents')
564
565=== added file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.deprecated_TabBar.qml'
566--- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.deprecated_TabBar.qml 1970-01-01 00:00:00 +0000
567+++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.deprecated_TabBar.qml 2014-08-26 11:42:43 +0000
568@@ -0,0 +1,61 @@
569+/*
570+ * Copyright 2014 Canonical Ltd.
571+ *
572+ * This program is free software; you can redistribute it and/or modify
573+ * it under the terms of the GNU Lesser General Public License as published by
574+ * the Free Software Foundation; version 3.
575+ *
576+ * This program is distributed in the hope that it will be useful,
577+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
578+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
579+ * GNU Lesser General Public License for more details.
580+ *
581+ * You should have received a copy of the GNU Lesser General Public License
582+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
583+ */
584+
585+import QtQuick 2.2
586+import Ubuntu.Components 1.1
587+
588+MainView {
589+ width: units.gu(70)
590+ height: units.gu(60)
591+ useDeprecatedToolbar: true
592+
593+ Tabs {
594+ id: tabs
595+ Tab {
596+ objectName: "tab1"
597+ title: "Tab1"
598+ Page {
599+ tools: ToolbarItems {
600+ ToolbarButton {
601+ text: "Test1"
602+ }
603+ }
604+ }
605+ }
606+ Tab {
607+ objectName: "tab2"
608+ title: "Tab2"
609+ Page {
610+ tools: ToolbarItems {
611+ ToolbarButton {
612+ text: "Test2"
613+ }
614+ }
615+ }
616+ }
617+ Tab {
618+ objectName: "tab3"
619+ title: "Tab3"
620+ Page {
621+ tools: ToolbarItems {
622+ ToolbarButton {
623+ text: "Test3"
624+ }
625+ }
626+ }
627+ }
628+ }
629+}
630
631=== added file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.new_header.qml'
632--- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.new_header.qml 1970-01-01 00:00:00 +0000
633+++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.TabsTestCase.new_header.qml 2014-08-26 11:42:43 +0000
634@@ -0,0 +1,43 @@
635+/*
636+ * Copyright 2014 Canonical Ltd.
637+ *
638+ * This program is free software; you can redistribute it and/or modify
639+ * it under the terms of the GNU Lesser General Public License as published by
640+ * the Free Software Foundation; version 3.
641+ *
642+ * This program is distributed in the hope that it will be useful,
643+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
644+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645+ * GNU Lesser General Public License for more details.
646+ *
647+ * You should have received a copy of the GNU Lesser General Public License
648+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
649+ */
650+
651+import QtQuick 2.2
652+import Ubuntu.Components 1.1
653+
654+MainView {
655+ width: units.gu(70)
656+ height: units.gu(60)
657+ useDeprecatedToolbar: false
658+
659+ Tabs {
660+ id: tabs
661+ Tab {
662+ objectName: "tab1"
663+ title: "Tab1"
664+ Page { }
665+ }
666+ Tab {
667+ objectName: "tab2"
668+ title: "Tab2"
669+ Page { }
670+ }
671+ Tab {
672+ objectName: "tab3"
673+ title: "Tab3"
674+ Page { }
675+ }
676+ }
677+}
678
679=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.py'
680--- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.py 2014-06-02 23:21:48 +0000
681+++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_tabs.py 2014-08-26 11:42:43 +0000
682@@ -14,6 +14,8 @@
683 # You should have received a copy of the GNU Lesser General Public License
684 # along with this program. If not, see <http://www.gnu.org/licenses/>.
685
686+import os
687+
688 try:
689 from unittest import mock
690 except ImportError:
691@@ -23,64 +25,20 @@
692 from ubuntuuitoolkit import tests
693
694
695-TEST_TABS_QML_FORMAT = ("""
696-import QtQuick 2.0
697-import Ubuntu.Components 1.0
698-
699-MainView {{
700- width: units.gu(70)
701- height: units.gu(60)
702- useDeprecatedToolbar: {use_deprecated_toolbar}
703-
704- Tabs {{
705- id: tabs
706- Tab {{
707- objectName: "tab1"
708- title: "Tab1"
709- Page {{
710- tools: ToolbarItems {{
711- ToolbarButton {{
712- text: "Test1"
713- }}
714- }}
715- }}
716- }}
717- Tab {{
718- objectName: "tab2"
719- title: "Tab2"
720- Page {{
721- tools: ToolbarItems {{
722- ToolbarButton {{
723- text: "Test2"
724- }}
725- }}
726- }}
727- }}
728- Tab {{
729- objectName: "tab3"
730- title: "Tab3"
731- Page {{
732- tools: ToolbarItems {{
733- ToolbarButton {{
734- text: "Test3"
735- }}
736- }}
737- }}
738- }}
739- }}
740-}}
741-""")
742-
743-
744-class TabsTestCase(tests.QMLStringAppTestCase):
745+class TabsTestCase(tests.QMLFileAppTestCase):
746+
747+ path = os.path.abspath(__file__)
748+ dir_path = os.path.dirname(path)
749+ deprecated_tabbar_test_qml_file_path = os.path.join(
750+ dir_path, 'test_tabs.TabsTestCase.deprecated_TabBar.qml')
751+ new_header_test_qml_file_path = os.path.join(
752+ dir_path, 'test_tabs.TabsTestCase.new_header.qml')
753
754 scenarios = [
755- ('deprecated tabs', dict(
756- test_qml=TEST_TABS_QML_FORMAT.format(
757- use_deprecated_toolbar='true'))),
758- ('drawer tabs', dict(
759- test_qml=TEST_TABS_QML_FORMAT.format(
760- use_deprecated_toolbar='false')))
761+ ('deprecated TabBar',
762+ dict(test_qml_file_path=deprecated_tabbar_test_qml_file_path)),
763+ ('new header',
764+ dict(test_qml_file_path=new_header_test_qml_file_path))
765 ]
766
767 def test_tabs_custom_proxy_object(self):
768
769=== modified file 'tests/resources/header/header.qml'
770--- tests/resources/header/header.qml 2014-07-31 14:09:45 +0000
771+++ tests/resources/header/header.qml 2014-08-26 11:42:43 +0000
772@@ -206,12 +206,10 @@
773 anchors.centerIn: parent
774 text: "Use back button to return"
775 }
776- tools: ToolbarItems {
777- ToolbarButton {
778- action: Action {
779- iconName: "settings"
780- text: "settings"
781- }
782+ head {
783+ actions: Action {
784+ iconName: "settings"
785+ text: "settings"
786 }
787 }
788 }
789
790=== modified file 'tests/resources/navigation/MyCustomPage.qml'
791--- tests/resources/navigation/MyCustomPage.qml 2014-08-26 11:42:42 +0000
792+++ tests/resources/navigation/MyCustomPage.qml 2014-08-26 11:42:43 +0000
793@@ -15,7 +15,7 @@
794 */
795
796 import QtQuick 2.0
797-import Ubuntu.Components 1.0
798+import Ubuntu.Components 1.1
799
800 Page {
801 title: i18n.tr("My custom page")
802@@ -30,32 +30,24 @@
803 horizontalCenter: parent.horizontalCenter
804 }
805
806- text: i18n.tr("This is an external page\nwith a locked toolbar.")
807+ text: i18n.tr("This is an external page.")
808 color: "#757373"
809 }
810 }
811
812- tools: ToolbarItems {
813- ToolbarButton {
814- action: Action {
815- text: "action 1"
816- iconName: "outgoing-call"
817- }
818- }
819- ToolbarButton {
820- action: Action {
821- text: "action 2"
822- iconName: "missed-call"
823- }
824- }
825- ToolbarButton {
826- action: Action {
827- text: "another one"
828- iconSource: "call_icon.png"
829- }
830- }
831-
832- opened: true
833- locked: true
834- }
835+ head.actions: [
836+ Action {
837+ text: "action 1"
838+ iconName: "outgoing-call"
839+ },
840+ Action {
841+ text: "action 2"
842+ iconSource: "call_icon.png"
843+ iconName: "missed-call"
844+ },
845+ Action {
846+ text: "another one"
847+ iconName: "contact"
848+ }
849+ ]
850 }
851
852=== modified file 'tests/unit_x11/tst_components/tst_headActions.qml'
853--- tests/unit_x11/tst_components/tst_headActions.qml 2014-07-28 18:41:55 +0000
854+++ tests/unit_x11/tst_components/tst_headActions.qml 2014-08-26 11:42:43 +0000
855@@ -64,39 +64,52 @@
856 property var app_header
857 property var back_button
858 property var custom_back_button
859+ property var head_animation
860
861 function initTestCase() {
862 testCase.app_header = findChild(mainView, "MainView_Header");
863 testCase.back_button = findChild(app_header, "backButton");
864 testCase.custom_back_button = findChild(app_header, "customBackButton");
865+ testCase.head_animation = findChild(app_header, "PageHeadStyle");
866
867+ waitHeadAnimation();
868 compare(page2.head.backAction, null, "Back action set by default.");
869 compare(back_button.visible, false, "Back button visible with only 1 page on the stack.");
870 compare(custom_back_button.visible, false, "Custom back button visible without custom back action.")
871 }
872
873+ function waitHeadAnimation() {
874+ tryCompareFunction(function(){return testCase.head_animation.animating}, false);
875+ }
876+
877 function test_default_back_button() {
878 pageStack.push(page2);
879+ waitHeadAnimation();
880 compare(back_button.visible, true, "Back button not visible with 2 pages on stack.");
881 compare(custom_back_button.visible, false, "Showing custom back button without custom back action.");
882 pageStack.pop();
883+ waitHeadAnimation();
884 }
885
886 function test_custom_back_button() {
887 page2.head.backAction = customBackAction;
888 pageStack.push(page2);
889+ waitHeadAnimation();
890 compare(back_button.visible, false, "Default back button visible with custom back action.");
891 compare(custom_back_button.visible, true, "Custom back button invisible with back action.");
892 pageStack.pop();
893+ waitHeadAnimation();
894 page2.head.backAction = null;
895 }
896
897 function test_no_back_button() {
898 page2.head.backAction = invisibleAction;
899 pageStack.push(page2);
900+ waitHeadAnimation();
901 compare(back_button.visible, false, "Default back button visible with invisible custom back action.");
902 compare(custom_back_button.visible, false, "Custom back button visible with invisible custom back action.");
903 pageStack.pop();
904+ waitHeadAnimation();
905 page2.head.backAction = null;
906 }
907 }
908
909=== modified file 'tests/unit_x11/tst_components/tst_pagestack_new_header.qml'
910--- tests/unit_x11/tst_components/tst_pagestack_new_header.qml 2014-08-18 10:40:45 +0000
911+++ tests/unit_x11/tst_components/tst_pagestack_new_header.qml 2014-08-26 11:42:43 +0000
912@@ -27,6 +27,7 @@
913
914 MainView {
915 id: mainView
916+ anchors.fill: parent
917 useDeprecatedToolbar: false
918 PageStack {
919 id: pageStack
920@@ -65,7 +66,13 @@
921 when: windowShown
922 id: testCase
923
924+ function waitPageHeadAnimation() {
925+ var pageHeadStyle = findChild(mainView, "PageHeadStyle");
926+ tryCompare(pageHeadStyle, "animating", false);
927+ }
928+
929 function initTestCase() {
930+ waitPageHeadAnimation();
931 compare(pageStack.currentPage, null, "is not set by default");
932 compare(pageStack.__propagated, mainView.__propagated, "propagated property of pageStack equals mainView.__propagated")
933 compare(mainView.__propagated.header.title, "", "empty title by default");
934@@ -74,55 +81,73 @@
935 function test_depth() {
936 compare(pageStack.depth, 0, "depth is 0 by default");
937 pageStack.push(page1);
938+ waitPageHeadAnimation();
939 compare(pageStack.depth, 1, "depth is correctly increased when pushing a page");
940 pageStack.push(page2);
941+ waitPageHeadAnimation();
942 compare(pageStack.depth, 2, "depth is correctly updated when pushing a page");
943 pageStack.pop();
944+ waitPageHeadAnimation();
945 compare(pageStack.depth, 1, "depth is correctly decreased when popping a page");
946 pageStack.clear();
947+ waitPageHeadAnimation();
948 compare(pageStack.depth, 0, "depth is after clearing");
949 }
950
951 function test_currentPage() {
952 compare(pageStack.currentPage, null, "currentPage is null by default");
953 pageStack.push(page1);
954+ waitPageHeadAnimation();
955 compare(pageStack.currentPage, page1, "currentPage properly updated");
956 pageStack.clear();
957+ waitPageHeadAnimation();
958 compare(pageStack.currentPage, null, "currentPage properly reset");
959 }
960
961 function test_active_bug1260116() {
962 pageStack.push(page1);
963+ waitPageHeadAnimation();
964 compare(page1.active, true, "Page is active after pushing");
965 pageStack.push(page2);
966+ waitPageHeadAnimation();
967 compare(page1.active, false, "Page no longer active after pushing a new page");
968 compare(page2.active, true, "New page is active after pushing");
969 pageStack.pop();
970+ waitPageHeadAnimation();
971 compare(page1.active, true, "Page re-activated when on top of the stack");
972 compare(page2.active, false, "Page no longer active after being popped");
973 pageStack.clear();
974+ waitPageHeadAnimation();
975
976 compare(pageInStack.active, false, "Page defined inside PageStack is not active by default");
977 pageStack.push(pageInStack);
978+ waitPageHeadAnimation();
979 compare(pageInStack.active, true, "Pushing a page on PageStack makes it active");
980 pageStack.pop();
981+ waitPageHeadAnimation();
982 compare(pageInStack.active, false, "Popping a page from PageStack makes it inactive");
983 pageStack.clear();
984+ waitPageHeadAnimation();
985 }
986
987 function test_title_bug1143345_bug1317902() {
988 pageStack.push(page1);
989+ waitPageHeadAnimation();
990 compare(mainView.__propagated.header.title, "Title 1", "Header title is correctly set by page");
991 page1.title = "New title";
992 compare(mainView.__propagated.header.title, "New title", "Header title correctly updated by page");
993 pageStack.push(page2);
994+ waitPageHeadAnimation();
995 compare(mainView.__propagated.header.title, "Title 2", "Header title is correctly set by page");
996 pageStack.clear();
997+ waitPageHeadAnimation();
998 page1.title = "Title 1";
999
1000 pageStack.push(pageWithPage);
1001+ waitPageHeadAnimation();
1002 compare(mainView.__propagated.header.title, pageWithPage.title, "Embedded page sets title of outer page");
1003 pageStack.clear();
1004+ waitPageHeadAnimation();
1005 }
1006
1007 function get_tabs_button() {
1008@@ -134,28 +159,36 @@
1009 function test_tabs_inside_stack_bug1187850() {
1010 compare(get_tabs_button(), null, "Without tabs there is no visible tabs button.");
1011 pageStack.push(tabs);
1012+ waitPageHeadAnimation();
1013 compare(pageStack.currentPage, tabs, "Tabs can be pushed on a PageStack");
1014 compare(tabs.active, true, "Tabs on top of a PageStack are active");
1015 compare(get_tabs_button().visible, true, "Pushing tabs on pagestack enables the tabs button");
1016 pageStack.push(page1);
1017+ waitPageHeadAnimation();
1018 compare(pageStack.currentPage, page1, "A page can be pushed on top of a Tabs");
1019 compare(tabs.active, false, "Tabs on a PageStack, but not on top, are inactive");
1020 compare(get_tabs_button(), null, "Contents of inactive Tabs is not applied to header");
1021 pageStack.pop();
1022+ waitPageHeadAnimation();
1023 compare(tabs.active, true, "Tabs on top of PageStack is active");
1024 compare(get_tabs_button().visible, true, "Active Tabs controls header contents");
1025 pageStack.clear();
1026+ waitPageHeadAnimation();
1027 }
1028
1029 function test_pop_to_tabs_bug1316736() {
1030 pageStack.push(tabs);
1031+ waitPageHeadAnimation();
1032 tabs.selectedTabIndex = 1;
1033 pageStack.push(page1);
1034+ waitPageHeadAnimation();
1035 compare(tabs.active, false, "Tabs on a PageStack, but not on top, are inactive");
1036 pageStack.pop();
1037+ waitPageHeadAnimation();
1038 compare(tabs.active, true, "Tabs on top of PageStack is active");
1039 compare(tabs.selectedTabIndex, 1, "Pushing and popping another page on top of Tabs does not change selectedTabsIndex");
1040 pageStack.clear();
1041+ waitPageHeadAnimation();
1042 }
1043 }
1044 }

Subscribers

People subscribed via source and target branches