on xenial help sign in
Merge trunk.
5c1075eMichał Sawicz
debian/changelog+25
@@ -1,3 +1,28 @@
1+unity8 (7.84+14.04.20140218-0ubuntu1) trusty; urgency=low
2+
3+ [ Michał Sawicz ]
4+ * Center-align title when it's alone in the header.
5+
6+ [ Leo Arias ]
7+ * Prepare unity8 to the _uinput refactors in autopilot.
8+
9+ [ Albert Astals ]
10+ * Progress Preview Widget
11+ * LWPH Fix crash from bug 1279434 (LP: #1279434)
12+ * Show the loading indicator of the screenshot in video playback
13+
14+ [ Andrea Cimitan ]
15+ * Adds rating preview widget. Work on the rating widget
16+
17+ [ Daniel d'Andrada ]
18+ * Make DirectionalDragArea work when rotated The drag gesture
19+ direction is in local coordinates, not in scene coordinates
20+
21+ [ Michał Karnicki ]
22+ * Center-align title when it's alone in the header.
23+
24+ -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 18 Feb 2014 11:41:58 +0000
25+
1unity8 (7.84+14.04.20140212-0ubuntu1) trusty; urgency=low
26unity8 (7.84+14.04.20140212-0ubuntu1) trusty; urgency=low
2
27
3 [ Gerry Boland ]
28 [ Gerry Boland ]
po/ar.po+6−4
@@ -8,7 +8,7 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
11−"PO-Revision-Date: 2013-12-05 06:55+0000\n"
11+"PO-Revision-Date: 2014-02-16 09:56+0000\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
12"Last-Translator: Ibrahim Saed <ibraheem5000@gmail.com>\n"
13"Language-Team: Arabic <ar@li.org>\n"
13"Language-Team: Arabic <ar@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
@@ -16,7 +16,7 @@ msgstr ""
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
17"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n % 100 >= "
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
18"3 && n % 100 <= 10 ? 3 : n % 100 >= 11 && n % 100 <= 99 ? 4 : 5;\n"
19−"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n"
19+"X-Launchpad-Export-Date: 2014-02-17 06:07+0000\n"
20"X-Generator: Launchpad (build 16916)\n"
20"X-Generator: Launchpad (build 16916)\n"
21
21
22#: plugins/Unity/Launcher/launcheritem.cpp:43
22#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -74,6 +74,8 @@ msgid ""
74"You have now mastered the edge gestures and can start using the "
74"You have now mastered the edge gestures and can start using the "
75"phone<br><br>Tap on the screen to start"
75"phone<br><br>Tap on the screen to start"
76msgstr ""
76msgstr ""
77+"أنت الآن بارع في إيماءات الحواف ويمكنك البدء باستخدام هاتفك<br><br>انقر على "
78+"الشاشة للبدء"
77
79
78#: qml/Components/PageHeader.qml:339
80#: qml/Components/PageHeader.qml:339
79msgid "Recent searches"
81msgid "Recent searches"
@@ -81,11 +83,11 @@ msgstr "عمليات البحث الأخيرة"
81
83
82#: qml/Components/SeeMore.qml:32
84#: qml/Components/SeeMore.qml:32
83msgid "See more"
85msgid "See more"
84−msgstr ""
86+msgstr "شاهد المزيد"
85
87
86#: qml/Components/SeeMore.qml:61
88#: qml/Components/SeeMore.qml:61
87msgid "See less"
89msgid "See less"
88−msgstr ""
90+msgstr "شاهد أقل"
89
91
90#: qml/Dash/Apps/AppPreview.qml:136
92#: qml/Dash/Apps/AppPreview.qml:136
91msgid "Rate this"
93msgid "Rate this"
po/fi.po+3−3
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
11−"PO-Revision-Date: 2013-11-20 08:09+0000\n"
11+"PO-Revision-Date: 2014-02-14 13:28+0000\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
12"Last-Translator: Jiri Grönroos <Unknown>\n"
13"Language-Team: Finnish <fi@li.org>\n"
13"Language-Team: Finnish <fi@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n"
18+"X-Launchpad-Export-Date: 2014-02-15 07:45+0000\n"
19"X-Generator: Launchpad (build 16916)\n"
19"X-Generator: Launchpad (build 16916)\n"
20
20
21#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -158,7 +158,7 @@ msgstr "Näytä salasana"
158
158
159#: qml/Notifications/NotificationMenuItemFactory.qml:103
159#: qml/Notifications/NotificationMenuItemFactory.qml:103
160msgid "Please enter SIM PIN"
160msgid "Please enter SIM PIN"
161−msgstr ""
161+msgstr "Anna SIM-kortin PIN-koodi"
162
162
163#: qml/Panel/SearchIndicator.qml:27
163#: qml/Panel/SearchIndicator.qml:27
164msgid "Search"
164msgid "Search"
po/gl.po+7−5
@@ -8,14 +8,14 @@ msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
11−"PO-Revision-Date: 2013-12-06 17:15+0000\n"
11+"PO-Revision-Date: 2014-02-15 04:00+0000\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
12"Last-Translator: Marcos Lans <Unknown>\n"
13"Language-Team: Galician <gl@li.org>\n"
13"Language-Team: Galician <gl@li.org>\n"
14"MIME-Version: 1.0\n"
14"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
17"Plural-Forms: nplurals=2; plural=n != 1;\n"
18−"X-Launchpad-Export-Date: 2014-02-12 06:27+0000\n"
18+"X-Launchpad-Export-Date: 2014-02-16 06:47+0000\n"
19"X-Generator: Launchpad (build 16916)\n"
19"X-Generator: Launchpad (build 16916)\n"
20
20
21#: plugins/Unity/Launcher/launcheritem.cpp:43
21#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -72,6 +72,8 @@ msgid ""
72"You have now mastered the edge gestures and can start using the "
72"You have now mastered the edge gestures and can start using the "
73"phone<br><br>Tap on the screen to start"
73"phone<br><br>Tap on the screen to start"
74msgstr ""
74msgstr ""
75+"Agora xa domina os xestos do bordo e pode comezar a usar o "
76+"teléfono<br><br>Toque na pantalla para comezar"
75
77
76#: qml/Components/PageHeader.qml:339
78#: qml/Components/PageHeader.qml:339
77msgid "Recent searches"
79msgid "Recent searches"
@@ -79,11 +81,11 @@ msgstr "Buscas recentes"
79
81
80#: qml/Components/SeeMore.qml:32
82#: qml/Components/SeeMore.qml:32
81msgid "See more"
83msgid "See more"
82−msgstr ""
84+msgstr "Ver máis"
83
85
84#: qml/Components/SeeMore.qml:61
86#: qml/Components/SeeMore.qml:61
85msgid "See less"
87msgid "See less"
86−msgstr ""
88+msgstr "Ver menos"
87
89
88#: qml/Dash/Apps/AppPreview.qml:136
90#: qml/Dash/Apps/AppPreview.qml:136
89msgid "Rate this"
91msgid "Rate this"
@@ -158,7 +160,7 @@ msgstr "Mostrar contrasinal"
158
160
159#: qml/Notifications/NotificationMenuItemFactory.qml:103
161#: qml/Notifications/NotificationMenuItemFactory.qml:103
160msgid "Please enter SIM PIN"
162msgid "Please enter SIM PIN"
161−msgstr ""
163+msgstr "Introduza o PIN da SIM"
162
164
163#: qml/Panel/SearchIndicator.qml:27
165#: qml/Panel/SearchIndicator.qml:27
164msgid "Search"
166msgid "Search"
po/ug.po+11−8
@@ -6,16 +6,17 @@
6msgid ""
6msgid ""
7msgstr ""
7msgstr ""
8"Project-Id-Version: unity\n"
8"Project-Id-Version: unity\n"
9−"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
9+"Report-Msgid-Bugs-To: \n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
10"POT-Creation-Date: 2014-02-04 15:43+0000\n"
11−"PO-Revision-Date: 2014-02-13 23:19+0000\n"
11+"PO-Revision-Date: 2014-02-15 12:09+0000\n"
12−"Last-Translator: volkhan <Unknown>\n"
12+"Last-Translator: Gheyret T.Kenji <Unknown>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
13"Language-Team: Uyghur <ug@li.org>\n"
14+"Language: \n"
14"MIME-Version: 1.0\n"
15"MIME-Version: 1.0\n"
15"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Type: text/plain; charset=UTF-8\n"
16"Content-Transfer-Encoding: 8bit\n"
17"Content-Transfer-Encoding: 8bit\n"
17"Plural-Forms: nplurals=1; plural=0;\n"
18"Plural-Forms: nplurals=1; plural=0;\n"
18−"X-Launchpad-Export-Date: 2014-02-14 07:53+0000\n"
19+"X-Launchpad-Export-Date: 2014-02-16 06:47+0000\n"
19"X-Generator: Launchpad (build 16916)\n"
20"X-Generator: Launchpad (build 16916)\n"
20
21
21#: plugins/Unity/Launcher/launcheritem.cpp:43
22#: plugins/Unity/Launcher/launcheritem.cpp:43
@@ -72,6 +73,8 @@ msgid ""
72"You have now mastered the edge gestures and can start using the "
73"You have now mastered the edge gestures and can start using the "
73"phone<br><br>Tap on the screen to start"
74"phone<br><br>Tap on the screen to start"
74msgstr ""
75msgstr ""
76+"ئېكراننى چېكىپ باشلاڭ<br><br>سىز ھازىر گىرۋەك بارماق ئىشارەتلىرىنى ئىگەللەپ "
77+"بولدىڭىز،ئەمدى تېلېفوننى ئىشلىتىشنى باشلىسىڭىز بولىدۇ"
75
78
76#: qml/Components/PageHeader.qml:339
79#: qml/Components/PageHeader.qml:339
77msgid "Recent searches"
80msgid "Recent searches"
@@ -116,7 +119,7 @@ msgstr "ئەۋەت"
116
119
117#: qml/Dash/Previews/Reviews.qml:139
120#: qml/Dash/Previews/Reviews.qml:139
118msgid "Comments:"
121msgid "Comments:"
119−msgstr ":ئىنكاس"
122+msgstr "ئىنكاس:"
120
123
121#: qml/Greeter/Lockscreen.qml:149
124#: qml/Greeter/Lockscreen.qml:149
122msgid "Emergency Call"
125msgid "Emergency Call"
@@ -141,15 +144,15 @@ msgstr "بۇيرۇق كىرگۈزۈڭ ياكى دەڭ"
141
144
142#: qml/Hud/Hud.qml:84
145#: qml/Hud/Hud.qml:84
143msgid "Loading. Please Wait..."
146msgid "Loading. Please Wait..."
144−msgstr "…ئوقۇۋاتىدۇ، سەل كۈتۈڭ"
147+msgstr "ئوقۇۋاتىدۇ، سەل كۈتۈڭ…"
145
148
146#: qml/Hud/Hud.qml:89
149#: qml/Hud/Hud.qml:89
147msgid "Speak Now..."
150msgid "Speak Now..."
148−msgstr "…ئەمدى سۆزلەڭ"
151+msgstr "ئەمدى سۆزلەڭ…"
149
152
150#: qml/Hud/Hud.qml:94
153#: qml/Hud/Hud.qml:94
151msgid "Speaking..."
154msgid "Speaking..."
152−msgstr "…سۆزلەۋاتىسىز"
155+msgstr "سۆزلەۋاتىسىز…"
153
156
154#: qml/Notifications/NotificationMenuItemFactory.qml:91
157#: qml/Notifications/NotificationMenuItemFactory.qml:91
155msgid "Show password"
158msgid "Show password"
po/unity8.pot+18−10
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2014-02-04 15:43+0000\n"
11+"POT-Creation-Date: 2014-02-13 18:37+0000\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -73,19 +73,19 @@ msgid ""
73"phone<br><br>Tap on the screen to start"
73"phone<br><br>Tap on the screen to start"
74msgstr ""
74msgstr ""
75
75
76−#: qml/Components/PageHeader.qml:339
76+#: qml/Components/PageHeader.qml:340
77msgid "Recent searches"
77msgid "Recent searches"
78msgstr ""
78msgstr ""
79
79
80−#: qml/Components/SeeMore.qml:32
80+#: qml/Components/SeeMore.qml:35
81msgid "See more"
81msgid "See more"
82msgstr ""
82msgstr ""
83
83
84−#: qml/Components/SeeMore.qml:61
84+#: qml/Components/SeeMore.qml:57
85msgid "See less"
85msgid "See less"
86msgstr ""
86msgstr ""
87
87
88−#: qml/Dash/Apps/AppPreview.qml:136
88+#: qml/Dash/Apps/AppPreview.qml:136 qml/Dash/Previews/PreviewRating.qml:70
89msgid "Rate this"
89msgid "Rate this"
90msgstr ""
90msgstr ""
91
91
@@ -103,18 +103,26 @@ msgid_plural "%1 reviews"
103msgstr[0] ""
103msgstr[0] ""
104msgstr[1] ""
104msgstr[1] ""
105
105
106−#: qml/Dash/Previews/Reviews.qml:74
106+#: qml/Dash/Previews/PreviewActionCombo.qml:34
107−msgid "Add a review"
107+msgid "More..."
108msgstr ""
108msgstr ""
109
109
110−#: qml/Dash/Previews/Reviews.qml:86
110+#: qml/Dash/Previews/PreviewActionCombo.qml:34
111−msgid "Review"
111+msgid "Less..."
112+msgstr ""
113+
114+#: qml/Dash/Previews/PreviewRating.qml:114 qml/Dash/Previews/Reviews.qml:74
115+msgid "Add a review"
112msgstr ""
116msgstr ""
113
117
114−#: qml/Dash/Previews/Reviews.qml:121
118+#: qml/Dash/Previews/PreviewRating.qml:153 qml/Dash/Previews/Reviews.qml:121
115msgid "Send"
119msgid "Send"
116msgstr ""
120msgstr ""
117
121
122+#: qml/Dash/Previews/Reviews.qml:86
123+msgid "Review"
124+msgstr ""
125+
118#: qml/Dash/Previews/Reviews.qml:139
126#: qml/Dash/Previews/Reviews.qml:139
119msgid "Comments:"
127msgid "Comments:"
120msgstr ""
128msgstr ""
qml/Components/Rating.qmlnew file+48
@@ -0,0 +1,48 @@
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+/*! Rating widget bar. */
21+
22+StyledItem {
23+ id: root
24+
25+ //! True if it accepts user input.
26+ property bool interactive: true
27+
28+ //! Maximum rating.
29+ property real maximumValue: 5
30+
31+ //! Number of rating icons.
32+ property int size: 5
33+
34+ //! Current rating.
35+ property real value: -1
36+
37+ readonly property real effectiveValue: MathUtils.clamp(size * value / maximumValue, 0, maximumValue)
38+
39+ style: RatingStyle {}
40+
41+ MouseArea {
42+ anchors.fill: parent
43+ enabled: root.interactive
44+ onClicked: root.value = Math.ceil(mouse.x / averageIconWidth) * root.maximumValue / root.size
45+
46+ readonly property int averageIconWidth: width / root.size
47+ }
48+}
qml/Components/RatingStyle.qmlnew file+47
@@ -0,0 +1,47 @@
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+Row {
21+ anchors.fill: parent
22+
23+ Repeater {
24+ id: repeater
25+ model: styledItem.size
26+
27+ property int indexHalfValue: {
28+ var integerPart = Math.floor(styledItem.effectiveValue);
29+ var fractionalPart = styledItem.effectiveValue - integerPart;
30+
31+ if (fractionalPart < 0.5) return -1;
32+ else return integerPart;
33+ }
34+ property url urlIconEmpty: styledItem.urlIconEmpty || "graphics/icon_star_empty.png"
35+ property url urlIconFull: styledItem.urlIconFull || "graphics/icon_star_full.png"
36+ property url urlIconHalf: styledItem.urlIconHalf || "graphics/icon_star_half.png"
37+
38+ Image {
39+ opacity: styledItem.value < 0 ? 0.4 : 1 // Let's make the stars look inactive for a not-set value
40+ source: {
41+ if (index === repeater.indexHalfValue) return repeater.urlIconHalf;
42+ else if (index < styledItem.effectiveValue) return repeater.urlIconFull;
43+ else return repeater.urlIconEmpty;
44+ }
45+ }
46+ }
47+}
qml/Components/graphics/icon_star_empty@20.pngnew file

Binary file not shown.

qml/Components/graphics/icon_star_full@20.pngnew file

Binary file not shown.

qml/Components/graphics/icon_star_half@20.pngnew file

Binary file not shown.

qml/Dash/Previews/PreviewRating.qmlnew file+173
@@ -0,0 +1,173 @@
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+import "../../Components"
20+
21+/*! \brief Preview widget for rating.
22+
23+ The widget can show a rating widget and a field to enter a comment.
24+ The visibility of the two widgets is specified by widgetData["visible"],
25+ accepting "both", "rating" or "review".
26+ The requirement of the review is specified by widgetData["visible"],
27+ accepting "both", "rating" or "review".
28+ It is possible to customise labels, widgetData["rating-label"] for the rating,
29+ widgetData["rewiew-label"] for the comment field and widgetData["submit-label"]
30+ for the submit button.
31+ The icons used in the rating widget can be customised with
32+ widgetData["rating-icon-empty"] and widgetData["rating-icon-full"].
33+ The successeful submit emits triggered(widgetId, widgetData["required"], data),
34+ with data being {"rating": rating value, "review": review comment, "author": null (for now)}.
35+*/
36+
37+PreviewWidget {
38+ id: root
39+ implicitHeight: {
40+ switch(widgetData["visible"]) {
41+ default:
42+ case "both":
43+ return ratingLabelAndWidgetContainer.implicitHeight + reviewContainer.implicitHeight;
44+ case "rating":
45+ return ratingLabelAndWidgetContainer.implicitHeight;
46+ case "review":
47+ return reviewContainer.implicitHeight;
48+ }
49+ }
50+
51+ function submit() {
52+ // checks rating-input requirements
53+ if (((widgetData["required"] === "both" ||
54+ widgetData["required"] === "rating") &&
55+ rating.value < 0) ||
56+ ((widgetData["required"] === "both" ||
57+ widgetData["required"] === "review") &&
58+ reviewTextArea.text === "")) return;
59+
60+ var data = {"rating": rating.value, "review": reviewTextArea.text, "author": null};
61+ triggered(root.widgetId, widgetData["required"], data);
62+ }
63+
64+ Item {
65+ id: ratingLabelAndWidgetContainer
66+ anchors {
67+ left: parent.left
68+ right: parent.right
69+ }
70+ implicitHeight: rating.height
71+ visible: widgetData["visible"] !== "review"
72+
73+ Label {
74+ objectName: "ratingLabel"
75+ anchors {
76+ verticalCenter: parent.verticalCenter
77+ left: parent.left
78+ }
79+ color: Theme.palette.selected.backgroundText
80+ opacity: .8
81+ text: widgetData["rating-label"] || i18n.tr("Rate this")
82+ }
83+
84+ Rating {
85+ id: rating
86+ objectName: "rating"
87+ anchors {
88+ verticalCenter: parent.verticalCenter
89+ right: parent.right
90+ }
91+ size: 5
92+ onValueChanged: {
93+ if (widgetData["visible"] === "rating") root.submit();
94+ }
95+
96+ property var urlIconEmpty: widgetData["rating-icon-empty"]
97+ property var urlIconFull: widgetData["rating-icon-full"]
98+ }
99+ }
100+
101+ Item {
102+ id: reviewContainer
103+ implicitHeight: reviewLabel.implicitHeight + reviewSubmitContainer.implicitHeight + anchors.topMargin
104+
105+ readonly property real innerMargin: units.gu(1)
106+
107+ anchors {
108+ left: parent.left
109+ right: parent.right
110+ top: ratingLabelAndWidgetContainer.visible ? ratingLabelAndWidgetContainer.bottom : parent.top
111+ bottom: parent.bottom
112+ topMargin: ratingLabelAndWidgetContainer.visible ? reviewContainer.innerMargin : 0
113+ }
114+ visible: widgetData["visible"] !== "rating"
115+
116+ Label {
117+ objectName: "reviewLabel"
118+ id: reviewLabel
119+ anchors {
120+ top: parent.top
121+ left: parent.left
122+ right: parent.right
123+ }
124+ color: Theme.palette.selected.backgroundText
125+ opacity: .8
126+ text: widgetData["review-label"] || i18n.tr("Add a review")
127+ }
128+
129+ Item {
130+ id: reviewSubmitContainer
131+ anchors {
132+ top: reviewLabel.bottom
133+ left: parent.left
134+ right: parent.right
135+ bottom: parent.bottom
136+ topMargin: reviewContainer.innerMargin
137+ }
138+ implicitHeight: reviewTextArea.implicitHeight + anchors.topMargin
139+
140+ TextArea {
141+ id: reviewTextArea
142+ objectName: "reviewTextArea"
143+ anchors {
144+ top: parent.top
145+ left: parent.left
146+ right: submitButton.left
147+ rightMargin: reviewContainer.innerMargin
148+ }
149+ }
150+
151+ Button {
152+ id: submitButton
153+ objectName: "submitButton"
154+
155+ readonly property bool readyToSubmit: {
156+ if (reviewTextArea.text === "" ||
157+ (widgetData["visible"] === "both" && rating.value < 0)) return false;
158+ else return true;
159+ }
160+
161+ anchors {
162+ top: parent.top
163+ right: parent.right
164+ }
165+ color: readyToSubmit ? Theme.palette.selected.base : Theme.palette.normal.base
166+ text: widgetData["submit-label"] || i18n.tr("Send")
167+ onClicked: {
168+ if (readyToSubmit) root.submit()
169+ }
170+ }
171+ }
172+ }
173+}
qml/Dash/Previews/PreviewWidget.qml+1−1
@@ -30,7 +30,7 @@ Item {
30
30
31 /*! \brief This signal should be emitted when a preview action was triggered.
31 /*! \brief This signal should be emitted when a preview action was triggered.
32 *
32 *
33− * \param widgetId,actionId Respective identifiers from widgetData.
33+ * \param widgetId, actionId Respective identifiers from widgetData.
34 * \param data Optional widget-specific data sent to the scope.
34 * \param data Optional widget-specific data sent to the scope.
35 */
35 */
36 signal triggered(string widgetId, string actionId, var data)
36 signal triggered(string widgetId, string actionId, var data)
qml/Dash/Previews/PreviewWidgetFactory.qml+1
@@ -48,6 +48,7 @@ Loader {
48 case "header": return "PreviewHeader.qml";
48 case "header": return "PreviewHeader.qml";
49 case "image": return "PreviewZoomableImage.qml";
49 case "image": return "PreviewZoomableImage.qml";
50 case "progress": return "PreviewProgress.qml";
50 case "progress": return "PreviewProgress.qml";
51+ case "rating-input": return "PreviewRating.qml";
51 case "text": return "PreviewTextSummary.qml";
52 case "text": return "PreviewTextSummary.qml";
52 case "video": return "PreviewVideoPlayback.qml";
53 case "video": return "PreviewVideoPlayback.qml";
53 default: return "";
54 default: return "";
tests/autopilot/unity8/shell/__init__.py+11−2
@@ -50,13 +50,22 @@ def disable_qml_mocking(fn):
50
50
51class DragMixin(object):
51class DragMixin(object):
52 def _drag(self, x1, y1, x2, y2):
52 def _drag(self, x1, y1, x2, y2):
53+ # XXX This ugly code is here just temporarily, waiting for drag
54+ # improvements to land on autopilot so we don't have to access device
55+ # private internal attributes. --elopio - 2014-02-12
53 cur_x = x1
56 cur_x = x1
54 cur_y = y1
57 cur_y = y1
55 dx = 1.0 * (x2 - x1) / 100
58 dx = 1.0 * (x2 - x1) / 100
56 dy = 1.0 * (y2 - y1) / 100
59 dy = 1.0 * (y2 - y1) / 100
57 for i in range(0, 100):
60 for i in range(0, 100):
61+ try:
58− self.touch._finger_move(int(cur_x), int(cur_y))
62+ self.touch._finger_move(int(cur_x), int(cur_y))
63+ except AttributeError:
64+ self.touch._device.finger_move(int(cur_x), int(cur_y))
59 sleep(0.002)
65 sleep(0.002)
60 cur_x += dx
66 cur_x += dx
61 cur_y += dy
67 cur_y += dy
68+ try:
62− self.touch._finger_move(int(x2), int(y2))
69+ self.touch._finger_move(int(x2), int(y2))
70+ except AttributeError:
71+ self.touch._device.finger_move(int(x2), int(y2))
tests/autopilot/unity8/shell/emulators/hud.py+8−1
@@ -54,7 +54,14 @@ class Hud(UnityEmulatorBase, DragMixin):
54 except AssertionError:
54 except AssertionError:
55 raise
55 raise
56 finally:
56 finally:
57+ # XXX This ugly code is here just temporarily, waiting for uinput
58+ # improvements to land on autopilot so we don't have to access
59+ # device private internal attributes. --elopio - 2014-02-12
60+ try:
57− if self.touch._touch_finger is not None:
61+ pressed = self.touch._touch_finger is not None
62+ except AttributeError:
63+ pressed = self.touch.pressed
64+ if pressed:
58 self.touch.release()
65 self.touch.release()
59
66
60 def dismiss(self):
67 def dismiss(self):
tests/autopilot/unity8/shell/tests/test_hud.py+8−1
@@ -184,5 +184,12 @@ class TestHud(UnityTestCase, DragMixin):
184 # we don't.
184 # we don't.
185 def _maybe_release_finger(self):
185 def _maybe_release_finger(self):
186 """Only release the finger if it is in fact down."""
186 """Only release the finger if it is in fact down."""
187+ # XXX This ugly code is here just temporarily, waiting for uinput
188+ # improvements to land on autopilot so we don't have to access device
189+ # private internal attributes. --elopio - 2014-02-12
190+ try:
187− if self.touch._touch_finger is not None:
191+ pressed = self.touch._touch_finger is not None
192+ except AttributeError:
193+ pressed = self.touch.pressed
194+ if pressed:
188 self.touch.release()
195 self.touch.release()
tests/qmltests/CMakeLists.txt+4−2
@@ -29,6 +29,7 @@ add_qml_test(Components DraggingArea)
29add_qml_test(Components EdgeDemoOverlay)
29add_qml_test(Components EdgeDemoOverlay)
30add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
30add_qml_test(Components FilterGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins)
31add_qml_test(Components LazyImage)
31add_qml_test(Components LazyImage)
32+add_qml_test(Components Rating)
32add_qml_test(Components ResponsiveFlowView)
33add_qml_test(Components ResponsiveFlowView)
33add_qml_test(Components ResponsiveGridView)
34add_qml_test(Components ResponsiveGridView)
34add_qml_test(Components Revealer)
35add_qml_test(Components Revealer)
@@ -56,14 +57,15 @@ add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} $
56add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
57add_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)
58add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
58add_qml_test(Dash/Previews Preview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
59add_qml_test(Dash/Previews Preview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
59−add_qml_test(Dash/Previews PreviewWidgetFactory IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
60add_qml_test(Dash/Previews PreviewActions IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
60add_qml_test(Dash/Previews PreviewActions IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
61add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
61add_qml_test(Dash/Previews PreviewAudioPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
62−add_qml_test(Dash/Previews PreviewImageGallery IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
63add_qml_test(Dash/Previews PreviewHeader IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
62add_qml_test(Dash/Previews PreviewHeader IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
63+add_qml_test(Dash/Previews PreviewImageGallery IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
64add_qml_test(Dash/Previews PreviewProgress IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
64add_qml_test(Dash/Previews PreviewProgress IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
65+add_qml_test(Dash/Previews PreviewRating IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
65add_qml_test(Dash/Previews PreviewTextSummary IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
66add_qml_test(Dash/Previews PreviewTextSummary IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
66add_qml_test(Dash/Previews PreviewVideoPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
67add_qml_test(Dash/Previews PreviewVideoPlayback IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
68+add_qml_test(Dash/Previews PreviewWidgetFactory IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
67add_qml_test(Dash/Previews PreviewZoomableImage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
69add_qml_test(Dash/Previews PreviewZoomableImage IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
68add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
70add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
69 PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
71 PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
tests/qmltests/Components/tst_DragHandle.cpp+45−5
@@ -58,7 +58,9 @@ private Q_SLOTS:
58 void cleanup(); // called right after each and every test function is executed
58 void cleanup(); // called right after each and every test function is executed
59
59
60 void dragThreshold_horizontal();
60 void dragThreshold_horizontal();
61+ void dragThreshold_horizontal_data();
61 void dragThreshold_vertical();
62 void dragThreshold_vertical();
63+ void dragThreshold_vertical_data();
62 void stretch_horizontal();
64 void stretch_horizontal();
63 void stretch_vertical();
65 void stretch_vertical();
64 void hintingAnimation();
66 void hintingAnimation();
@@ -145,17 +147,29 @@ void tst_DragHandle::tryCompare(std::function<qreal ()> actualFunc,
145namespace {
147namespace {
146QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea)
148QPointF calculateDirectionVector(DirectionalDragArea *edgeDragArea)
147{
149{
148−
150+ QPointF localOrigin(0., 0.);
151+ QPointF localDirection;
149 switch (edgeDragArea->direction()) {
152 switch (edgeDragArea->direction()) {
150 case Direction::Upwards:
153 case Direction::Upwards:
151− return QPointF(0, -1);
154+ localDirection.rx() = 0.;
155+ localDirection.ry() = -1.;
156+ break;
152 case Direction::Downwards:
157 case Direction::Downwards:
153− return QPointF(0, 1);
158+ localDirection.rx() = 0.;
159+ localDirection.ry() = 1;
160+ break;
154 case Direction::Leftwards:
161 case Direction::Leftwards:
155− return QPointF(-1, 0);
162+ localDirection.rx() = -1.;
163+ localDirection.ry() = 0.;
164+ break;
156 default: // Direction::Rightwards:
165 default: // Direction::Rightwards:
157− return QPointF(1, 0);
166+ localDirection.rx() = 1.;
167+ localDirection.ry() = 0.;
168+ break;
158 }
169 }
170+ QPointF sceneOrigin = edgeDragArea->mapToScene(localOrigin);
171+ QPointF sceneDirection = edgeDragArea->mapToScene(localDirection);
172+ return sceneDirection - sceneOrigin;
159}
173}
160}
174}
161
175
@@ -222,6 +236,11 @@ qreal tst_DragHandle::fetchDragThreshold(DirectionalDragArea *dragHandle)
222 */
236 */
223void tst_DragHandle::dragThreshold_horizontal()
237void tst_DragHandle::dragThreshold_horizontal()
224{
238{
239+ QFETCH(qreal, rotation);
240+
241+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
242+ baseItem->setRotation(rotation);
243+
225 DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
244 DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("rightwardsDragHandle");
226
245
227 qreal dragThreshold = fetchDragThreshold(dragHandle);
246 qreal dragThreshold = fetchDragThreshold(dragHandle);
@@ -260,8 +279,21 @@ void tst_DragHandle::dragThreshold_horizontal()
260 QCOMPARE(parentItem->property("shown").toBool(), false);
279 QCOMPARE(parentItem->property("shown").toBool(), false);
261}
280}
262
281
282+void tst_DragHandle::dragThreshold_horizontal_data()
283+{
284+ QTest::addColumn<qreal>("rotation");
285+
286+ QTest::newRow("not rotated") << 0.;
287+ QTest::newRow("rotated 90") << 90.;
288+}
289+
263void tst_DragHandle::dragThreshold_vertical()
290void tst_DragHandle::dragThreshold_vertical()
264{
291{
292+ QFETCH(qreal, rotation);
293+
294+ QQuickItem *baseItem = m_view->rootObject()->findChild<QQuickItem*>("baseItem");
295+ baseItem->setRotation(rotation);
296+
265 DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
297 DirectionalDragArea *dragHandle = fetchAndSetupDragHandle("downwardsDragHandle");
266
298
267 qreal dragThreshold = fetchDragThreshold(dragHandle);
299 qreal dragThreshold = fetchDragThreshold(dragHandle);
@@ -300,6 +332,14 @@ void tst_DragHandle::dragThreshold_vertical()
300 QCOMPARE(parentItem->property("shown").toBool(), false);
332 QCOMPARE(parentItem->property("shown").toBool(), false);
301}
333}
302
334
335+void tst_DragHandle::dragThreshold_vertical_data()
336+{
337+ QTest::addColumn<qreal>("rotation");
338+
339+ QTest::newRow("not rotated") << 0.;
340+ QTest::newRow("rotated 90") << 90.;
341+}
342+
303/*
343/*
304 Checks that when the stretch property is true, dragging the DragHandle increases
344 Checks that when the stretch property is true, dragging the DragHandle increases
305 the width or height (depending on its direction) of its parent Showable
345 the width or height (depending on its direction) of its parent Showable
tests/qmltests/Components/tst_DragHandle.qml+1
@@ -39,6 +39,7 @@ Item {
39
39
40 Item {
40 Item {
41 id: baseItem
41 id: baseItem
42+ objectName: "baseItem"
42 anchors.fill: parent
43 anchors.fill: parent
43
44
44 VerticalShowable {
45 VerticalShowable {
tests/qmltests/Components/tst_Rating.qmlnew file+86
@@ -0,0 +1,86 @@
1+/*
2+ * Copyright 2013 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/Components"
20+import Ubuntu.Components 0.1
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(10)
27+ color: Theme.palette.selected.background
28+
29+ Rating {
30+ id: rating
31+ anchors.centerIn: parent
32+ maximumValue: 5
33+ size: 5
34+ value: 3
35+ }
36+
37+ UT.UnityTestCase {
38+ name: "RatingTest"
39+ when: windowShown
40+
41+ function init() {
42+ rating.maximumValue = 5;
43+ rating.size = 5
44+ rating.value = 3;
45+ }
46+
47+ function test_interactive_rating_data() {
48+ return [
49+ {tag: "1st icon without interactive", interactive: false, size: 5, maximumValue: 5, index: 0, value: 3},
50+ {tag: "1st icon", interactive: true, size: 5, maximumValue: 5, index: 0, value: 1},
51+ {tag: "1st icon size 10", interactive: true, size: 10, maximumValue: 10, index: 0, value: 1},
52+ {tag: "3rd icon size 10 small maximumValue", interactive: true, size: 10, maximumValue: 5, index: 2, value: 1.5},
53+ {tag: "2nd icon with big maximumValue", interactive: true, size: 5, maximumValue: 100, index: 1, value: 40},
54+ {tag: "last icon", interactive: true, size: 5, maximumValue: 5, index: 4, value: 5},
55+ ];
56+ }
57+
58+ function test_interactive_rating(data) {
59+ rating.interactive = data.interactive;
60+ rating.maximumValue = data.maximumValue;
61+ rating.size = data.size;
62+
63+ var averageIconWidth = rating.width / rating.size;
64+ mouseClick(rating, averageIconWidth * data.index + averageIconWidth / 2, rating.height / 2);
65+ compare(rating.value, data.value);
66+
67+ rating.interactive = false;
68+ }
69+
70+ function test_effectiveValue_data() {
71+ return [
72+ {tag: "negative", value: -3, expectedValue: 0},
73+ {tag: "ranged value", value: 2, expectedValue: 2},
74+ {tag: "big", value: 200, expectedValue: rating.maximumValue},
75+ {tag: "min", value: 0, expectedValue: 0},
76+ {tag: "max", value: rating.maximumValue, expectedValue: rating.maximumValue},
77+ {tag: "half", value: 2.5, expectedValue: 2.5}
78+ ];
79+ }
80+
81+ function test_effectiveValue(data) {
82+ rating.value = data.value;
83+ compare(rating.effectiveValue, data.expectedValue, "effectiveValue not calculated correctly")
84+ }
85+ }
86+}
tests/qmltests/Dash/Previews/tst_PreviewRating.qmlnew file+183
@@ -0,0 +1,183 @@
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 Ubuntu.Components 0.1
20+import "../../../../qml/Dash/Previews"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+ color: Theme.palette.selected.background
28+
29+ property real validInputRating: 1
30+ property real invalidInputRating: -1
31+ property string validInputText: "Great!"
32+ property string invalidInputText: ""
33+
34+ property var triggeredDataBoth: { "rating": validInputRating, "review": validInputText, "author": null }
35+ property var triggeredDataRatingOnly: { "rating": validInputRating, "review": invalidInputText, "author": null }
36+ property var triggeredDataReviewOnly: { "rating": invalidInputRating, "review": validInputText, "author": null }
37+
38+ property var widgetDataBoth: { "visible": "both", "required": "both" }
39+ property var widgetDataRating: { "visible": "rating", "required": "rating" }
40+ property var widgetDataRatingBroken: { "visible": "rating", "required": "review" }
41+ property var widgetDataReview: { "visible": "review", "required": "review" }
42+ property var widgetDataReviewBroken: { "visible": "review", "required": "rating" }
43+
44+ property var widgetDataNewLabels: { "visible": "both", "required": "both", "rating-label": "TestRatingLabel", "review-label": "TestReviewLabel", "submit-label": "TestSubmitLabel" }
45+
46+ PreviewRating {
47+ id: previewRating
48+ anchors.left: parent.left
49+ anchors.right: parent.right
50+ widgetData: widgetDataBoth
51+ widgetId: "previewRating"
52+ }
53+
54+ SignalSpy {
55+ id: spy
56+ signalName: "triggered"
57+ }
58+
59+ UT.UnityTestCase {
60+ name: "PreviewRatingTest"
61+ when: windowShown
62+
63+ property var rating: findChild(previewRating, "rating")
64+ property var reviewTextArea: findChild(previewRating, "reviewTextArea")
65+ property var submitButton: findChild(previewRating, "submitButton")
66+
67+ function init() {
68+ rating.value = -1;
69+ reviewTextArea.text = "";
70+ }
71+
72+ function test_labels() {
73+ var ratingLabel = findChild(previewRating, "ratingLabel");
74+ var reviewLabel = findChild(previewRating, "reviewLabel");
75+
76+ previewRating.widgetData = widgetDataNewLabels;
77+ compare(ratingLabel.text, widgetDataNewLabels["rating-label"]);
78+ compare(reviewLabel.text, widgetDataNewLabels["review-label"]);
79+ compare(submitButton.text, widgetDataNewLabels["submit-label"]);
80+ }
81+
82+ function test_submit_and_visibility_data() {
83+ return [
84+ {tag: "both, null review", widgetData: widgetDataBoth, inputRating: invalidInputRating, inputText: invalidInputText, emitted: false},
85+ {tag: "both, rating-only review", widgetData: widgetDataBoth, inputRating: validInputRating, inputText: invalidInputText, emitted: false},
86+ {tag: "both, review-only review", widgetData: widgetDataBoth, inputRating: invalidInputRating, inputText: validInputText, emitted: false},
87+ {tag: "both, complete review", widgetData: widgetDataBoth, inputRating: validInputRating, inputText: validInputText, emitted: true},
88+ {tag: "rating, null review", widgetData: widgetDataRating, inputRating: invalidInputRating, inputText: invalidInputText, emitted: false},
89+ {tag: "rating, rating-only review", widgetData: widgetDataRating, inputRating: validInputRating, inputText: invalidInputText, emitted: true},
90+ {tag: "rating, review-only review", widgetData: widgetDataRating, inputRating: invalidInputRating, inputText: validInputText, emitted: false},
91+ {tag: "rating, complete review", widgetData: widgetDataRating, inputRating: validInputRating, inputText: validInputText, emitted: true},
92+ {tag: "rating broken, null review", widgetData: widgetDataRatingBroken, inputRating: invalidInputRating, inputText: invalidInputText, emitted: false},
93+ {tag: "rating broken, rating-only review", widgetData: widgetDataRatingBroken, inputRating: validInputRating, inputText: invalidInputText, emitted: false},
94+ {tag: "rating broken, review-only review", widgetData: widgetDataRatingBroken, inputRating: invalidInputRating, inputText: validInputText, emitted: false},
95+ {tag: "rating broken, complete review", widgetData: widgetDataRatingBroken, inputRating: validInputRating, inputText: validInputText, emitted: false},
96+ {tag: "review, null review", widgetData: widgetDataReview, inputRating: invalidInputRating, inputText: invalidInputText, emitted: false},
97+ {tag: "review, rating-only review", widgetData: widgetDataReview, inputRating: validInputRating, inputText: invalidInputText, emitted: false},
98+ {tag: "review, review-only review", widgetData: widgetDataReview, inputRating: invalidInputRating, inputText: validInputText, emitted: true},
99+ {tag: "review, complete review", widgetData: widgetDataReview, inputRating: validInputRating, inputText: validInputText, emitted: true},
100+ {tag: "review broken, null review", widgetData: widgetDataReviewBroken, inputRating: invalidInputRating, inputText: invalidInputText, emitted: false},
101+ {tag: "review broken, rating-only review", widgetData: widgetDataReviewBroken, inputRating: validInputRating, inputText: invalidInputText, emitted: false},
102+ {tag: "review broken, review-only review", widgetData: widgetDataReviewBroken, inputRating: invalidInputRating, inputText: validInputText, emitted: false},
103+ {tag: "review broken, complete review", widgetData: widgetDataReviewBroken, inputRating: validInputRating, inputText: validInputText, emitted: false},
104+ ];
105+ }
106+
107+ function test_submit_and_visibility(data) {
108+ spy.clear();
109+ spy.target = previewRating;
110+
111+ previewRating.widgetData = data.widgetData;
112+
113+ if (data.widgetData["visible"] !== "review") {
114+ verify(rating.visible === true);
115+
116+ rating.value = data.inputRating;
117+ if (data.widgetData["required"] !== "rating" || data.inputRating < 0) {
118+ compare(spy.count, 0);
119+ } else {
120+ compare(spy.count, 1);
121+ }
122+ } else {
123+ verify(rating.visible === false);
124+ }
125+
126+ if (data.widgetData["visible"] !== "rating") {
127+ verify(reviewTextArea.visible === true);
128+
129+ reviewTextArea.text = data.inputText;
130+ mouseClick(submitButton, submitButton.width / 2, submitButton.height / 2);
131+ switch (data.widgetData["required"]) {
132+ case "rating": compare(spy.count, 0); break;
133+ case "both":
134+ default: {
135+ if (data.inputRating < 0 || data.inputText === "") {
136+ compare(spy.count, 0); break;
137+ }
138+ }
139+ case "review": {
140+ if (data.inputText === "") {
141+ compare(spy.count, 0); break;
142+ } else {
143+ compare(spy.count, 1); break;
144+ }
145+ }
146+ }
147+ } else {
148+ verify(reviewTextArea.visible === false);
149+ }
150+
151+ compare(spy.count === 1, data.emitted);
152+ }
153+
154+ function test_triggered_data() {
155+ return [
156+ {tag: "complete review", widgetData: widgetDataBoth, inputRating: validInputRating, inputText: validInputText, triggeredData: triggeredDataBoth},
157+ {tag: "rating-only review", widgetData: widgetDataRating, inputRating: validInputRating, inputText: invalidInputText, triggeredData: triggeredDataRatingOnly},
158+ {tag: "review-only review", widgetData: widgetDataReview, inputRating: invalidInputRating, inputText: validInputText, triggeredData: triggeredDataReviewOnly}
159+ ];
160+ }
161+
162+ function test_triggered(data) {
163+ spy.clear();
164+ spy.target = previewRating;
165+
166+ previewRating.widgetData = data.widgetData;
167+
168+ if (data.inputRating > 0) rating.value = data.inputRating;
169+ if (data.inputText !== "") {
170+ reviewTextArea.text = data.inputText;
171+ mouseClick(submitButton, submitButton.width / 2, submitButton.height / 2);
172+ }
173+
174+ compare(spy.count, 1);
175+ var args = spy.signalArguments[0];
176+ compare(args[0], previewRating.widgetId);
177+ compare(args[1], data.widgetData["required"]);
178+ compare(args[2]["rating"], data.triggeredData["rating"]);
179+ compare(args[2]["review"], data.triggeredData["review"]);
180+ verify(args[2]["author"]); // Just verifying it exists now
181+ }
182+ }
183+}
tests/qmltests/Dash/Previews/tst_PreviewWidgetFactory.qml+1
@@ -81,6 +81,7 @@ Rectangle {
81 { tag: "Header", type: "header", source: "PreviewHeader.qml" },
81 { tag: "Header", type: "header", source: "PreviewHeader.qml" },
82 { tag: "Image", type: "image", source: "PreviewZoomableImage.qml" },
82 { tag: "Image", type: "image", source: "PreviewZoomableImage.qml" },
83 { tag: "Progress", type: "progress", source: "PreviewProgress.qml" },
83 { tag: "Progress", type: "progress", source: "PreviewProgress.qml" },
84+ { tag: "Rating Input", type: "rating-input", source: "PreviewRating.qml" },
84 { tag: "Text", type: "text", source: "PreviewTextSummary.qml" },
85 { tag: "Text", type: "text", source: "PreviewTextSummary.qml" },
85 { tag: "Video", type: "video", source: "PreviewVideoPlayback.qml" },
86 { tag: "Video", type: "video", source: "PreviewVideoPlayback.qml" },
86 ];
87 ];