on xenial help sign in
Actions Preview Widget
e44a203Michał Sawicz
qml/Dash/Previews/PreviewActionButton.qmlnew file+30
@@ -0,0 +1,30 @@
1+/*
2+ * Copyright (C) 2014 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+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+Button {
21+ signal triggeredAction(string id)
22+
23+ property var data: null
24+ objectName: "button" + (data && data.id || "")
25+ color: Theme.palette.selected.foreground
26+ text: data && data.label || ""
27+ iconSource: data && data.icon || ""
28+ iconPosition: "left"
29+ onClicked: triggeredAction(data.id)
30+}
qml/Dash/Previews/PreviewActionCombo.qmlnew file+66
@@ -0,0 +1,66 @@
1+/*
2+ * Copyright (C) 2014 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+import QtQuick 2.0
18+import Ubuntu.Components 0.1
19+
20+Item {
21+ id: root
22+
23+ implicitHeight: childrenRect.height
24+
25+ signal triggeredAction(string id)
26+
27+ property alias model: actionRepeater.model
28+
29+ Button {
30+ id: moreButton
31+ property bool expanded: false
32+
33+ objectName: "moreLessButton"
34+ text: !expanded ? i18n.tr("More...") : i18n.tr("Less...")
35+ color: Theme.palette.selected.foreground
36+ onClicked: expanded = !expanded
37+ width: parent.width
38+ }
39+
40+ Column {
41+ anchors {
42+ top: moreButton.bottom
43+ topMargin: height > 0 ? spacing : 0
44+ }
45+ objectName: "buttonColumn"
46+ spacing: units.gu(1)
47+ width: parent.width
48+ height: moreButton.expanded ? implicitHeight : 0
49+ clip: true
50+ Behavior on height {
51+ UbuntuNumberAnimation {
52+ duration: UbuntuAnimation.SnapDuration
53+ }
54+ }
55+
56+ Repeater {
57+ id: actionRepeater
58+
59+ delegate: PreviewActionButton {
60+ data: modelData
61+ width: implicitWidth < parent.width ? parent.width : implicitWidth
62+ onClicked: root.triggeredAction(modelData.id)
63+ }
64+ }
65+ }
66+}
qml/Dash/Previews/PreviewActions.qmlnew file+64
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright (C) 2014 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+import QtQuick 2.1
18+
19+/*! This preview widget shows either one button, two buttons or one button
20+ * and a combo button depending on the number of items in widgetData["actions"].
21+ * For each of the items we recognize the fields "label", "icon" and "id".
22+ */
23+
24+PreviewWidget {
25+ id: root
26+
27+ height: row.height
28+
29+ Row {
30+ id: row
31+ readonly property var actions: root.widgetData ? root.widgetData["actions"] : null
32+ anchors.right: parent.right
33+
34+ spacing: units.gu(1)
35+
36+ Loader {
37+ id: loader
38+ readonly property bool button: row.actions && row.actions.length == 2
39+ readonly property bool combo: row.actions && row.actions.length > 2
40+ source: button ? "PreviewActionButton.qml" : (combo ? "PreviewActionCombo.qml" : "")
41+ width: (root.width - units.gu(1)) / 2
42+ onLoaded: {
43+ if (button) {
44+ item.data = row.actions[1];
45+ } else if (combo) {
46+ item.model = row.actions.slice(1);
47+ }
48+ }
49+ Connections {
50+ target: loader.item
51+ onTriggeredAction: {
52+ root.triggered(root.widgetId, id, null);
53+ }
54+ }
55+ }
56+
57+ PreviewActionButton {
58+ data: visible ? row.actions[0] : null
59+ visible: row.actions && row.actions.length > 0
60+ onTriggeredAction: root.triggered(root.widgetId, id, null)
61+ width: (root.width - units.gu(1)) / 2
62+ }
63+ }
64+}
qml/Dash/Previews/PreviewWidget.qml+10
@@ -22,6 +22,16 @@ Item {
22 //! Specifies the preview widget being currently used or not
22 //! Specifies the preview widget being currently used or not
23 property bool isCurrentPreview: true
23 property bool isCurrentPreview: true
24
24
25+ //! The widget identifier
26+ property string widgetId
27+
25 //! Variable used to contain widget's data
28 //! Variable used to contain widget's data
26 property var widgetData
29 property var widgetData
30+
31+ /*! \brief This signal should be emitted when a preview action was triggered.
32+ *
33+ * \param widgetId,actionId Respective identifiers from widgetData.
34+ * \param data Optional widget-specific data sent to the scope.
35+ */
36+ signal triggered(string widgetId, string actionId, var data)
27}
37}
tests/qmltests/CMakeLists.txt+1
@@ -55,6 +55,7 @@ add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IM
55add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
55add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
56add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
56add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
57add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
57add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
58+add_qml_test(Dash/Previews PreviewActions IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
58add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
59add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
59add_qml_test(Dash/Previews PreviewImageGallery IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
60add_qml_test(Dash/Previews PreviewImageGallery IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
60add_qml_test(Dash/Previews PreviewTextSummary IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
61add_qml_test(Dash/Previews PreviewTextSummary IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
tests/qmltests/Dash/Previews/tst_PreviewActions.qmlnew file+148
@@ -0,0 +1,148 @@
1+/*
2+ * Copyright 2014 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+import QtQuick 2.0
18+import QtTest 1.0
19+import "../../../../qml/Dash/Previews"
20+import Unity.Test 0.1 as UT
21+import Ubuntu.Components 0.1
22+
23+
24+Rectangle {
25+ id: root
26+ width: units.gu(60)
27+ height: units.gu(80)
28+
29+ property var actionDataOneAction: {
30+ "actions": [{"label": "Some Label", "icon": "../graphics/play_button.png", "id": "someid"}]
31+ }
32+
33+ property var actionDataTwoActions: {
34+ "actions": [{"label": "Some Label A", "icon": "../graphics/icon_clear.png", "id": "someid1"},
35+ {"label": "Some Label B", "icon": "../graphics/play_button.png", "id": "someid2"}
36+ ]
37+ }
38+
39+ property var actionDataFiveActions: {
40+ "actions": [{"label": "Some Label C", "icon": "../graphics/play_button.png", "id": "someid3"},
41+ {"label": "Some Label D", "icon": "../graphics/icon_clear.png", "id": "someid4"},
42+ {"label": "Some Label E", "icon": "../graphics/play_button.png", "id": "someid5"},
43+ {"label": "Some Label F", "icon": "../graphics/icon_clear.png", "id": "someid6"},
44+ {"label": "Some Label G", "icon": "../graphics/play_button.png", "id": "someid7"}
45+ ]
46+ }
47+
48+ SignalSpy {
49+ id: spy
50+ signalName: "triggered"
51+ }
52+
53+ Column {
54+ spacing: units.gu(1)
55+
56+ PreviewActions {
57+ id: oneAction
58+ widgetId: "button"
59+ widgetData: actionDataOneAction
60+ onTriggered: console.log("triggered", widgetId, actionId);
61+ width: units.gu(50)
62+
63+ Rectangle {
64+ anchors.fill: parent
65+ color: "red"
66+ opacity: 0.1
67+ }
68+ }
69+
70+ PreviewActions {
71+ id: buttonAndCombo
72+ widgetId: "buttonAndCombo"
73+ widgetData: actionDataFiveActions
74+ onTriggered: console.log("triggered", widgetId, actionId);
75+ width: units.gu(40)
76+
77+ Rectangle {
78+ anchors.fill: parent
79+ color: "red"
80+ opacity: 0.1
81+ }
82+ }
83+
84+ PreviewActions {
85+ id: twoActions
86+ widgetId: "2buttons"
87+ widgetData: actionDataTwoActions
88+ onTriggered: console.log("triggered", widgetId, actionId);
89+ width: units.gu(60)
90+ }
91+ }
92+
93+ UT.UnityTestCase {
94+ name: "PreviewActionTest"
95+ when: windowShown
96+
97+ function cleanup()
98+ {
99+ spy.clear();
100+ }
101+
102+ function checkButtonPressSignal(target, id)
103+ {
104+ var button = findChild(root, "button" + id);
105+ verify(button != null);
106+ spy.target = target;
107+ mouseClick(button, button.width / 2, button.height / 2);
108+ compare(spy.count, 1);
109+ compare(spy.signalArguments[0][0], target.widgetId);
110+ compare(spy.signalArguments[0][1], id);
111+ }
112+
113+ function test_checkButtons_data() {
114+ return [
115+ {tag: "oneActionButton", target: oneAction, id: "someid" },
116+ {tag: "twobuttonsButton0", target: twoActions, id: "someid1" },
117+ {tag: "twobuttonsButton1", target: twoActions, id: "someid2" },
118+ {tag: "buttonAndComboButton0", target: buttonAndCombo, id: "someid3" }
119+ ]
120+ }
121+
122+ function test_checkButtons(data) {
123+ checkButtonPressSignal(data.target, data.id, data.buttonNumber)
124+ }
125+
126+ function test_comboButton_data() {
127+ return [
128+ {tag: "button1", id: "someid4" },
129+ {tag: "button2", id: "someid5" },
130+ {tag: "button3", id: "someid6" },
131+ {tag: "button4", id: "someid7" }
132+ ]
133+ }
134+
135+ function test_comboButton(data) {
136+ var button = findChild(root, "moreLessButton");
137+ var buttonColumn = findChild(root, "buttonColumn");
138+ verify(button != null);
139+ var twoActionsY = twoActions.y
140+ mouseClick(button, button.width / 2, button.height / 2);
141+ tryCompareFunction(function () { return twoActions.y <= twoActionsY; }, false);
142+ tryCompare(buttonColumn, "height", buttonColumn.implicitHeight);
143+ checkButtonPressSignal(buttonAndCombo, data.id, data.buttonNumber);
144+ mouseClick(button, button.width / 2, button.height / 2);
145+ tryCompare(twoActions, "y", twoActionsY);
146+ }
147+ }
148+}