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
1=== modified file 'components.api'
2--- components.api 2015-10-12 14:45:11 +0000
3+++ components.api 2015-10-15 10:08:16 +0000
4@@ -671,6 +671,7 @@
5 Ubuntu.Components.Page 1.3: PageTreeNode
6 property Flickable flickable
7 readonly property PageHeadConfiguration head
8+ property Item header
9 property string title
10 Ubuntu.Components.PageColumn 1.3: QtObject
11 property bool fillWidth
12
13=== modified file 'src/Ubuntu/Components/1.3/AdaptivePageLayout.qml'
14--- src/Ubuntu/Components/1.3/AdaptivePageLayout.qml 2015-10-02 05:18:15 +0000
15+++ src/Ubuntu/Components/1.3/AdaptivePageLayout.qml 2015-10-15 10:08:16 +0000
16@@ -667,13 +667,17 @@
17 Layout.minimumWidth: metrics.minimumWidth
18 Layout.maximumWidth: metrics.maximumWidth
19
20+ property var page: pageWrapper ? pageWrapper.object : null
21+ property bool customHeader: page && page.hasOwnProperty("header") &&
22+ page.header
23+
24 // prevent the pages from taking the app header height into account.
25 __propagated: null
26 Item {
27 id: holderBody
28 objectName: parent.objectName + "Body"
29 anchors {
30- top: subHeader.bottom
31+ top: customHeader ? parent.top : subHeader.bottom
32 bottom: parent.bottom
33 left: parent.left
34 right: parent.right
35@@ -715,12 +719,12 @@
36 property color dividerColor: layout.__propagated.header.dividerColor
37 property color panelColor: layout.__propagated.header.panelColor
38
39- visible: holder.pageWrapper && holder.pageWrapper.active
40+ visible: !customHeader && holder.pageWrapper && holder.pageWrapper.active
41
42 // The multiColumn, page and showBackButton properties are used in
43 // PageHeadStyle to show/hide the back button.
44 property var multiColumn: layout
45- property var page: holder.pageWrapper ? holder.pageWrapper.object : null
46+ property alias page: holder.page // used in PageHeadStyle for the back button.
47 property bool showBackButton: {
48 if (!page) {
49 return false;
50
51=== modified file 'src/Ubuntu/Components/1.3/MainView.qml'
52--- src/Ubuntu/Components/1.3/MainView.qml 2015-10-01 15:50:07 +0000
53+++ src/Ubuntu/Components/1.3/MainView.qml 2015-10-15 10:08:16 +0000
54@@ -172,9 +172,17 @@
55 // Used when there is no active Page, or a Page 1.0 is used which
56 // does not have a PageHeadConfiguration.
57 }
58- config: internal.activePage && internal.activePage.hasOwnProperty("head") ?
59+ config: visible && internal.activePage &&
60+ internal.activePage.hasOwnProperty("head") ?
61 internal.activePage.head : defaultConfig
62
63+ // don't show the application header if the page has its own header.
64+ visible: !(internal.activePage &&
65+ internal.activePage.hasOwnProperty("header") &&
66+ internal.activePage.header)
67+
68+ height: visible ? implicitHeight : 0
69+
70 // 'window' is defined by QML between startup and showing on the screen.
71 // There is no signal for when it becomes available and re-declaring it is not safe.
72 property bool windowActive: typeof window != 'undefined'
73
74=== modified file 'src/Ubuntu/Components/1.3/Page.qml'
75--- src/Ubuntu/Components/1.3/Page.qml 2015-10-01 12:54:32 +0000
76+++ src/Ubuntu/Components/1.3/Page.qml 2015-10-15 10:08:16 +0000
77@@ -33,6 +33,27 @@
78 width: parentNode ? parentNode.width - page.x : undefined
79 height: parentNode ? page.flickable ? parentNode.height : parentNode.height - internal.headerHeight : undefined
80
81+ /*!
82+ The header property for this page. Setting this property will reparent the
83+ header to the page and disable the \l Mainview's application header.
84+ \qml
85+ Page {
86+ id: page
87+ title: "Page with header"
88+ header: PageHeader {
89+ title: page.header
90+ trailingActionBar.actions: [
91+ Action { iconName: "settings" },
92+ Action { iconName: "info" }
93+ ]
94+ }
95+ }
96+ \endqml
97+ */
98+ property Item header
99+ onHeaderChanged: internal.updateHeader()
100+ Component.onCompleted: internal.updateHeader()
101+
102 isLeaf: true
103 property string title: parentNode && parentNode.hasOwnProperty("title") ? parentNode.title : ""
104 property Flickable flickable: Utils.getFlickableChild(page)
105@@ -50,6 +71,25 @@
106 Toolkit13.Object {
107 id: internal
108
109+ property Item previousHeader: null
110+ property Item previousHeaderParent: null
111+ function updateHeader() {
112+ if (internal.previousHeader) {
113+ internal.previousHeader.parent = internal.previousHeaderParent;
114+ }
115+ if (page.header) {
116+ internal.previousHeaderParent = page.header.parent;
117+ internal.previousHeader = page.header;
118+ page.header.parent = page;
119+ } else {
120+ internal.previousHeader = null;
121+ internal.previousHeaderParent = null;
122+ }
123+ }
124+
125+ ///////////////////////////////
126+ // old header handling below //
127+ ///////////////////////////////
128 property AppHeader header: page.__propagated && page.__propagated.header ? page.__propagated.header : null
129 // Used to position the Page when there is no flickable.
130 // When there is a flickable, the header will automatically position it.
131
132=== modified file 'src/Ubuntu/Components/1.3/PageTreeNode.qml'
133--- src/Ubuntu/Components/1.3/PageTreeNode.qml 2015-05-06 10:32:20 +0000
134+++ src/Ubuntu/Components/1.3/PageTreeNode.qml 2015-10-15 10:08:16 +0000
135@@ -43,13 +43,6 @@
136
137 /*!
138 \deprecated
139- The header of the node. Propagates down from the root node.
140- This property is DEPRECATED.
141- */
142- property Item header: node.__propagated ? node.__propagated.header : null
143-
144- /*!
145- \deprecated
146 The toolbar of the node. Propagates down from the root node.
147 This property is DEPRECATED.
148 */
149
150=== modified file 'src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml'
151--- src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml 2015-10-13 09:58:12 +0000
152+++ src/Ubuntu/Components/Themes/Ambiance/1.3/PageHeaderStyle.qml 2015-10-15 10:08:16 +0000
153@@ -53,7 +53,7 @@
154 right: parent.right
155 verticalCenter: parent.verticalCenter
156 }
157- color: header.__styleInstance.foregroundColor
158+ color: pageHeaderStyle.foregroundColor
159 font.weight: pageHeaderStyle.fontWeight
160 textSize: pageHeaderStyle.textSize
161 elide: Text.ElideRight
162
163=== modified file 'tests/unit_x11/tst_components/tst_multicolumnheader.qml'
164--- tests/unit_x11/tst_components/tst_multicolumnheader.qml 2015-09-01 12:00:17 +0000
165+++ tests/unit_x11/tst_components/tst_multicolumnheader.qml 2015-10-15 10:08:16 +0000
166@@ -69,6 +69,14 @@
167 text: "Add page with head contents right"
168 onClicked: layout.addPageToNextColumn(rootPage, headContentsPage)
169 }
170+ ListItemWithLabel {
171+ text: "Add page with header left"
172+ onClicked: layout.addPageToCurrentColumn(rootPage, pageWithHeader)
173+ }
174+ ListItemWithLabel {
175+ text: "Add page with header right"
176+ onClicked: layout.addPageToNextColumn(rootPage, pageWithHeader)
177+ }
178 }
179 }
180 Page {
181@@ -124,6 +132,40 @@
182 anchors.fill: parent
183 }
184 }
185+ Page {
186+ id: pageWithHeader
187+ header: PageHeader {
188+ title: "Page with header"
189+ // FIXME (timp): Automatic back buttons for the PageHeader
190+ // will be added in a later MR.
191+ leadingActionBar.actions: Action {
192+ text: "Back"
193+ iconName: "close"
194+ onTriggered: layout.removePages(pageWithHeader)
195+ }
196+ // Distinguish this header clearly from the AppHeader
197+ // visually for manual tests.
198+ StyleHints {
199+ backgroundColor: UbuntuColors.blue
200+ foregroundColor: "white"
201+ }
202+ }
203+ Rectangle {
204+ anchors {
205+ top: pageWithHeader.header.bottom
206+ left: parent.left
207+ right: parent.right
208+ bottom: parent.bottom
209+ margins: units.gu(2)
210+ }
211+ color: UbuntuColors.warmGrey
212+ Button {
213+ anchors.centerIn: parent
214+ text: "Add sections to next column."
215+ onTriggered: layout.addPageToNextColumn(pageWithHeader, sectionsPage)
216+ }
217+ }
218+ }
219 }
220
221 UbuntuTestCase {
222@@ -376,5 +418,32 @@
223 compare(headRectangle.parent == null, false, "Head contents has no parent in next column.");
224 layout.removePages(headContentsPage);
225 }
226+
227+ function test_page_header_disables_apl_subheader() {
228+ layout.addPageToCurrentColumn(rootPage, pageWithHeader);
229+ var subHeader = get_header(0);
230+ compare(subHeader.visible, false,
231+ "Adding a Page with header does not hide the column's subHeader.");
232+
233+ layout.addPageToCurrentColumn(pageWithHeader, sectionsPage);
234+ subHeader = get_header(0);
235+ compare(subHeader.visible, true,
236+ "Adding a Page without header does not reveal the column's subHeader.");
237+
238+ layout.removePages(sectionsPage);
239+ subHeader = get_header(0);
240+ compare(subHeader.visible, false,
241+ "Going back to Page with header does not hide the column's subHeader.");
242+
243+ if (root.columns > 1) {
244+ layout.addPageToNextColumn(pageWithHeader, sectionsPage);
245+ subHeader = get_header(0);
246+ compare(subHeader.visible, false,
247+ "Adding Page without header to next column shows subHeader in first column.");
248+ subHeader = get_header(1);
249+ compare(subHeader.visible, true,
250+ "Adding Page without header to next column does not show subHeader in next column");
251+ }
252+ }
253 }
254 }
255
256=== added file 'tests/unit_x11/tst_components/tst_page_with_header.qml'
257--- tests/unit_x11/tst_components/tst_page_with_header.qml 1970-01-01 00:00:00 +0000
258+++ tests/unit_x11/tst_components/tst_page_with_header.qml 2015-10-15 10:08:16 +0000
259@@ -0,0 +1,152 @@
260+/*
261+ * Copyright (C) 2015 Canonical Ltd.
262+ *
263+ * This program is free software; you can redistribute it and/or modify
264+ * it under the terms of the GNU Lesser General Public License as published by
265+ * the Free Software Foundation; version 3.
266+ *
267+ * This program is distributed in the hope that it will be useful,
268+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
269+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
270+ * GNU Lesser General Public License for more details.
271+ *
272+ * You should have received a copy of the GNU Lesser General Public License
273+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
274+ */
275+
276+import QtQuick 2.4
277+import Ubuntu.Components 1.3
278+import Ubuntu.Test 1.0
279+
280+MainView {
281+ width: units.gu(50)
282+ height: units.gu(70)
283+ id: root
284+
285+ Item {
286+ id: invisible
287+ visible: false
288+
289+ Rectangle {
290+ objectName: "my_rectangle"
291+ id: myRectangle
292+ anchors {
293+ left: parent.left
294+ right: parent.right
295+ }
296+ height: units.gu(6)
297+ color: UbuntuColors.red
298+ }
299+
300+ PageHeader {
301+ id: myPageHeader
302+ objectName: "my_page_header"
303+ title: "Page header"
304+ trailingActionBar.actions: [
305+ Action {
306+ iconName: "settings"
307+ text: "First"
308+ },
309+ Action {
310+ iconName: "info"
311+ text: "Second"
312+ }
313+ ]
314+ }
315+ }
316+
317+ Page {
318+ id: page
319+ title: "Page with header"
320+ header: myPageHeader
321+
322+ Column {
323+ anchors {
324+ left: parent.left
325+ right: parent.right
326+ top: parent.top
327+ topMargin: units.gu(10)
328+ leftMargin: units.gu(10)
329+ rightMargin: units.gu(10)
330+ }
331+ height: childrenRect.height
332+
333+ Button {
334+ anchors {
335+ left: parent.left
336+ right: parent.right
337+ }
338+ text: "Page header"
339+ onClicked: page.header = myPageHeader
340+ }
341+ Button {
342+ anchors {
343+ left: parent.left
344+ right: parent.right
345+ }
346+ text: "Rectangle"
347+ onClicked: page.header = myRectangle
348+ }
349+ Button {
350+ anchors {
351+ left: parent.left
352+ right: parent.right
353+ }
354+ text: "Null"
355+ onClicked: page.header = null
356+ }
357+ }
358+ }
359+
360+ UbuntuTestCase {
361+ name: "PageWithHeader"
362+ when: windowShown
363+ id: testCase
364+
365+ property var appHeader;
366+ function initTestCase() {
367+ var pageHeader = findChild(page, "my_page_header");
368+ compare(pageHeader, myPageHeader,
369+ "My PageHeader not initialized with Page as its parent.");
370+ appHeader = findChild(root, "MainView_Header");
371+ compare(appHeader.visible, false,
372+ "AppHeader is not hidden initially when Page.header is set.");
373+ }
374+
375+ function cleanup() {
376+ page.header = myPageHeader;
377+ var pageHeader = findChild(page, "my_page_header");
378+ compare(pageHeader, myPageHeader,
379+ "PageHeader is not correctly re-parented to the Page when setting Page.header.");
380+ compare(myPageHeader.visible, true,
381+ "PageHeader is not visible after being re-parented to the Page.");
382+ compare(appHeader.visible, false,
383+ "AppHeader is not hidden when Page.header is set.");
384+ }
385+
386+ function test_page_with_no_header() {
387+ page.header = null;
388+ compare(myPageHeader.parent, invisible,
389+ "Header parent is not correctly reverted when unsetting Page.header.");
390+ compare(myPageHeader.visible, false,
391+ "My PageHeader is still visible after re-parenting it to an invisible Item.");
392+ compare(appHeader.visible, true,
393+ "AppHeader does not become visible when Page.header is null.");
394+ }
395+
396+ function test_page_with_alternative_header() {
397+ page.header = myRectangle;
398+ compare(myPageHeader.parent, invisible,
399+ "Header parent not correctly reverted when setting a different Page.header.");
400+ compare(myRectangle.parent, page,
401+ "Rectangle parent is not correctly set to page after setting it as Page.header.");
402+ compare(appHeader.visible, false,
403+ "Setting a different Page.header Item shows the AppHeader.");
404+
405+ page.header = myPageHeader;
406+ compare(myRectangle.parent, invisible,
407+ "Rectangle parent is not correctly reverted after unsetting it as Page.header.");
408+ // myPageHeader parent is checked in cleanup().
409+ }
410+ }
411+}

Subscribers

People subscribed via source and target branches