Merge lp:~tpeeters/ubuntu-ui-toolkit/100-SectionBar into lp:ubuntu-ui-toolkit/staging

Proposed by Tim Peeters
Status: Merged
Approved by: Zsombor Egri
Approved revision: 1564
Merged at revision: 1535
Proposed branch: lp:~tpeeters/ubuntu-ui-toolkit/100-SectionBar
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 835 lines (+732/-0)
12 files modified
components.api (+4/-0)
examples/ubuntu-ui-toolkit-gallery/Sections.qml (+47/-0)
examples/ubuntu-ui-toolkit-gallery/WidgetsModel.qml (+5/-0)
modules/Ubuntu/Components/1.3/Sections.qml (+101/-0)
modules/Ubuntu/Components/Themes/Ambiance/1.3/SectionsStyle.qml (+119/-0)
modules/Ubuntu/Components/qmldir (+1/-0)
tests/autopilot/ubuntuuitoolkit/__init__.py (+2/-0)
tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py (+2/-0)
tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_sections.py (+49/-0)
tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.SectionsTestCase.qml (+42/-0)
tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.py (+51/-0)
tests/unit_x11/tst_components/tst_sections.qml (+309/-0)
To merge this branch: bzr merge lp:~tpeeters/ubuntu-ui-toolkit/100-SectionBar
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Zsombor Egri Approve
Tim Peeters Needs Fixing
Review via email: mp+260502@code.launchpad.net

Commit message

Introduce the new Sections component.

Description of the change

Introduce the new Sections component.

This component will be used (in a following MR) in the new header to replace the sections selector in the current header divider. Sections will also be available as a separate component for convergence apps that need to place the Sections outside of the single standard header.

To post a comment you must log in.
1534. By Tim Peeters

docs

1535. By Tim Peeters

docs

1536. By Tim Peeters

spacing

1537. By Tim Peeters

spacing

1538. By Tim Peeters

update components.api

1539. By Tim Peeters

docs

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1540. By Tim Peeters

remove empty functions from tst_sections

1541. By Tim Peeters

sections

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

Comments inline. I'm not good with the API.

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote :

38 +/*!
39 + \qmltype Sections
40 + \inqmlmodule Ubuntu.Components 1.3
41 + \ingroup ubuntu
42 + \since Ubuntu.Components 1.3
43 + \brief Display a list of sections that the user can select.
44 + */
> Zsombor Egri (zsombi) wrote 7 hours ago:
> Shouldn't you have more to say here?

Yes I can extend it a bit.

45 +StyledItem {
46 + id: sections
47 + style: theme.createStyleComponent("SectionsStyle.qml", sections)
> Zsombor Egri (zsombi) wrote 7 hours ago:
> This is wrong, once the styleName will get into staging, this will be broken. Please merge with
> styleName MR and fix this. With a small luck, we will get it soon if LP gets it.

Ok, will do. I thought I would land my MR before you land yours. ;)

48 +
49 + /*!
50 + List of strings that represent section names. Example:
51 + \qml
> Zsombor Egri (zsombi) wrote 7 hours ago:
> Hmm.... I was thinking shouldn't this be rather a list of actions? Then you don't need the
> model and the selectedIndex properties separated. The Action would drive the visual (you
> would also be able to show icons if design changes his mind - with the current setup an API
> change would be needed) and the trigger would tell which Action is selected. I feel we have
> to discuss more about this.

Ok. After our discussion, I'll make this a list of actions and keep the selectedIndex as well. Changing the selectedIndex will trigger the appropriate Action.

137 + Row {
138 + id: sectionsRow
> Zsombor Egri (zsombi) wrote 7 hours ago:
> Aren't the sections proportionally filling the space? What if a text exceeds the
> space available?

No. In the new designs, the sections are always aligned left and don't fill the space.
If the text exceeds the available space, the section list will be scrollable. I will add the scrolling in a following MR.

150 + AbstractButton {
151 + id: sectionButton
> Zsombor Egri (zsombi) wrote 7 hours ago:
> I feel like this should be rather that FlatButton instead...

We don't have a FlatButton yet. I think the AbstractButton is fine here, since the visuals are quite specific for the section selector.

399 + def test_click_unexisting_section_button(self):
400 + error = self.assertRaises(
Zsombor Egri (zsombi) wrote 7 hours ago:
> Why do you need this? Can't you cover this in unit test?

It does not test component functionality, only verifies that the CPO works as expected.

1542. By Tim Peeters

sync staging

1543. By Tim Peeters

use styleName in Sections

1544. By Tim Peeters

extend docs a bit

1545. By Tim Peeters

use Actions instead of strings for the model

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1546. By Tim Peeters

changing selectedIndex triggers Action.

1547. By Tim Peeters

update components.api

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1548. By Tim Peeters

sync staging

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

/tmp/buildd/ubuntu-ui-toolkit-1.3.1517+15.10.20150523bzr1548pkg0vivid571/modules/Ubuntu/Components/1.3/Sections.qml:36: warning: Unknown command '\selectedIndex'
/tmp/buildd/ubuntu-ui-toolkit-1.3.1517+15.10.20150523bzr1548pkg0vivid571/modules/Ubuntu/Components/1.3/Sections.qml:64: warning: Can't link to 'model'
Makefile:289: recipe for target 'docs' failed

review: Needs Fixing
1549. By Tim Peeters

fix docs

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

Ready for another review.

Note that Page.head.sections.model is currently a list of strings, see https://developer.ubuntu.com/api/apps/qml/sdk-14.10/Ubuntu.Components.PageHeadSections/

Do we want to break that API and replace it with a list of Actions?

Revision history for this message
Zsombor Egri (zsombi) wrote :

> Ready for another review.
>
> Note that Page.head.sections.model is currently a list of strings, see https:/
> /developer.ubuntu.com/api/apps/qml/sdk-14.10/Ubuntu.Components.PageHeadSection
> s/
>
> Do we want to break that API and replace it with a list of Actions?

Do we break the API if we say that it can be either strings - in which case we have more work - or it also can be a list of Actions? I think not.

Revision history for this message
Tim Peeters (tpeeters) wrote :

Supporting both Actions and strings in PageHeadSections is problematic. Then in order to feed it to the Sections we need to convert the list of strings into a list of Actions. I don't see a simple way to do that in QML.

We can support strings and actions in Sections and PageHeadSections, and then inside Sections I'll have to support both in the Repeater. That is not difficult but I'd say it is a bit messy.

1550. By Tim Peeters

unit tests for list of strings as model

1551. By Tim Peeters

rename actions to model and support a list of strings as model

1552. By Tim Peeters

improve test app

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1553. By Tim Peeters

split up unit tests

1554. By Tim Peeters

update components.api

1555. By Tim Peeters

merge staging

1556. By Tim Peeters

update docs

Revision history for this message
Tim Peeters (tpeeters) wrote :

Updated and ready for another review. The 'actions' property was renamed to 'model' and now accepts either a list of Actions or a list of strings. Docs and unit tests were also updated.

1557. By Tim Peeters

fix components.api

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
Tim Peeters (tpeeters) wrote :

[10:55:46] <nerochiaro> timp: i am trying to use the Sections from your branch but when i follow the example and set actions to a list, like this "actions: [ Action { text: "A" } ]" QML gives me this error: "Cannot assign multiple values to a singular property"... any ideas why ?
[10:56:11] <nerochiaro> timp: if I create a list<Action> property and then assign it to the actions it works ok

review: Needs Fixing
1558. By Tim Peeters

fix

1559. By Tim Peeters

document actions/model

1560. By Tim Peeters

add Sections to the component gallery

1561. By Tim Peeters

clean tst_sections.qml

1562. By Tim Peeters

update components.api

1563. By Tim Peeters

update docs

1564. By Tim Peeters

fix docs

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: Needs Fixing (continuous-integration)
Revision history for this message
Zsombor Egri (zsombi) wrote :

Good to go.

review: Approve
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
=== modified file 'components.api'
--- components.api 2015-06-02 12:37:41 +0000
+++ components.api 2015-06-17 12:24:49 +0000
@@ -793,6 +793,10 @@
793 property int align793 property int align
794 property Flickable flickableItem794 property Flickable flickableItem
795Ubuntu.Components.ScrollbarUtils 0.1 1.0795Ubuntu.Components.ScrollbarUtils 0.1 1.0
796Ubuntu.Components.Sections 1.3: StyledItem
797 readonly property Action actions
798 property var model
799 property int selectedIndex
796Ubuntu.Components.ServiceProperties 1.1: QtObject800Ubuntu.Components.ServiceProperties 1.1: QtObject
797 property string adaptorInterface801 property string adaptorInterface
798 readonly property string error802 readonly property string error
799803
=== added file 'examples/ubuntu-ui-toolkit-gallery/Sections.qml'
--- examples/ubuntu-ui-toolkit-gallery/Sections.qml 1970-01-01 00:00:00 +0000
+++ examples/ubuntu-ui-toolkit-gallery/Sections.qml 2015-06-17 12:24:49 +0000
@@ -0,0 +1,47 @@
1/*
2 * Copyright 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
19
20Template {
21 objectName: "sectionsTemplate"
22
23 TemplateSection {
24 title: "Sections"
25 className: "Sections"
26
27 TemplateRow {
28 title: i18n.tr("Enabled")
29
30 Sections {
31 actions: [
32 Action { text: "one" },
33 Action { text: "two" },
34 Action { text: "three" }
35 ]
36 }
37 }
38 TemplateRow {
39 title: i18n.tr("Disabled")
40
41 Sections {
42 model: ["one", "two", "three"]
43 enabled: false
44 }
45 }
46 }
47}
048
=== modified file 'examples/ubuntu-ui-toolkit-gallery/WidgetsModel.qml'
--- examples/ubuntu-ui-toolkit-gallery/WidgetsModel.qml 2015-03-23 16:24:43 +0000
+++ examples/ubuntu-ui-toolkit-gallery/WidgetsModel.qml 2015-06-17 12:24:49 +0000
@@ -72,6 +72,11 @@
72 source: "ProgressBars.qml"72 source: "ProgressBars.qml"
73 }73 }
74 ListElement {74 ListElement {
75 objectName: "sectionsElement"
76 label: "Sections"
77 source: "Sections.qml"
78 }
79 ListElement {
75 objectName: "ubuntuShapesElement"80 objectName: "ubuntuShapesElement"
76 label: "Ubuntu Shape"81 label: "Ubuntu Shape"
77 source: "UbuntuShape.qml"82 source: "UbuntuShape.qml"
7883
=== added file 'modules/Ubuntu/Components/1.3/Sections.qml'
--- modules/Ubuntu/Components/1.3/Sections.qml 1970-01-01 00:00:00 +0000
+++ modules/Ubuntu/Components/1.3/Sections.qml 2015-06-17 12:24:49 +0000
@@ -0,0 +1,101 @@
1/*
2 * Copyright 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
19
20/*!
21 \qmltype Sections
22 \inqmlmodule Ubuntu.Components 1.3
23 \ingroup ubuntu
24 \since Ubuntu.Components 1.3
25 \brief Display a list of sections that the user can select. By tapping
26 on a section name the \l selectedIndex will be updated, and the
27 associated \l Action is triggered.
28 */
29StyledItem {
30 id: sections
31 styleName: "SectionsStyle"
32
33 /*!
34 List of actions that represent the sections.
35 The text of each action is displayed as the section name and clicking
36 a section will update the \l selectedIndex.
37
38 When \l selectedIndex is changed (by user interaction or by setting
39 the value), actions[selectedIndex] will be triggered.
40
41 Example:
42 \qml
43 Sections {
44 actions: [
45 Action {
46 text: "first"
47 onTriggered: print("one")
48 },
49 Action {
50 text: "second"
51 onTriggered: print("two")
52 },
53 Action {
54 text: "third"
55 onTriggered: print("three")
56 }
57 ]
58 }
59 \endqml
60 It is strongly recommended to limit the number of sections to two or three.
61 The actions are used as the model for the Sections by default.
62 If no trigger functions need to be specified, \l model may be used directly
63 without setting the actions property. If both \l actions and \l model are set,
64 model overrides the actions.
65 */
66 property list<Action> actions
67
68 /*!
69 The input model for the sections. By default model takes the \l actions
70 as input, but if no trigger functions need to be specified, it can be
71 simplified to a list of strings naming the sections:
72 \qml
73 Sections {
74 model: [ "one", "two", "three" ]
75 onSelectedIndexChanged: {
76 print("Selected section " + model[selectedIndex]);
77 }
78 }
79 \endqml
80 */
81 property var model: actions
82 onModelChanged: {
83 if (model && model.length > 3) {
84 // FIXME: Make the Sections scrollable for more than 3 sections.
85 console.warn("It is not YET recommended or supported to use more than three sections.");
86 }
87 }
88
89 /*!
90 The index of the currently selected section in \l model.
91 */
92 property int selectedIndex: model ? 0 : -1
93
94 onSelectedIndexChanged: {
95 if ((selectedIndex >= 0) && (selectedIndex < model.length)) {
96 if (model[selectedIndex].hasOwnProperty("trigger")) {
97 model[selectedIndex].trigger();
98 }
99 }
100 }
101}
0102
=== added file 'modules/Ubuntu/Components/Themes/Ambiance/1.3/SectionsStyle.qml'
--- modules/Ubuntu/Components/Themes/Ambiance/1.3/SectionsStyle.qml 1970-01-01 00:00:00 +0000
+++ modules/Ubuntu/Components/Themes/Ambiance/1.3/SectionsStyle.qml 2015-06-17 12:24:49 +0000
@@ -0,0 +1,119 @@
1/*
2 * Copyright 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 */
16import QtQuick 2.4
17import Ubuntu.Components 1.3
18
19Item {
20 id: sectionsStyle
21
22 implicitWidth: sectionsRow.width
23 implicitHeight: units.gu(4)
24
25 enabled: styledItem.enabled
26 opacity: enabled ? 1.0 : 0.5
27
28 /*!
29 The foreground color of unselected sections.
30 */
31 property color sectionColor: theme.palette.selected.backgroundText
32
33 /*!
34 The foreground color of the selected section.
35 */
36 property color selectedSectionColor: UbuntuColors.orange
37
38 /*!
39 The background color for the pressed section button.
40 */
41 property color pressedBackgroundColor: theme.palette.selected.background
42
43 /*!
44 The font size for the text in the buttons.
45 */
46 property string fontSize: "small"
47
48 /*!
49 The spacing on the left and right sides of the label
50 inside a section button.
51 */
52 property real horizontalLabelSpacing: units.gu(2)
53
54 /*!
55 The height of the bar underlining the sections.
56 */
57 property real underlineHeight: units.dp(2)
58
59 Row {
60 id: sectionsRow
61 anchors {
62 top: parent.top
63 bottom: parent.bottom
64 horizontalCenter: parent.horizontalCenter
65 }
66 width: childrenRect.width
67
68 Repeater {
69 id: sectionsRepeater
70 model: styledItem.model
71 objectName: "sections_repeater"
72 AbstractButton {
73 id: sectionButton
74 anchors {
75 top: parent ? parent.top : undefined
76 bottom: parent ? parent.bottom : undefined
77 }
78 objectName: "section_button_" + index
79 width: label.width + 2 * sectionsStyle.horizontalLabelSpacing
80 height: sectionsRow.height
81 property bool selected: index === styledItem.selectedIndex
82 onClicked: styledItem.selectedIndex = index
83
84 // Background pressed highlight
85 Rectangle {
86 visible: parent.pressed
87 anchors.fill: parent
88 color: sectionsStyle.pressedBackgroundColor
89 }
90
91 // Section title
92 Label {
93 id: label
94 objectName: "section_button_label_" + index
95 // modelData may be either a string, or an Action
96 text: modelData.hasOwnProperty("text") ? modelData.text : modelData
97 fontSize: sectionsStyle.fontSize
98 anchors.centerIn: parent
99 color: sectionButton.selected ?
100 sectionsStyle.selectedSectionColor :
101 sectionsStyle.sectionColor
102 }
103
104 // Section title underline
105 Rectangle {
106 anchors {
107 bottom: parent.bottom
108 left: parent.left
109 right: parent.right
110 }
111 height: sectionsStyle.underlineHeight
112 color: sectionButton.selected ?
113 sectionsStyle.selectedSectionColor :
114 sectionsStyle.sectionColor
115 }
116 }
117 }
118 }
119}
0120
=== modified file 'modules/Ubuntu/Components/qmldir'
--- modules/Ubuntu/Components/qmldir 2015-05-12 13:41:39 +0000
+++ modules/Ubuntu/Components/qmldir 2015-06-17 12:24:49 +0000
@@ -133,6 +133,7 @@
133PageHeadConfiguration 1.3 1.3/PageHeadConfiguration.qml133PageHeadConfiguration 1.3 1.3/PageHeadConfiguration.qml
134PageHeadSections 1.3 1.3/PageHeadSections.qml134PageHeadSections 1.3 1.3/PageHeadSections.qml
135PageHeadState 1.3 1.3/PageHeadState.qml135PageHeadState 1.3 1.3/PageHeadState.qml
136Sections 1.3 1.3/Sections.qml
136Header 1.3 1.3/Header.qml137Header 1.3 1.3/Header.qml
137CrossFadeImage 1.3 1.3/CrossFadeImage.qml138CrossFadeImage 1.3 1.3/CrossFadeImage.qml
138OrientationHelper 1.3 1.3/OrientationHelper.qml139OrientationHelper 1.3 1.3/OrientationHelper.qml
139140
=== modified file 'tests/autopilot/ubuntuuitoolkit/__init__.py'
--- tests/autopilot/ubuntuuitoolkit/__init__.py 2015-05-14 20:08:45 +0000
+++ tests/autopilot/ubuntuuitoolkit/__init__.py 2015-06-17 12:24:49 +0000
@@ -38,6 +38,7 @@
38 'QQuickFlickable',38 'QQuickFlickable',
39 'QQuickGridView',39 'QQuickGridView',
40 'QQuickListView',40 'QQuickListView',
41 'Sections',
41 'TabBar',42 'TabBar',
42 'Tabs',43 'Tabs',
43 'tests',44 'tests',
@@ -76,6 +77,7 @@
76 QQuickFlickable,77 QQuickFlickable,
77 QQuickGridView,78 QQuickGridView,
78 QQuickListView,79 QQuickListView,
80 Sections,
79 TabBar,81 TabBar,
80 Tabs,82 Tabs,
81 TextArea,83 TextArea,
8284
=== modified file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py'
--- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py 2015-05-14 20:08:45 +0000
+++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/__init__.py 2015-06-17 12:24:49 +0000
@@ -35,6 +35,7 @@
35 'QQuickFlickable',35 'QQuickFlickable',
36 'QQuickGridView',36 'QQuickGridView',
37 'QQuickListView',37 'QQuickListView',
38 'Sections',
38 'TabBar',39 'TabBar',
39 'Tabs',40 'Tabs',
40 'TextArea',41 'TextArea',
@@ -46,6 +47,7 @@
46]47]
4748
48from ubuntuuitoolkit._custom_proxy_objects._actionbar import ActionBar49from ubuntuuitoolkit._custom_proxy_objects._actionbar import ActionBar
50from ubuntuuitoolkit._custom_proxy_objects._sections import Sections
49from ubuntuuitoolkit._custom_proxy_objects._checkbox import CheckBox51from ubuntuuitoolkit._custom_proxy_objects._checkbox import CheckBox
50from ubuntuuitoolkit._custom_proxy_objects._common import (52from ubuntuuitoolkit._custom_proxy_objects._common import (
51 check_autopilot_version,53 check_autopilot_version,
5254
=== added file 'tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_sections.py'
--- tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_sections.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/ubuntuuitoolkit/_custom_proxy_objects/_sections.py 2015-06-17 12:24:49 +0000
@@ -0,0 +1,49 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright (C) 2015 Canonical Ltd.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published by
7# the Free Software Foundation; version 3.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import logging
18
19from autopilot import logging as autopilot_logging
20from autopilot.introspection import dbus
21from ubuntuuitoolkit._custom_proxy_objects import _common
22
23
24logger = logging.getLogger(__name__)
25
26
27class Sections(_common.UbuntuUIToolkitCustomProxyObjectBase):
28 """Sections Autopilot custom proxy object."""
29
30 def _get_section_button(self, section_index):
31 try:
32 object_name = "section_button_" + str(section_index)
33 button = self.select_single(objectName=object_name)
34 except dbus.StateNotFoundError:
35 raise _common.ToolkitException(
36 'Button not found in Sections.')
37
38 return button
39
40 @autopilot_logging.log_action(logger.info)
41 def click_section_button(self, section_index):
42 """Click a section button of the Sections.
43
44 :parameter section_index: The index of the section to click.
45 :raise ToolkitException: If there is no section button with that index.
46
47 """
48 button = self._get_section_button(section_index)
49 self.pointing_device.click_object(button)
050
=== added file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.SectionsTestCase.qml'
--- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.SectionsTestCase.qml 1970-01-01 00:00:00 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.SectionsTestCase.qml 2015-06-17 12:24:49 +0000
@@ -0,0 +1,42 @@
1/*
2 * Copyright 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
19
20MainView {
21 width: units.gu(48)
22 height: units.gu(60)
23 objectName: "mainView"
24 Page {
25 title: "Sections test"
26 Label {
27 id: label
28 objectName: "label"
29 anchors {
30 top: parent.top
31 horizontalCenter: parent.horizontalCenter
32 }
33 text: "Section " + sections.selectedIndex + " is selected."
34 }
35 Sections {
36 id: sections
37 objectName: "sections"
38 anchors.centerIn: parent
39 model: [ "first", "second", "third" ]
40 }
41 }
42}
043
=== added file 'tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.py'
--- tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.py 1970-01-01 00:00:00 +0000
+++ tests/autopilot/ubuntuuitoolkit/tests/custom_proxy_objects/test_sections.py 2015-06-17 12:24:49 +0000
@@ -0,0 +1,51 @@
1# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2#
3# Copyright (C) 2015 Canonical Ltd.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published by
7# the Free Software Foundation; version 3.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Lesser General Public License for more details.
13#
14# You should have received a copy of the GNU Lesser General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17import os
18import ubuntuuitoolkit
19from ubuntuuitoolkit import tests
20
21
22class SectionsTestCase(tests.QMLFileAppTestCase):
23
24 path = os.path.abspath(__file__)
25 dir_path = os.path.dirname(path)
26 test_qml_file_path = os.path.join(
27 dir_path, 'test_sections.SectionsTestCase.qml')
28
29 def setUp(self):
30 super().setUp()
31 self.sections = self.app.select_single(
32 'Sections', objectName='sections')
33 self.label = self.app.select_single(
34 'Label', objectName='label')
35 self.assertEqual(self.label.text, 'Section 0 is selected.')
36
37 def test_custom_proxy_object(self):
38 self.assertIsInstance(self.sections, ubuntuuitoolkit.Sections)
39 self.assertTrue(self.sections.visible)
40
41 def test_click_section_button(self):
42 self.sections.click_section_button(2)
43 self.assertEqual(self.label.text, 'Section 2 is selected.')
44
45 def test_click_unexisting_section_button(self):
46 error = self.assertRaises(
47 ubuntuuitoolkit.ToolkitException,
48 self.sections.click_section_button, 3)
49 self.assertEqual(
50 str(error),
51 'Button not found in Sections.')
052
=== added file 'tests/unit_x11/tst_components/tst_sections.qml'
--- tests/unit_x11/tst_components/tst_sections.qml 1970-01-01 00:00:00 +0000
+++ tests/unit_x11/tst_components/tst_sections.qml 2015-06-17 12:24:49 +0000
@@ -0,0 +1,309 @@
1/*
2 * Copyright 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.Test 1.0
19import Ubuntu.Components 1.3
20
21Rectangle {
22 id: root
23 width: 400
24 height: 600
25 color: "white"
26
27 property list<Action> actionList: [
28 Action {
29 text: "first";
30 onTriggered: label.text = "First action triggered.";
31 },
32 Action {
33 text: "second";
34 onTriggered: label.text = "Second action triggered.";
35 },
36 Action {
37 text: "third";
38 onTriggered: label.text = "Third action triggered.";
39 }
40 ]
41
42 property var stringList: [
43 "string one", "string two", "string three"
44 ]
45
46 Column {
47 id: column
48 anchors {
49 left: parent.left
50 right: parent.right
51 top: parent.top
52 margins: units.gu(2)
53 }
54 spacing: units.gu(2)
55
56 Label {
57 anchors.horizontalCenter: parent.horizontalCenter
58 text: "Sections with actions"
59 }
60 Label {
61 anchors.left: parent.left
62 text: "actions in-line:"
63 fontSize: small
64 }
65 Sections {
66 // Not used in the tests below, but added here to
67 // verify that the Actions can be defined directly
68 // inside the list of actions.
69 actions: [
70 Action { text: "1" },
71 Action { text: "2" }
72 ]
73 }
74 Label {
75 anchors.left: parent.left
76 text: "enabled:"
77 fontSize: "small"
78 }
79 Sections {
80 id: enabledSections
81 actions: root.actionList
82 }
83 Label {
84 text: "disabled:"
85 fontSize: "small"
86 }
87 Sections {
88 id: disabledSections
89 actions: root.actionList
90 enabled: false
91 }
92 Rectangle {
93 anchors {
94 left: parent.left
95 right: parent.right
96 margins: units.gu(2)
97 }
98 color: UbuntuColors.blue
99 height: units.gu(10)
100 Label {
101 id: label
102 anchors.centerIn: parent
103 text: "No action triggered."
104 color: "white"
105 }
106 }
107 Label {
108 anchors.horizontalCenter: parent.horizontalCenter
109 text: "Sections with strings"
110 }
111 Label {
112 anchors.left: parent.left
113 text: "enabled:"
114 fontSize: "small"
115 }
116 Sections {
117 id: enabledStringSections
118 model: root.stringList
119 }
120 Label {
121 anchors.left: parent.left
122 text: "disabled:"
123 fontSize: "small"
124 }
125 Sections {
126 id: disabledStringSections
127 model: root.stringList
128 enabled: false
129 }
130 }
131
132 UbuntuTestCase {
133 id: testCase
134 name: "SectionsApi"
135 when: windowShown
136
137 function initTestCase() {
138 compare(label.text, "No action triggered.", "An action was triggered initially.");
139 }
140
141 function cleanup() {
142 enabledSections.selectedIndex = 0;
143 disabledSections.selectedIndex = 0;
144 enabledStringSections.selectedIndex = 0;
145 disabledStringSections.selectedIndex = 0;
146 }
147
148 function wait_for_animation(sections) {
149 // TODO when animations are added
150 }
151
152 function get_number_of_section_buttons(sections) {
153 var repeater = findChild(sections, "sections_repeater");
154 return repeater.count;
155 }
156
157 // return the index of the selected section button,
158 // or -1 if no selected section button is found.
159 function get_selected_section_button_index(sections) {
160 var n = get_number_of_section_buttons(sections);
161 var button;
162 for (var i=0; i < n; i++) {
163 button = findChild(sections, "section_button_"+i);
164 if (button.selected) {
165 return i;
166 }
167 }
168 return -1;
169 }
170
171 function get_selected_section_button_text(sections) {
172 var index = get_selected_section_button_index(sections);
173 if (index < 0) return "BUTTON NOT FOUND.";
174 var button = findChild(sections, "section_button_label_"+index);
175 return button.text;
176 }
177
178 function click_section_button(sections, sectionName) {
179 var index = -1;
180 var object;
181 for (index = 0; index < sections.model.length; index++) {
182 object = sections.model[index];
183 // object may be a string or an Action
184 if (object.hasOwnProperty("text")) {
185 if (object.text === sectionName) {
186 break;
187 }
188 } else {
189 if (object === sectionName) {
190 break;
191 }
192 }
193 }
194 verify(index >= 0, "Button with name \'"+sectionName+"\' not found.");
195 var button = findChild(sections, "section_button_"+index);
196 mouseClick(button, button.width/2, button.height/2);
197 }
198
199 function check_selected_section(sections, index, name) {
200 var v = sections.selectedIndex;
201 compare(v, index, "selectedIndex "+v+" does not match "+index);
202 v = get_selected_section_button_index(sections);
203 compare(v, index, "selected button index "+v+" does not match "+index);
204 var w = get_selected_section_button_text(sections);
205 compare(w, name, "selected button text \'"+w+"\' does not match \'"+name+"\'");
206 }
207
208 // in each test function below, test the desired behavior
209 // for both enabledSections and disabledSections.
210
211 function test_0_first_section_initially_selected_actions_enabled() {
212 check_selected_section(enabledSections, 0, "first");
213 }
214 function test_0_first_section_initially_selected_actions_disabled() {
215 check_selected_section(disabledSections, 0, "first");
216 }
217 function test_0_first_section_initially_selected_strings_enabled() {
218 check_selected_section(enabledStringSections, 0, "string one");
219 }
220 function test_0_first_section_initially_selected_strings_disabled() {
221 check_selected_section(disabledStringSections, 0, "string one");
222 }
223
224 function test_number_of_section_buttons() {
225 var n = root.actionList.length;
226 compare(get_number_of_section_buttons(enabledSections), n,
227 "Showing incorrect number of sections.");
228 compare(get_number_of_section_buttons(disabledSections), n,
229 "Showing incorrect number of disabled sections.")
230 }
231
232 function test_click_to_select_section_and_trigger_action() {
233 var index = 2;
234 var name = "third";
235 click_section_button(enabledSections, name);
236 wait_for_animation(enabledSections);
237 check_selected_section(enabledSections, index, name);
238 var text = "Third action triggered.";
239 compare(label.text, text, "Action for clicked button not triggered.");
240 }
241
242 function test_click_disabled_section_action() {
243 var index = 2;
244 var name = "third";
245 click_section_button(disabledSections, name);
246 wait_for_animation(disabledSections);
247 // first button should still be selected:
248 index = 0;
249 name = "first";
250 check_selected_section(disabledSections, index, name);
251 var text = "No action triggered.";
252 compare(label.text, text, "Clicking disabled button triggered something.");
253 }
254
255 function test_click_to_select_section_string() {
256 var index = 2;
257 var name = "string three";
258 click_section_button(enabledStringSections, name);
259 wait_for_animation(enabledStringSections);
260 check_selected_section(enabledStringSections, index, name);
261 }
262
263 function test_click_disabled_section_string() {
264 var name = "string three";
265 click_section_button(disabledStringSections, name);
266 wait_for_animation(disabledStringSections);
267 // first button should still be selected:
268 var index = 0;
269 name = "string one";
270 check_selected_section(disabledStringSections, index, name);
271 }
272
273 function test_set_selectedIndex_to_select_section_and_trigger_action_enabled() {
274 var index = 1;
275 var name = "second";
276 enabledSections.selectedIndex = index;
277 wait_for_animation(enabledSections);
278 check_selected_section(enabledSections, index, name);
279 var text = "Second action triggered.";
280 compare(label.text, text, "Changing selected index did not trigger action.");
281 }
282
283 function test_set_selectedIndex_to_select_section_and_trigger_action_disabled() {
284 var index = 2;
285 var name = "third";
286 disabledSections.selectedIndex = index;
287 wait_for_animation(disabledSections);
288 check_selected_section(disabledSections, index, name);
289 var text = "Third action triggered.";
290 compare(label.text, text, "Changing selected index for disabled Sections " +
291 "did not trigger action.");
292 }
293
294 function test_set_selectedIndex_to_select_section_string_enabled() {
295 var index = 1;
296 var name = "string two";
297 enabledStringSections.selectedIndex = index;
298 wait_for_animation(enabledStringSections);
299 check_selected_section(enabledStringSections, index, name);
300 }
301
302 function test_set_selectedIndex_to_select_section_string_disabled() {
303 var index = 2;
304 var name = "string three";
305 disabledStringSections.selectedIndex = index;
306 check_selected_section(disabledStringSections, index, name);
307 }
308 }
309}

Subscribers

People subscribed via source and target branches