Merge lp:~mrqtros/component-store/bottom-edge-tabs into lp:component-store

Proposed by Roman Shchekin
Status: Merged
Approved by: Nekhelesh Ramananthan
Approved revision: 52
Merged at revision: 50
Proposed branch: lp:~mrqtros/component-store/bottom-edge-tabs
Merge into: lp:component-store
Diff against target: 738 lines (+680/-0)
8 files modified
curated-store/ComponentStore/BottomEdgeTabs/BottomEdgeTabs.qml (+427/-0)
curated-store/ComponentStore/BottomEdgeTabs/FakeHeader.qml (+39/-0)
curated-store/ComponentStore/BottomEdgeTabs/ubuntu_component_store.json (+6/-0)
curated-store/GallerySRC/BottomEdgeTabsWidget.qml (+69/-0)
curated-store/GallerySRC/WidgetsModel.qml (+5/-0)
docs/_components/bottomedgetabs.rst (+129/-0)
docs/index.rst (+1/-0)
docs/release.rst (+4/-0)
To merge this branch: bzr merge lp:~mrqtros/component-store/bottom-edge-tabs
Reviewer Review Type Date Requested Status
Nekhelesh Ramananthan Approve
Review via email: mp+256041@code.launchpad.net

Commit message

New component - BottomEdgeTabs (something like PageWithBottomEdge, but for Tabs).

Description of the change

New component - BottomEdgeTabs (something like PageWithBottomEdge, but for Tabs).

P.S. I think that PageWithBottomEdge also should use my method of displaying live preview (use ShaderEffectSource instead of manual creating and reparenting).

To post a comment you must log in.
Revision history for this message
Roman Shchekin (mrqtros) wrote :

Btw, you maybe will see warning message about message loop - it's result of hosting one PageStack in another, in real use case there are no any warnings.
And feel free to change docs & other staff - my English is not good.

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

The only warning I see is,

QML UbuntuShape: Binding Loop Detected for property "hidden".. I guess that's fine.

1. Merge https://code.launchpad.net/~nik90/component-store/fix-bottomedgetabs-docs/+merge/256047
2. This is your component, so please maintain it as and when required :-)

Nice Work!

52. By Roman Shchekin

Merged with correct docs (thanks Nekhelesh).

Revision history for this message
Roman Shchekin (mrqtros) wrote :

1. Merged with your branch!
2. Yes I will :)

BTW, binding loop can be caused by this bug https://bugreports.qt.io/browse/QTBUG-39921 (reported by me some time ago).

Revision history for this message
Nekhelesh Ramananthan (nik90) wrote :

LGTM

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory 'curated-store/ComponentStore/BottomEdgeTabs'
=== added file 'curated-store/ComponentStore/BottomEdgeTabs/BottomEdgeTabs.qml'
--- curated-store/ComponentStore/BottomEdgeTabs/BottomEdgeTabs.qml 1970-01-01 00:00:00 +0000
+++ curated-store/ComponentStore/BottomEdgeTabs/BottomEdgeTabs.qml 2015-04-14 06:07:01 +0000
@@ -0,0 +1,427 @@
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 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 General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17/*
18 Example:
19
20MainView {
21 objectName: "mainView"
22
23 applicationName: "com.ubuntu.developer.qtros.tabsbottomedge"
24
25 width: units.gu(50)
26 height: units.gu(75)
27 useDeprecatedToolbar: false
28
29 PageStack {
30 id: stack
31 Component.onCompleted: push(tabs)
32 }
33
34 BottomEdgeTabs {
35 id: tabs
36
37 bottomEdgePage: secondPage
38 bottomEdgeTitle: "Violet page"
39
40 Tab {
41 title: "First tab"
42 page: Page {
43 Label {
44 anchors.centerIn: parent
45 text: "Content of first tab"
46 }
47 }
48 }
49
50 Tab {
51 title: "Second tab"
52 page: Page {
53 Label {
54 anchors.centerIn: parent
55 text: "Centered label"
56 }
57 }
58 }
59 } // BottomEdgeTabs
60
61 Page {
62 id: secondPage
63 title: "Violet page"
64 visible: false
65
66 Rectangle {
67 anchors.fill: parent
68 color: "darkviolet"
69 }
70 }
71}
72
73*/
74
75import QtQuick 2.3
76import Ubuntu.Components 1.1
77
78Tabs {
79 id: page
80
81 property Page bottomEdgePage: null
82 property alias bottomEdgeTitle: tipLabel.text
83 property color bottomEdgeBackgroundColor: Theme.palette.normal.background
84 property color bottomEdgeTipColor: Theme.palette.normal.background
85 property bool bottomEdgeEnabled: true
86 property bool bottomEdgeHeaderHidden: true
87 property bool bottomEdgeUseHeaderInCalculations: true
88 property real bottomEdgeExpandThreshold: 0.2
89
90 readonly property bool isReady: bottomEdgePageLoaded && bottomEdgePage.active && bottomEdge.y === __pageStartY
91 readonly property bool isCollapsed: (bottomEdge.y === page.height)
92 readonly property bool bottomEdgePageLoaded: bottomEdgePage != null
93
94 readonly property int __pageStartY: bottomEdgeUseHeaderInCalculations ? fakeHeader.height : 0
95
96 signal bottomEdgeReleased()
97 signal bottomEdgeDismissed()
98
99 function __pushPage() {
100 if (bottomEdgePageLoaded) {
101 bottomEdgePage.active = true
102 if (bottomEdgePage.hasOwnProperty("isDirty")) // TODO
103 bottomEdgePage.isDirty = true
104 page.pageStack.push(bottomEdgePage)
105 if (bottomEdgePage.flickable) {
106 bottomEdgePage.flickable.contentY = -page.header.height
107 bottomEdgePage.flickable.returnToBounds()
108 }
109 if (bottomEdgePage.ready)
110 bottomEdgePage.ready()
111 }
112 }
113
114 onActiveChanged: {
115 if (active) {
116 bottomEdge.state = "collapsed"
117 }
118 }
119
120 onBottomEdgePageChanged: {
121 tip.forceActiveFocus()
122 if (page.isReady && bottomEdgePageLoaded && !bottomEdgePage.active) {
123 page.__pushPage()
124 }
125 }
126
127 Rectangle {
128 id: bgVisual
129
130 color: "black"
131 anchors {
132 fill: parent
133 topMargin: __pageStartY
134 }
135 opacity: 0.7 * ((page.height - bottomEdge.y) / page.height)
136 z: 1
137 }
138
139 UbuntuShape {
140 id: tip
141 objectName: "bottomEdgeTip"
142
143 property bool hidden: !activeFocus || (bottomEdge.y - units.gu(1) < tip.y)
144
145 enabled: bottomEdgePageLoaded
146 visible: bottomEdgeEnabled
147 anchors {
148 bottom: parent.bottom
149 horizontalCenter: bottomEdge.horizontalCenter
150 bottomMargin: hidden ? - height + units.gu(1) : -units.gu(1)
151 Behavior on bottomMargin {
152 SequentialAnimation {
153 // wait some msecs in case of the focus change again, to avoid flickering
154 PauseAnimation {
155 duration: 300
156 }
157 UbuntuNumberAnimation {
158 duration: UbuntuAnimation.SnapDuration
159 }
160 }
161 }
162 }
163
164 z: 1
165 width: tipLabel.paintedWidth + units.gu(6)
166 height: bottomEdge.tipHeight + units.gu(1)
167 color: bottomEdgeTipColor //color: "#C9C9C9"
168
169 Label {
170 id: tipLabel
171
172 anchors {
173 top: parent.top
174 left: parent.left
175 right: parent.right
176 }
177 height: bottomEdge.tipHeight
178 verticalAlignment: Text.AlignVCenter
179 horizontalAlignment: Text.AlignHCenter
180 opacity: tip.hidden ? 0.0 : 1.0
181 Behavior on opacity {
182 UbuntuNumberAnimation {
183 duration: UbuntuAnimation.SnapDuration
184 }
185 }
186 }
187 } // UbuntuShape
188
189 Rectangle {
190 id: shadow
191
192 anchors {
193 left: parent.left
194 right: parent.right
195 bottom: bottomEdge.top
196 }
197 height: units.gu(1)
198 z: 1
199 opacity: 0.0
200 gradient: Gradient {
201 GradientStop { position: 0.0; color: "transparent" }
202 GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.2) }
203 }
204 }
205
206 MouseArea {
207 id: mouseArea
208
209 property real previousY: -1
210 property string dragDirection: "None"
211
212 preventStealing: true
213 drag {
214 axis: Drag.YAxis
215 target: bottomEdge
216 minimumY: __pageStartY
217 maximumY: page.height
218 }
219 enabled: bottomEdgePageLoaded
220 visible: page.bottomEdgeEnabled
221
222 anchors {
223 left: parent.left
224 right: parent.right
225 bottom: parent.bottom
226 }
227 height: bottomEdge.tipHeight
228 z: 1
229
230 onReleased: {
231 page.bottomEdgeReleased()
232 if ((dragDirection === "BottomToTop") &&
233 bottomEdge.y < (page.height - page.height * bottomEdgeExpandThreshold - bottomEdge.tipHeight)) {
234 bottomEdge.state = "expanded"
235 } else {
236 bottomEdge.state = "collapsed"
237 }
238 previousY = -1
239 dragDirection = "None"
240 }
241
242 onPressed: {
243 previousY = mouse.y
244 tip.forceActiveFocus()
245 }
246
247 onMouseYChanged: {
248 var yOffset = previousY - mouseY
249 // skip if was a small move
250 if (Math.abs(yOffset) <= units.gu(2))
251 return
252
253 previousY = mouseY
254 dragDirection = yOffset > 0 ? "BottomToTop" : "TopToBottom"
255 }
256 }
257
258 FakeHeader {
259 id: fakeHeader
260 visible: bottomEdgeEnabled && !bottomEdgeHeaderHidden
261
262 anchors {
263 left: parent.left
264 right: parent.right
265 }
266 y: -fakeHeader.height + (fakeHeader.height * (page.height - bottomEdge.y)) / (page.height - fakeHeader.height)
267 z: bgVisual.z + 1
268
269 Behavior on y {
270 UbuntuNumberAnimation {
271 duration: UbuntuAnimation.SnapDuration
272 }
273 }
274 }
275
276 Rectangle {
277 id: bottomEdge
278 objectName: "bottomEdge"
279
280 readonly property int tipHeight: units.gu(3)
281
282
283 z: 1
284 color: bottomEdgeBackgroundColor
285 clip: true
286 anchors {
287 left: parent.left
288 right: parent.right
289 }
290 height: page.height
291 y: height
292
293 visible: !page.isCollapsed
294 state: "collapsed"
295 states: [
296 State {
297 name: "collapsed"
298 PropertyChanges {
299 target: bottomEdge
300 y: bottomEdge.height
301 }
302 PropertyChanges {
303 target: fakeHeader
304 y: -fakeHeader.height
305 }
306 },
307 State {
308 name: "expanded"
309 PropertyChanges {
310 target: bottomEdge
311 y: __pageStartY
312 }
313 PropertyChanges {
314 target: fakeHeader
315 y: 0
316 }
317 },
318 State {
319 name: "floating"
320 when: mouseArea.drag.active
321 PropertyChanges {
322 target: shadow
323 opacity: 1.0
324 }
325 }
326 ]
327
328 transitions: [
329 Transition {
330 to: "expanded"
331 SequentialAnimation {
332 alwaysRunToEnd: true
333 ParallelAnimation {
334 SmoothedAnimation {
335 target: bottomEdge
336 property: "y"
337 duration: UbuntuAnimation.FastDuration
338 easing.type: Easing.Linear
339 }
340 SmoothedAnimation {
341 target: fakeHeader
342 property: "y"
343 duration: UbuntuAnimation.FastDuration
344 easing.type: Easing.Linear
345 }
346 }
347 SmoothedAnimation {
348 target: shaderSource
349 property: "anchors.topMargin"
350 to: - units.gu(4)
351 duration: UbuntuAnimation.FastDuration
352 easing.type: Easing.Linear
353 }
354 SmoothedAnimation {
355 target: shaderSource
356 property: "anchors.topMargin"
357 to: 0
358 duration: UbuntuAnimation.FastDuration
359 easing: UbuntuAnimation.StandardEasing
360 }
361 ScriptAction {
362 script: page.__pushPage()
363 }
364 }
365 },
366 Transition {
367 from: "expanded"
368 to: "collapsed"
369 SequentialAnimation {
370 alwaysRunToEnd: true
371
372 ScriptAction {
373 script: {
374 Qt.inputMethod.hide()
375 bottomEdgePage.active = false
376 }
377 }
378 ParallelAnimation {
379 SmoothedAnimation {
380 target: bottomEdge
381 property: "y"
382 duration: UbuntuAnimation.SlowDuration
383 }
384 SmoothedAnimation {
385 target: fakeHeader
386 property: "y"
387 duration: UbuntuAnimation.SlowDuration
388 }
389 }
390 ScriptAction {
391 script: {
392 // notify
393 page.bottomEdgeDismissed()
394 bottomEdgePage.active = true
395 }
396 }
397 }
398 },
399 Transition {
400 from: "floating"
401 to: "collapsed"
402 UbuntuNumberAnimation {
403 target: bottomEdge
404 property: "opacity"
405 }
406 }
407 ]
408
409 ShaderEffectSource {
410 id: shaderSource
411 sourceItem: bottomEdgePage
412 anchors {
413 top: parent.top
414 left: parent.left
415 right: parent.right
416 }
417 height: page.height - fakeHeader.height
418
419 Binding {
420 target: bottomEdgePageLoaded ? shaderSource : null
421 property: "anchors.topMargin"
422 value: bottomEdgePage && bottomEdgePage.flickable ? bottomEdgePage.flickable.contentY : 0
423 when: !page.isReady
424 }
425 }
426 } // Rectanlgle
427}
0428
=== added file 'curated-store/ComponentStore/BottomEdgeTabs/FakeHeader.qml'
--- curated-store/ComponentStore/BottomEdgeTabs/FakeHeader.qml 1970-01-01 00:00:00 +0000
+++ curated-store/ComponentStore/BottomEdgeTabs/FakeHeader.qml 2015-04-14 06:07:01 +0000
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This file is part of Ubuntu Clock App
5 *
6 * Ubuntu Clock App is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * Ubuntu Clock App is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19import QtQuick 2.3
20import Ubuntu.Components 1.1
21
22Column {
23 id: fakeHeader
24
25 height: units.gu(9)
26
27 Rectangle {
28 height: units.gu(7)
29 width: parent.width
30 color: Theme.palette.normal.background
31 }
32
33 Rectangle {
34 color: "#C9C9C9"
35 height: units.gu(2)
36 anchors.left: parent.left
37 anchors.right: parent.right
38 }
39}
040
=== added file 'curated-store/ComponentStore/BottomEdgeTabs/ubuntu_component_store.json'
--- curated-store/ComponentStore/BottomEdgeTabs/ubuntu_component_store.json 1970-01-01 00:00:00 +0000
+++ curated-store/ComponentStore/BottomEdgeTabs/ubuntu_component_store.json 2015-04-14 06:07:01 +0000
@@ -0,0 +1,6 @@
1{
2 "name": "BottomEdgeTabs",
3 "description": "This component adds a bottom edge page to Tabs.",
4 "version": "1.0",
5 "documentation_url": "http://ubuntu-component-store.readthedocs.org/en/latest/_components/bottomedgetabs.html"
6}
07
=== added file 'curated-store/GallerySRC/BottomEdgeTabsWidget.qml'
--- curated-store/GallerySRC/BottomEdgeTabsWidget.qml 1970-01-01 00:00:00 +0000
+++ curated-store/GallerySRC/BottomEdgeTabsWidget.qml 2015-04-14 06:07:01 +0000
@@ -0,0 +1,69 @@
1import QtQuick 2.0
2import Ubuntu.Components 1.1
3import Ubuntu.Components.ListItems 1.0 as ListItems
4import "../ComponentStore/BottomEdgeTabs"
5
6TemplateWidgetPage {
7 id: bottomEdgeTabsWidget
8
9 title: "Tabs With Bottom Edge"
10 author: "Roman Shchekin"
11 email: "mrqtros@gmail.com"
12 license: "GNU General Public License v3.0"
13 description: "Tabs component with the ability to setting bottom edge page."
14
15 Component {
16 id: pageComponent
17
18 PageStack {
19 id: stack
20 Component.onCompleted: push(tabs)
21
22 BottomEdgeTabs {
23 id: tabs
24
25 bottomEdgePage: secondPage
26 bottomEdgeTitle: "Violet page"
27
28 Tab {
29 title: "First tab"
30 page: Page {
31 Label {
32 anchors.centerIn: parent
33 text: "Content of first tab"
34 }
35 }
36 }
37
38 Tab {
39 title: "Second tab"
40 page: Page {
41 Label {
42 anchors.centerIn: parent
43 text: "Centered label"
44 }
45 }
46 }
47 } // BottomEdgeTabs
48
49 Page {
50 id: secondPage
51 title: "Violet page"
52 visible: false
53
54 Rectangle {
55 anchors.fill: parent
56 color: "darkviolet"
57 }
58 }
59 }
60 }
61
62 content: Button {
63 text: "Preview BottomEdgeTabs Component"
64 color: "Green"
65 height: units.gu(6)
66 onClicked: stack.push(pageComponent)
67 anchors.centerIn: parent
68 }
69}
070
=== modified file 'curated-store/GallerySRC/WidgetsModel.qml'
--- curated-store/GallerySRC/WidgetsModel.qml 2015-03-03 13:16:09 +0000
+++ curated-store/GallerySRC/WidgetsModel.qml 2015-04-14 06:07:01 +0000
@@ -37,4 +37,9 @@
37 label: "Welcome Wizard"37 label: "Welcome Wizard"
38 source: "GallerySRC/WelcomeWizardWidget.qml"38 source: "GallerySRC/WelcomeWizardWidget.qml"
39 }39 }
40
41 ListElement {
42 label: "Tabs With Bottom Edge"
43 source: "GallerySRC/BottomEdgeTabsWidget.qml"
44 }
40}45}
4146
=== added file 'docs/_components/bottomedgetabs.rst'
--- docs/_components/bottomedgetabs.rst 1970-01-01 00:00:00 +0000
+++ docs/_components/bottomedgetabs.rst 2015-04-14 06:07:01 +0000
@@ -0,0 +1,129 @@
1Bottom Edge Tabs
2================
3
4+----------+----------------------------------------+
5| Author | Roman Shchekin |
6+----------+-------------+--------------------------+
7| License | GNU General Public License v3.0 |
8+----------+----------------------------------------+
9| Contact | mrqtros@gmail.com |
10+----------+----------------------------------------+
11| Framework| ubuntu-sdk-14.10 |
12+----------+----------------------------------------+
13
14BottomEdgeTabs is very similar to PageWithBottomEdge but uses Tabs as root component instead of Page. Check it's documentation.
15
16Example:
17
18.. code-block:: qml
19
20 MainView {
21 objectName: "mainView"
22
23 applicationName: "com.ubuntu.developer.qtros.tabsbottomedge"
24
25 width: units.gu(50)
26 height: units.gu(75)
27 useDeprecatedToolbar: false
28
29 PageStack {
30 id: stack
31 Component.onCompleted: push(tabs)
32
33 BottomEdgeTabs {
34 id: tabs
35
36 bottomEdgePage: secondPage
37 bottomEdgeTitle: "Violet page"
38
39 Tab {
40 title: "First tab"
41 page: Page {
42 Label {
43 anchors.centerIn: parent
44 text: "Content of first tab"
45 }
46 }
47 }
48
49 Tab {
50 title: "Second tab"
51 page: Page {
52 Label {
53 anchors.centerIn: parent
54 text: "Centered label"
55 }
56 }
57 }
58 } // BottomEdgeTabs
59
60 Page {
61 id: secondPage
62 title: "Violet page"
63 visible: false
64
65 Rectangle {
66 anchors.fill: parent
67 color: "darkviolet"
68 }
69 }
70 }
71 }
72
73.. image:: ../_images/bottomedgetabs.png
74 :align: center
75
76Properties
77----------
78
79- :ref:`bottomEdgeTitle`: string
80- :ref:`bottomEdgePage`: Page
81- :ref:`bottomEdgeEnabled`: boolean
82
83Signals
84-------
85
86- :ref:`bottomEdgeReleased()`
87- :ref:`bottomEdgeDismissed()`
88
89Property Documentation
90----------------------
91
92.. _bottomEdgeTitle:
93
94bottomEdgeTitle
95^^^^^^^^^^^^^^^
96
97The text to be displayed in the bottom edge action.
98
99.. _bottomEdgePage:
100
101bottomEdgePage
102^^^^^^^^^^^^^^
103
104The page to be shown when swiping the bottom edge up.
105
106.. _bottomEdgeEnabled:
107
108bottomEdgeEnabled
109^^^^^^^^^^^^^^^^^
110
111Boolean property to enable/disable the bottom edge
112
113Signal Documentation
114--------------------
115
116.. _bottomEdgeReleased():
117
118bottomEdgeReleased()
119^^^^^^^^^^^^^^^^^^^^
120
121This handler is called when the bottom edge is let go.
122
123.. _bottomEdgeDismissed():
124
125bottomEdgeDismissed()
126^^^^^^^^^^^^^^^^^^^^^
127
128Called when the bottom edge is dismissed (hidden).
129
0130
=== added file 'docs/_images/bottomedgetabs.png'
1Binary files docs/_images/bottomedgetabs.png 1970-01-01 00:00:00 +0000 and docs/_images/bottomedgetabs.png 2015-04-14 06:07:01 +0000 differ131Binary files docs/_images/bottomedgetabs.png 1970-01-01 00:00:00 +0000 and docs/_images/bottomedgetabs.png 2015-04-14 06:07:01 +0000 differ
=== modified file 'docs/index.rst'
--- docs/index.rst 2015-04-13 17:45:49 +0000
+++ docs/index.rst 2015-04-14 06:07:01 +0000
@@ -50,6 +50,7 @@
50.. toctree::50.. toctree::
51 :maxdepth: 151 :maxdepth: 1
52 52
53 _components/bottomedgetabs
53 _components/circleimage54 _components/circleimage
54 _components/emptystate55 _components/emptystate
55 _components/fastscroll56 _components/fastscroll
5657
=== modified file 'docs/release.rst'
--- docs/release.rst 2015-03-23 14:32:46 +0000
+++ docs/release.rst 2015-04-14 06:07:01 +0000
@@ -1,6 +1,10 @@
1Release Notes1Release Notes
2=============2=============
33
4**13th April 2015**
5
6* Added Bottom Edge Tabs component
7
4**23rd March 2015**8**23rd March 2015**
59
6* Added haptic feedback to radial action buttons10* Added haptic feedback to radial action buttons

Subscribers

People subscribed via source and target branches