Merge lp:~tpeeters/ubuntu-ui-toolkit/40-PageWithHeader into lp:ubuntu-ui-toolkit/staging

Proposed by Tim Peeters
Status: Merged
Approved by: Cris Dywan
Approved revision: 1695
Merged at revision: 1686
Proposed branch: lp:~tpeeters/ubuntu-ui-toolkit/40-PageWithHeader
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 411 lines (+279/-12)
8 files modified
components.api (+1/-0)
src/Ubuntu/Components/1.3/AdaptivePageLayout.qml (+7/-3)
src/Ubuntu/Components/1.3/MainView.qml (+9/-1)
src/Ubuntu/Components/1.3/Page.qml (+40/-0)
src/Ubuntu/Components/1.3/PageTreeNode.qml (+0/-7)
src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml (+1/-1)
tests/unit_x11/tst_components/tst_multicolumnheader.qml (+69/-0)
tests/unit_x11/tst_components/tst_page_with_header.qml (+152/-0)
To merge this branch: bzr merge lp:~tpeeters/ubuntu-ui-toolkit/40-PageWithHeader
Reviewer Review Type Date Requested Status
Cris Dywan Approve
PS Jenkins bot continuous-integration Approve
Review via email: mp+274427@code.launchpad.net

Commit message

Add header property to Page.

Description of the change

Add header property to Page. Setting the header property will disable the MainView's application header, and the column header in the AdaptivePageLayout.

Follow-up MRs will have to add an automatic back-button to the PageHeader, as well as sync the PageHeader heights when used in Pages in the AdaptivePageLayout. Also, when these features are done I will update the Page documentation examples to use the new header, and deprecated the old properties.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Cris Dywan (kalikiana) wrote :

Looks sensible and works very nicely. Keep those iterations coming!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Cris Dywan (kalikiana) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'components.api'
--- components.api 2015-10-12 14:45:11 +0000
+++ components.api 2015-10-15 10:08:16 +0000
@@ -671,6 +671,7 @@
671Ubuntu.Components.Page 1.3: PageTreeNode671Ubuntu.Components.Page 1.3: PageTreeNode
672 property Flickable flickable672 property Flickable flickable
673 readonly property PageHeadConfiguration head673 readonly property PageHeadConfiguration head
674 property Item header
674 property string title675 property string title
675Ubuntu.Components.PageColumn 1.3: QtObject676Ubuntu.Components.PageColumn 1.3: QtObject
676 property bool fillWidth677 property bool fillWidth
677678
=== modified file 'src/Ubuntu/Components/1.3/AdaptivePageLayout.qml'
--- src/Ubuntu/Components/1.3/AdaptivePageLayout.qml 2015-10-02 05:18:15 +0000
+++ src/Ubuntu/Components/1.3/AdaptivePageLayout.qml 2015-10-15 10:08:16 +0000
@@ -667,13 +667,17 @@
667 Layout.minimumWidth: metrics.minimumWidth667 Layout.minimumWidth: metrics.minimumWidth
668 Layout.maximumWidth: metrics.maximumWidth668 Layout.maximumWidth: metrics.maximumWidth
669669
670 property var page: pageWrapper ? pageWrapper.object : null
671 property bool customHeader: page && page.hasOwnProperty("header") &&
672 page.header
673
670 // prevent the pages from taking the app header height into account.674 // prevent the pages from taking the app header height into account.
671 __propagated: null675 __propagated: null
672 Item {676 Item {
673 id: holderBody677 id: holderBody
674 objectName: parent.objectName + "Body"678 objectName: parent.objectName + "Body"
675 anchors {679 anchors {
676 top: subHeader.bottom680 top: customHeader ? parent.top : subHeader.bottom
677 bottom: parent.bottom681 bottom: parent.bottom
678 left: parent.left682 left: parent.left
679 right: parent.right683 right: parent.right
@@ -715,12 +719,12 @@
715 property color dividerColor: layout.__propagated.header.dividerColor719 property color dividerColor: layout.__propagated.header.dividerColor
716 property color panelColor: layout.__propagated.header.panelColor720 property color panelColor: layout.__propagated.header.panelColor
717721
718 visible: holder.pageWrapper && holder.pageWrapper.active722 visible: !customHeader && holder.pageWrapper && holder.pageWrapper.active
719723
720 // The multiColumn, page and showBackButton properties are used in724 // The multiColumn, page and showBackButton properties are used in
721 // PageHeadStyle to show/hide the back button.725 // PageHeadStyle to show/hide the back button.
722 property var multiColumn: layout726 property var multiColumn: layout
723 property var page: holder.pageWrapper ? holder.pageWrapper.object : null727 property alias page: holder.page // used in PageHeadStyle for the back button.
724 property bool showBackButton: {728 property bool showBackButton: {
725 if (!page) {729 if (!page) {
726 return false;730 return false;
727731
=== modified file 'src/Ubuntu/Components/1.3/MainView.qml'
--- src/Ubuntu/Components/1.3/MainView.qml 2015-10-01 15:50:07 +0000
+++ src/Ubuntu/Components/1.3/MainView.qml 2015-10-15 10:08:16 +0000
@@ -172,9 +172,17 @@
172 // Used when there is no active Page, or a Page 1.0 is used which172 // Used when there is no active Page, or a Page 1.0 is used which
173 // does not have a PageHeadConfiguration.173 // does not have a PageHeadConfiguration.
174 }174 }
175 config: internal.activePage && internal.activePage.hasOwnProperty("head") ?175 config: visible && internal.activePage &&
176 internal.activePage.hasOwnProperty("head") ?
176 internal.activePage.head : defaultConfig177 internal.activePage.head : defaultConfig
177178
179 // don't show the application header if the page has its own header.
180 visible: !(internal.activePage &&
181 internal.activePage.hasOwnProperty("header") &&
182 internal.activePage.header)
183
184 height: visible ? implicitHeight : 0
185
178 // 'window' is defined by QML between startup and showing on the screen.186 // 'window' is defined by QML between startup and showing on the screen.
179 // There is no signal for when it becomes available and re-declaring it is not safe.187 // There is no signal for when it becomes available and re-declaring it is not safe.
180 property bool windowActive: typeof window != 'undefined'188 property bool windowActive: typeof window != 'undefined'
181189
=== modified file 'src/Ubuntu/Components/1.3/Page.qml'
--- src/Ubuntu/Components/1.3/Page.qml 2015-10-01 12:54:32 +0000
+++ src/Ubuntu/Components/1.3/Page.qml 2015-10-15 10:08:16 +0000
@@ -33,6 +33,27 @@
33 width: parentNode ? parentNode.width - page.x : undefined33 width: parentNode ? parentNode.width - page.x : undefined
34 height: parentNode ? page.flickable ? parentNode.height : parentNode.height - internal.headerHeight : undefined34 height: parentNode ? page.flickable ? parentNode.height : parentNode.height - internal.headerHeight : undefined
3535
36 /*!
37 The header property for this page. Setting this property will reparent the
38 header to the page and disable the \l Mainview's application header.
39 \qml
40 Page {
41 id: page
42 title: "Page with header"
43 header: PageHeader {
44 title: page.header
45 trailingActionBar.actions: [
46 Action { iconName: "settings" },
47 Action { iconName: "info" }
48 ]
49 }
50 }
51 \endqml
52 */
53 property Item header
54 onHeaderChanged: internal.updateHeader()
55 Component.onCompleted: internal.updateHeader()
56
36 isLeaf: true57 isLeaf: true
37 property string title: parentNode && parentNode.hasOwnProperty("title") ? parentNode.title : ""58 property string title: parentNode && parentNode.hasOwnProperty("title") ? parentNode.title : ""
38 property Flickable flickable: Utils.getFlickableChild(page)59 property Flickable flickable: Utils.getFlickableChild(page)
@@ -50,6 +71,25 @@
50 Toolkit13.Object {71 Toolkit13.Object {
51 id: internal72 id: internal
5273
74 property Item previousHeader: null
75 property Item previousHeaderParent: null
76 function updateHeader() {
77 if (internal.previousHeader) {
78 internal.previousHeader.parent = internal.previousHeaderParent;
79 }
80 if (page.header) {
81 internal.previousHeaderParent = page.header.parent;
82 internal.previousHeader = page.header;
83 page.header.parent = page;
84 } else {
85 internal.previousHeader = null;
86 internal.previousHeaderParent = null;
87 }
88 }
89
90 ///////////////////////////////
91 // old header handling below //
92 ///////////////////////////////
53 property AppHeader header: page.__propagated && page.__propagated.header ? page.__propagated.header : null93 property AppHeader header: page.__propagated && page.__propagated.header ? page.__propagated.header : null
54 // Used to position the Page when there is no flickable.94 // Used to position the Page when there is no flickable.
55 // When there is a flickable, the header will automatically position it.95 // When there is a flickable, the header will automatically position it.
5696
=== modified file 'src/Ubuntu/Components/1.3/PageTreeNode.qml'
--- src/Ubuntu/Components/1.3/PageTreeNode.qml 2015-05-06 10:32:20 +0000
+++ src/Ubuntu/Components/1.3/PageTreeNode.qml 2015-10-15 10:08:16 +0000
@@ -43,13 +43,6 @@
4343
44 /*!44 /*!
45 \deprecated45 \deprecated
46 The header of the node. Propagates down from the root node.
47 This property is DEPRECATED.
48 */
49 property Item header: node.__propagated ? node.__propagated.header : null
50
51 /*!
52 \deprecated
53 The toolbar of the node. Propagates down from the root node.46 The toolbar of the node. Propagates down from the root node.
54 This property is DEPRECATED.47 This property is DEPRECATED.
55 */48 */
5649
=== modified file 'src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml'
--- src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml 2015-10-13 09:58:12 +0000
+++ src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml 2015-10-15 10:08:16 +0000
@@ -53,7 +53,7 @@
53 right: parent.right53 right: parent.right
54 verticalCenter: parent.verticalCenter54 verticalCenter: parent.verticalCenter
55 }55 }
56 color: header.__styleInstance.foregroundColor56 color: pageHeaderStyle.foregroundColor
57 font.weight: pageHeaderStyle.fontWeight57 font.weight: pageHeaderStyle.fontWeight
58 textSize: pageHeaderStyle.textSize58 textSize: pageHeaderStyle.textSize
59 elide: Text.ElideRight59 elide: Text.ElideRight
6060
=== modified file 'tests/unit_x11/tst_components/tst_multicolumnheader.qml'
--- tests/unit_x11/tst_components/tst_multicolumnheader.qml 2015-09-01 12:00:17 +0000
+++ tests/unit_x11/tst_components/tst_multicolumnheader.qml 2015-10-15 10:08:16 +0000
@@ -69,6 +69,14 @@
69 text: "Add page with head contents right"69 text: "Add page with head contents right"
70 onClicked: layout.addPageToNextColumn(rootPage, headContentsPage)70 onClicked: layout.addPageToNextColumn(rootPage, headContentsPage)
71 }71 }
72 ListItemWithLabel {
73 text: "Add page with header left"
74 onClicked: layout.addPageToCurrentColumn(rootPage, pageWithHeader)
75 }
76 ListItemWithLabel {
77 text: "Add page with header right"
78 onClicked: layout.addPageToNextColumn(rootPage, pageWithHeader)
79 }
72 }80 }
73 }81 }
74 Page {82 Page {
@@ -124,6 +132,40 @@
124 anchors.fill: parent132 anchors.fill: parent
125 }133 }
126 }134 }
135 Page {
136 id: pageWithHeader
137 header: PageHeader {
138 title: "Page with header"
139 // FIXME (timp): Automatic back buttons for the PageHeader
140 // will be added in a later MR.
141 leadingActionBar.actions: Action {
142 text: "Back"
143 iconName: "close"
144 onTriggered: layout.removePages(pageWithHeader)
145 }
146 // Distinguish this header clearly from the AppHeader
147 // visually for manual tests.
148 StyleHints {
149 backgroundColor: UbuntuColors.blue
150 foregroundColor: "white"
151 }
152 }
153 Rectangle {
154 anchors {
155 top: pageWithHeader.header.bottom
156 left: parent.left
157 right: parent.right
158 bottom: parent.bottom
159 margins: units.gu(2)
160 }
161 color: UbuntuColors.warmGrey
162 Button {
163 anchors.centerIn: parent
164 text: "Add sections to next column."
165 onTriggered: layout.addPageToNextColumn(pageWithHeader, sectionsPage)
166 }
167 }
168 }
127 }169 }
128170
129 UbuntuTestCase {171 UbuntuTestCase {
@@ -376,5 +418,32 @@
376 compare(headRectangle.parent == null, false, "Head contents has no parent in next column.");418 compare(headRectangle.parent == null, false, "Head contents has no parent in next column.");
377 layout.removePages(headContentsPage);419 layout.removePages(headContentsPage);
378 }420 }
421
422 function test_page_header_disables_apl_subheader() {
423 layout.addPageToCurrentColumn(rootPage, pageWithHeader);
424 var subHeader = get_header(0);
425 compare(subHeader.visible, false,
426 "Adding a Page with header does not hide the column's subHeader.");
427
428 layout.addPageToCurrentColumn(pageWithHeader, sectionsPage);
429 subHeader = get_header(0);
430 compare(subHeader.visible, true,
431 "Adding a Page without header does not reveal the column's subHeader.");
432
433 layout.removePages(sectionsPage);
434 subHeader = get_header(0);
435 compare(subHeader.visible, false,
436 "Going back to Page with header does not hide the column's subHeader.");
437
438 if (root.columns > 1) {
439 layout.addPageToNextColumn(pageWithHeader, sectionsPage);
440 subHeader = get_header(0);
441 compare(subHeader.visible, false,
442 "Adding Page without header to next column shows subHeader in first column.");
443 subHeader = get_header(1);
444 compare(subHeader.visible, true,
445 "Adding Page without header to next column does not show subHeader in next column");
446 }
447 }
379 }448 }
380}449}
381450
=== added file 'tests/unit_x11/tst_components/tst_page_with_header.qml'
--- tests/unit_x11/tst_components/tst_page_with_header.qml 1970-01-01 00:00:00 +0000
+++ tests/unit_x11/tst_components/tst_page_with_header.qml 2015-10-15 10:08:16 +0000
@@ -0,0 +1,152 @@
1/*
2 * Copyright (C) 2015 Canonical Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.4
18import Ubuntu.Components 1.3
19import Ubuntu.Test 1.0
20
21MainView {
22 width: units.gu(50)
23 height: units.gu(70)
24 id: root
25
26 Item {
27 id: invisible
28 visible: false
29
30 Rectangle {
31 objectName: "my_rectangle"
32 id: myRectangle
33 anchors {
34 left: parent.left
35 right: parent.right
36 }
37 height: units.gu(6)
38 color: UbuntuColors.red
39 }
40
41 PageHeader {
42 id: myPageHeader
43 objectName: "my_page_header"
44 title: "Page header"
45 trailingActionBar.actions: [
46 Action {
47 iconName: "settings"
48 text: "First"
49 },
50 Action {
51 iconName: "info"
52 text: "Second"
53 }
54 ]
55 }
56 }
57
58 Page {
59 id: page
60 title: "Page with header"
61 header: myPageHeader
62
63 Column {
64 anchors {
65 left: parent.left
66 right: parent.right
67 top: parent.top
68 topMargin: units.gu(10)
69 leftMargin: units.gu(10)
70 rightMargin: units.gu(10)
71 }
72 height: childrenRect.height
73
74 Button {
75 anchors {
76 left: parent.left
77 right: parent.right
78 }
79 text: "Page header"
80 onClicked: page.header = myPageHeader
81 }
82 Button {
83 anchors {
84 left: parent.left
85 right: parent.right
86 }
87 text: "Rectangle"
88 onClicked: page.header = myRectangle
89 }
90 Button {
91 anchors {
92 left: parent.left
93 right: parent.right
94 }
95 text: "Null"
96 onClicked: page.header = null
97 }
98 }
99 }
100
101 UbuntuTestCase {
102 name: "PageWithHeader"
103 when: windowShown
104 id: testCase
105
106 property var appHeader;
107 function initTestCase() {
108 var pageHeader = findChild(page, "my_page_header");
109 compare(pageHeader, myPageHeader,
110 "My PageHeader not initialized with Page as its parent.");
111 appHeader = findChild(root, "MainView_Header");
112 compare(appHeader.visible, false,
113 "AppHeader is not hidden initially when Page.header is set.");
114 }
115
116 function cleanup() {
117 page.header = myPageHeader;
118 var pageHeader = findChild(page, "my_page_header");
119 compare(pageHeader, myPageHeader,
120 "PageHeader is not correctly re-parented to the Page when setting Page.header.");
121 compare(myPageHeader.visible, true,
122 "PageHeader is not visible after being re-parented to the Page.");
123 compare(appHeader.visible, false,
124 "AppHeader is not hidden when Page.header is set.");
125 }
126
127 function test_page_with_no_header() {
128 page.header = null;
129 compare(myPageHeader.parent, invisible,
130 "Header parent is not correctly reverted when unsetting Page.header.");
131 compare(myPageHeader.visible, false,
132 "My PageHeader is still visible after re-parenting it to an invisible Item.");
133 compare(appHeader.visible, true,
134 "AppHeader does not become visible when Page.header is null.");
135 }
136
137 function test_page_with_alternative_header() {
138 page.header = myRectangle;
139 compare(myPageHeader.parent, invisible,
140 "Header parent not correctly reverted when setting a different Page.header.");
141 compare(myRectangle.parent, page,
142 "Rectangle parent is not correctly set to page after setting it as Page.header.");
143 compare(appHeader.visible, false,
144 "Setting a different Page.header Item shows the AppHeader.");
145
146 page.header = myPageHeader;
147 compare(myRectangle.parent, invisible,
148 "Rectangle parent is not correctly reverted after unsetting it as Page.header.");
149 // myPageHeader parent is checked in cleanup().
150 }
151 }
152}

Subscribers

People subscribed via source and target branches