on xenial help sign in
more cleanups in Previews
4564d3dMichael Zanetti
Dash/Apps/AppPreview.qml+52−100
@@ -19,45 +19,56 @@ import Ubuntu.Components 0.1
19import Ubuntu.Components.ListItems 0.1 as ListItem
19import Ubuntu.Components.ListItems 0.1 as ListItem
20import Ubuntu.DownloadDaemonListener 0.1
20import Ubuntu.DownloadDaemonListener 0.1
21import ".."
21import ".."
22+import "../Generic"
23+import "../Previews"
22import "../../Components"
24import "../../Components"
23
25
24−DashPreview {
26+GenericPreview {
25 id: root
27 id: root
26
28
27 signal sendUserReview(string review)
29 signal sendUserReview(string review)
28
30
29− previewImages: ListView {
31+ previewImages: previewImagesComponent
32+ actions: root.previewData.infoMap["show_progressbar"] ? progressComponent : buttonsComponent
33+ description: descriptionComponent
34+ header: headerComponent
35+
36+ Component {
37+ id: previewImagesComponent
38+ ListView {
30− spacing: units.gu(1)
39+ spacing: units.gu(1)
31− orientation: ListView.Horizontal
40+ orientation: ListView.Horizontal
32− height: units.gu(22)
41+ height: units.gu(22)
33− model: previewData.infoMap["more-screenshots"] != null ? previewData.infoMap["more-screenshots"].value : [previewData.image]
42+ model: previewData.infoMap["more-screenshots"] != null ? previewData.infoMap["more-screenshots"].value : [previewData.image]
34−
43+
35− delegate: UbuntuShape {
44+ delegate: UbuntuShape {
36− id: shape
45+ id: shape
37− anchors {
46+ anchors {
38− top: parent.top
47+ top: parent.top
39− bottom: parent.bottom
48+ bottom: parent.bottom
40− }
49+ }
41− width: units.gu(12)
50+ width: units.gu(12)
42− radius: "medium"
51+ radius: "medium"
43− borderSource: ""
52+ borderSource: ""
44− image: Image {
53+ image: Image {
45− asynchronous: true
54+ asynchronous: true
46− sourceSize { width: shape.width; height: shape.height }
55+ sourceSize { width: shape.width; height: shape.height }
47− source: modelData ? modelData : ""
56+ source: modelData ? modelData : ""
48− fillMode: Image.PreserveAspectCrop
57+ fillMode: Image.PreserveAspectCrop
58+ }
49 }
59 }
50 }
60 }
51 }
61 }
52
62
53− header: AppInfo {
63+ Component {
54− objectName: "appInfo"
64+ id: headerComponent
55−
65+ PreviewHeader {
56− appName: root.previewData.title
66+ title: previewData.title
57− icon: root.previewData.appIcon
67+ icon: previewData.appIcon
58− rating: Math.round(root.previewData.rating * 10)
68+ rating: Math.round(root.previewData.rating * 10)
59− reviews: root.previewData.numRatings
69+ reviews: root.previewData.numRatings
60− rated: root.previewData.infoMap["rated"] ? root.previewData.infoMap["rated"].value : 0
70+ rated: root.previewData.infoMap["rated"] ? root.previewData.infoMap["rated"].value : 0
71+ }
61 }
72 }
62
73
63 Component {
74 Component {
@@ -67,6 +78,8 @@ DashPreview {
67 id: buttonsGrid
78 id: buttonsGrid
68 objectName: "gridButtons"
79 objectName: "gridButtons"
69
80
81+ model: root.previewData.actions
82+
70 property int numOfRows: (count + 1) / 2
83 property int numOfRows: (count + 1) / 2
71 property int spacing: units.gu(1)
84 property int spacing: units.gu(1)
72 height: Math.max(units.gu(5), units.gu(5)*numOfRows + spacing*(numOfRows - 1))
85 height: Math.max(units.gu(5), units.gu(5)*numOfRows + spacing*(numOfRows - 1))
@@ -99,7 +112,7 @@ DashPreview {
99 maximumValue: 100
112 maximumValue: 100
100 height: units.gu(5)
113 height: units.gu(5)
101
114
102− property var model
115+ property var model: root.previewData.actions
103
116
104 DownloadTracker {
117 DownloadTracker {
105 service: "com.canonical.applications.Downloader"
118 service: "com.canonical.applications.Downloader"
@@ -122,81 +135,20 @@ DashPreview {
122 }
135 }
123 }
136 }
124
137
125− actions: Loader {
138+ Component {
126− anchors {
139+ id: descriptionComponent
127− left: parent.left
128− right: parent.right
129− }
130−
131− sourceComponent: root.previewData.infoMap["show_progressbar"] ? progressComponent : buttonsComponent
132−
133− onLoaded: {
134− item.model = root.previewData.actions;
135− }
136− }
137−
138− description: Column {
140+ Column {
139− spacing: units.gu(1)
140−
141− Label {
142− anchors { left: parent.left; right: parent.right }
143− text: root.previewData.description
144− fontSize: "medium"
145− color: Theme.palette.selected.backgroundText
146− opacity: .6
147− wrapMode: Text.WordWrap
148− style: Text.Raised
149− styleColor: "black"
150− }
151−
152− }
153− ratings: Column {
154− visible: root.previewData.rating >= 0
155− spacing: units.gu(1)
141+ spacing: units.gu(1)
156− height: childrenRect.height
157−
158− ListItem.ThinDivider { }
159−
160− Item {
161− anchors { left: parent.left; right: parent.right }
162− height: rateLabel.height
163
142
164 Label {
143 Label {
165− id: rateLabel
144+ anchors { left: parent.left; right: parent.right }
145+ text: root.previewData.description
166 fontSize: "medium"
146 fontSize: "medium"
167− color: "white"
147+ color: Theme.palette.selected.backgroundText
148+ opacity: .6
149+ wrapMode: Text.WordWrap
168 style: Text.Raised
150 style: Text.Raised
169 styleColor: "black"
151 styleColor: "black"
170− opacity: .9
171− text: i18n.tr("Rate this")
172−
173− anchors.left: parent.left
174− anchors.verticalCenter: parent.verticalCenter
175− }
176−
177− // FIXME these need to be made interactive and connected to the scope
178− RatingStars {
179− anchors.right: parent.right
180− anchors.verticalCenter: parent.verticalCenter
181− }
182− }
183−
184− ListItem.ThinDivider { }
185−
186− AppReviews {
187− id: appReviews
188− objectName: "appReviews"
189− // TODO: This should make this visible when the feature for reviews/comments is complete.
190− visible: false; height: 0
191−
192− anchors { left: parent.left; right: parent.right }
193−
194− model: root.previewData.infoMap["comments"] ? root.previewData.infoMap["comments"].value : undefined
195−
196− onSendReview: root.sendUserReview(review);
197−
198− onEditing: {
199− root.ensureVisible(appReviews.textArea);
200 }
152 }
201 }
153 }
202 }
154 }
Dash/DashPreview.qml+1−4
@@ -35,9 +35,6 @@ Rectangle {
35 readonly property int columnWidth: narrowMode ? contentRow.width : (contentRow.width / 3) - contentRow.spacing
35 readonly property int columnWidth: narrowMode ? contentRow.width : (contentRow.width / 3) - contentRow.spacing
36 readonly property int contentSpacing: units.gu(3)
36 readonly property int contentSpacing: units.gu(3)
37
37
38− signal close()
39− signal previewImageClicked()
40−
41 color: Qt.rgba(0, 0, 0, .3)
38 color: Qt.rgba(0, 0, 0, .3)
42 clip: true
39 clip: true
43
40
@@ -88,7 +85,7 @@ Rectangle {
88 bottom: parent.bottom
85 bottom: parent.bottom
89 }
86 }
90 width: root.columnWidth
87 width: root.columnWidth
91− contentHeight: leftColumn.height
88+ contentHeight: leftColumn.height + root.contentSpacing
92 anchors.bottomMargin: root.keyboardSize
89 anchors.bottomMargin: root.keyboardSize
93 clip: true
90 clip: true
94
91
Dash/Generic/GenericPreview.qml+182−128
@@ -16,154 +16,208 @@
16
16
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19+import Ubuntu.Components.ListItems 0.1 as ListItems
19import "../../Components"
20import "../../Components"
20−import "../../Components/ListItems" as ListItems
21import ".."
21import ".."
22+import "../Previews"
22
23
23DashPreview {
24DashPreview {
24 id: genericPreview
25 id: genericPreview
25−
26− previewWidthRatio: 0.6
27−
28 property url url: previewData.image
26 property url url: previewData.image
29
27
28+ previewImages: previewImagesComponent
29+ header: headerComponent
30+ actions: actionsComponent
31+ description: descriptionComponent
32+ ratings: ratingsComponent
33+
34+ Component {
35+ id: previewImagesComponent
30− previewImages: UbuntuShape {
36+ UbuntuShape {
31− id: urlLoader
37+ id: urlLoader
32− anchors.left: parent.left
38+ anchors.left: parent.left
33− anchors.right: parent.right
39+ anchors.right: parent.right
34− height: width * previewImage.sourceSize.height / previewImage.sourceSize.width
40+ height: width * previewImage.sourceSize.height / previewImage.sourceSize.width
35− radius: "medium"
41+ radius: "medium"
42+ visible: height > 0
36− image: Image {
43+ image: Image {
37− id: previewImage
44+ id: previewImage
38− asynchronous: true
45+ asynchronous: true
39− source: genericPreview.url
46+ source: genericPreview.url
40− fillMode: Image.PreserveAspectCrop
47+ fillMode: Image.PreserveAspectCrop
48+ }
41 }
49 }
42 }
50 }
43
51
44− header: Column {
52+ Component {
45− height: childrenRect.height
53+ id: headerComponent
46−
54+ PreviewHeader {
47− Label {
48− id: title
49− objectName: "titleLabel"
50− anchors { left: parent.left; right: parent.right }
51−
52− elide: Text.ElideRight
53− fontSize: "large"
54− font.weight: Font.Light
55− color: Theme.palette.selected.backgroundText
56− opacity: 0.9
57− text: previewData.title
55+ title: previewData.title
58− style: Text.Raised
56+ rating: Math.round(root.previewData.rating * 10)
59− styleColor: "black"
57+ reviews: root.previewData.numRatings
60− maximumLineCount: 2
58+ rated: root.previewData.infoMap["rated"] ? root.previewData.infoMap["rated"].value : 0
61− wrapMode: Text.WordWrap
62− }
63−
64− Label {
65− anchors { left: parent.left; right: parent.right }
66− visible: text != ""
67− fontSize: "small"
68− opacity: 0.6
69− color: "white"
70− text: previewData.subtitle.replace(/[\r\n]+/g, "<br />")
71− style: Text.Raised
72− styleColor: "black"
73− wrapMode: Text.WordWrap
74− textFormat: Text.RichText
75− maximumLineCount: 1
76− // FIXME: workaround for https://bugreports.qt-project.org/browse/QTBUG-33020
77− onWidthChanged: { wrapMode = Text.NoWrap; wrapMode = Text.WordWrap }
78 }
59 }
79 }
60 }
61+
62+ Component {
63+ id: actionsComponent
80− actions: GridView {
64+ GridView {
81− id: buttons
65+ id: buttons
82− model: genericPreview.previewData.actions
66+ model: genericPreview.previewData.actions
83−
67+
84− property int buttonMaxWidth: units.gu(34)
68+ property int buttonMaxWidth: units.gu(34)
85− property int numOfColumns: Math.ceil((width + spacing) / (buttonMaxWidth + spacing))
69+ property int numOfColumns: Math.ceil((width + spacing) / (buttonMaxWidth + spacing))
86− property int numOfRows: Math.ceil(count / numOfColumns)
70+ property int numOfRows: Math.ceil(count / numOfColumns)
87− property int spacing: units.gu(1)
71+ property int spacing: units.gu(1)
88− height: Math.max(units.gu(4), units.gu(4)*numOfRows + spacing*(numOfRows - 1))
72+ height: Math.max(units.gu(4), units.gu(4)*numOfRows + spacing*(numOfRows - 1))
89−
73+
90− cellWidth: width / numOfColumns
74+ cellWidth: width / numOfColumns
91− cellHeight: buttonHeight + spacing
75+ cellHeight: buttonHeight + spacing
92− property int buttonWidth: cellWidth - spacing / 2
76+ property int buttonWidth: cellWidth - spacing / 2
93− property int buttonHeight: units.gu(4)
77+ property int buttonHeight: units.gu(4)
94−
78+
95− delegate: Button {
79+ delegate: Button {
96− width: Math.max(units.gu(4), buttons.buttonWidth)
80+ width: Math.max(units.gu(4), buttons.buttonWidth)
97− height: buttons.buttonHeight
81+ height: buttons.buttonHeight
98− color: "#dd4814"
82+ color: "#dd4814"
99− text: modelData.displayName
83+ text: modelData.displayName
100− iconSource: modelData.iconHint
84+ iconSource: modelData.iconHint
101− iconPosition: "right"
85+ iconPosition: "right"
102− visible: true
86+ visible: true
103− onClicked: {
87+ onClicked: {
104− genericPreview.previewData.execute(modelData.id, { })
88+ genericPreview.previewData.execute(modelData.id, { })
89+ }
105 }
90 }
91+ focus: false
106 }
92 }
107− focus: false
108 }
93 }
109
94
95+ Component {
96+ id: descriptionComponent
110− description: Column {
97+ Column {
111− spacing: units.gu(2)
98+ spacing: units.gu(2)
112−
99+
113− Label {
100+ Label {
114− id: descriptionLabel
101+ id: descriptionLabel
115− anchors { left: parent.left; right: parent.right }
102+ anchors { left: parent.left; right: parent.right }
116− visible: text != ""
103+ visible: text != ""
117− fontSize: "small"
104+ fontSize: "small"
118− opacity: 0.6
105+ opacity: 0.6
119− color: "white"
106+ color: "white"
120− text: previewData.description.replace(/[\r\n]+/g, "<br />")
107+ text: previewData.description.replace(/[\r\n]+/g, "<br />")
121− style: Text.Raised
108+ style: Text.Raised
122− styleColor: "black"
109+ styleColor: "black"
123− wrapMode: Text.WordWrap
110+ wrapMode: Text.WordWrap
124− textFormat: Text.RichText
111+ textFormat: Text.RichText
125− // FIXME: workaround for https://bugreports.qt-project.org/browse/QTBUG-33020
112+ // FIXME: workaround for https://bugreports.qt-project.org/browse/QTBUG-33020
126− onWidthChanged: { wrapMode = Text.NoWrap; wrapMode = Text.WordWrap }
113+ onWidthChanged: { wrapMode = Text.NoWrap; wrapMode = Text.WordWrap }
114+ }
115+
116+ Column {
117+ id: infoItem
118+ anchors {
119+ left: parent.left
120+ right: parent.right
121+ }
122+ Repeater {
123+ model: previewData.infoHints
124+
125+ delegate: Item {
126+ width: parent.width
127+ height: units.gu(5)
128+ Row {
129+ width: parent.width
130+ spacing: units.gu(1)
131+ property int columnWidth: (width - spacing) / 2
132+ anchors.verticalCenter: parent.verticalCenter
133+
134+ Label {
135+ visible: directedLabel.visible
136+ fontSize: "small"
137+ opacity: 0.9
138+ color: "white"
139+ horizontalAlignment: Text.AlignLeft
140+ width: parent.columnWidth
141+ text: modelData.displayName
142+ style: Text.Raised
143+ styleColor: "black"
144+ }
145+ Label {
146+ id: directedLabel
147+ visible: modelData.value != ""
148+ fontSize: "small"
149+ opacity: 0.6
150+ color: "white"
151+ horizontalAlignment: Text.AlignRight
152+ width: parent.columnWidth
153+ text: modelData.value ? modelData.value : ""
154+ style: Text.Raised
155+ styleColor: "black"
156+ wrapMode: Text.WordWrap
157+ }
158+ }
159+ ListItems.ThinDivider {
160+ anchors {
161+ left: parent.left
162+ bottom: parent.bottom
163+ right: parent.right
164+ }
165+ }
166+ }
167+ }
168+ }
127 }
169 }
170+ }
128
171
172+ Component {
173+ id: ratingsComponent
129 Column {
174 Column {
130− id: infoItem
175+ visible: root.previewData.rating >= 0
131− anchors {
176+ spacing: units.gu(1)
177+ height: childrenRect.height
178+
179+ ListItems.ThinDivider { }
180+
181+ Item {
182+ anchors { left: parent.left; right: parent.right }
183+ height: rateLabel.height
184+
185+ Label {
186+ id: rateLabel
187+ fontSize: "medium"
188+ color: "white"
189+ style: Text.Raised
190+ styleColor: "black"
191+ opacity: .9
192+ text: i18n.tr("Rate this")
193+
132− left: parent.left
194+ anchors.left: parent.left
195+ anchors.verticalCenter: parent.verticalCenter
196+ }
197+
198+ // FIXME these need to be made interactive and connected to the scope
199+ RatingStars {
133− right: parent.right
200+ anchors.right: parent.right
201+ anchors.verticalCenter: parent.verticalCenter
202+ }
134 }
203 }
135− Repeater {
204+
136− model: previewData.infoHints
205+ ListItems.ThinDivider { }
137−
206+
138− delegate: Grid {
207+ Reviews {
139− columns: 2
208+ id: appReviews
140− width: parent.width
209+ objectName: "appReviews"
141− spacing: units.gu(1)
210+ // TODO: This should make this visible when the feature for reviews/comments is complete.
142−
211+ visible: false; height: 0
143− Label {
212+
144− visible: directedLabel.visible
213+ anchors { left: parent.left; right: parent.right }
145− fontSize: "small"
214+
146− opacity: 0.9
215+ model: root.previewData.infoMap["comments"] ? root.previewData.infoMap["comments"].value : undefined
147− color: "white"
216+
148− horizontalAlignment: Text.AlignLeft
217+ onSendReview: root.sendUserReview(review);
149− width: infoItem.width / 2
218+
150− text: modelData.displayName
219+ onEditing: {
151− style: Text.Raised
220+ root.ensureVisible(appReviews.textArea);
152− styleColor: "black"
153− }
154− Label {
155− id: directedLabel
156− visible: modelData.value != ""
157− fontSize: "small"
158− opacity: 0.6
159− color: "white"
160− horizontalAlignment: Text.AlignRight
161− width: infoItem.width / 2
162− text: modelData.value ? modelData.value : ""
163− style: Text.Raised
164− styleColor: "black"
165− wrapMode: Text.WordWrap
166− }
167 }
221 }
168 }
222 }
169 }
223 }
Dash/Movie/MoviePreview.qml+7−78
@@ -17,29 +17,23 @@
17import QtQuick 2.0
17import QtQuick 2.0
18import Ubuntu.Components 0.1
18import Ubuntu.Components 0.1
19import ".."
19import ".."
20+import "../Generic"
20import "../../Components"
21import "../../Components"
21
22
22−DashPreview {
23+GenericPreview {
23 id: root
24 id: root
24
25
25 property bool ready: previewData ? true : false
26 property bool ready: previewData ? true : false
26 property bool playable: previewData.imageSourceUri != null
27 property bool playable: previewData.imageSourceUri != null
27 property url url: ready ? previewData.image : ""
28 property url url: ready ? previewData.image : ""
28
29
29− title: root.ready ? previewData.title : ""
30− previewWidthRatio: 0.6
31−
32− onPreviewImageClicked: {
33− if (playable) {
34− shell.activateApplication('/usr/share/applications/mediaplayer-app.desktop', previewData.imageSourceUri);
35− }
36− }
37−
38− header: UbuntuShape {
30+ previewImages: UbuntuShape {
39 id: urlLoader
31 id: urlLoader
40 anchors.left: parent.left
32 anchors.left: parent.left
41 anchors.right: parent.right
33 anchors.right: parent.right
34+ height: width * previewImage.sourceSize.height / previewImage.sourceSize.width
42 radius: "medium"
35 radius: "medium"
36+ visible: height > 0
43 image: Image {
37 image: Image {
44 id: previewImage
38 id: previewImage
45 asynchronous: true
39 asynchronous: true
@@ -60,11 +54,11 @@ DashPreview {
60 MouseArea {
54 MouseArea {
61 id: previewImageMouseArea
55 id: previewImageMouseArea
62 anchors.fill: parent
56 anchors.fill: parent
63− onClicked: root.previewImageClicked()
57+ onClicked: shell.activateApplication('/usr/share/applications/mediaplayer-app.desktop', previewData.imageSourceUri);
64 }
58 }
65 }
59 }
66
60
67− buttons: GridView {
61+ actions: GridView {
68 id: buttons
62 id: buttons
69 objectName: "gridButtons"
63 objectName: "gridButtons"
70 model: root.previewData.actions
64 model: root.previewData.actions
@@ -97,69 +91,4 @@ DashPreview {
97 }
91 }
98 focus: false
92 focus: false
99 }
93 }
100−
101− body: Column {
102− spacing: units.gu(2)
103− RatingStars {
104− visible: previewData.rating >= 0.0
105− rating: previewData.rating >= 0.0 ? previewData.rating * 5 : 0
106− }
107−
108− Label {
109− text: ready ? previewData.description : ""
110− color: Theme.palette.selected.backgroundText
111− opacity: .6
112− fontSize: "medium"
113− width: parent.width
114− wrapMode: Text.WordWrap
115− style: Text.Raised
116− styleColor: "black"
117− }
118−
119− Grid {
120− columns: 2
121− spacing: units.gu(1)
122− width: parent.width
123− property int firstColWidth: units.gu(9)
124− property int secondColWidth: width - firstColWidth - spacing
125− Label {
126− visible: directedLabel.visible
127− fontSize: "small"
128− opacity: 0.9
129− color: "white"
130− horizontalAlignment: Text.AlignRight
131− width: parent.firstColWidth
132− text: i18n.tr("Date:")
133− style: Text.Raised
134− styleColor: "black"
135− }
136− Label {
137− id: directedLabel
138− visible: text != ""
139− fontSize: "small"
140− opacity: 0.6
141− color: "white"
142− width: parent.secondColWidth
143− text: ready ? previewData.subtitle : ""
144− style: Text.Raised
145− styleColor: "black"
146− wrapMode: Text.WordWrap
147− }
148− }
149−
150− Label {
151− fontSize: "small"
152− opacity: 0.6
153− color: "white"
154− text: {
155− var parts = []
156− if (ready) {
157− if (previewData.year) parts.push(previewData.year)
158− }
159− return parts.join(", ");
160− }
161− style: Text.Raised
162− styleColor: "black"
163− }
164− }
165}
94}
Dash/Previews/PreviewHeader.qmlnew file+90
@@ -0,0 +1,90 @@
1+/*
2+ * Copyright (C) 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 Ubuntu.Components 0.1
19+import "../../Components"
20+
21+Row {
22+ id: root
23+ property alias icon: image.source
24+ property alias title: titleLabel.text
25+ property alias rating: ratingStars.rating
26+ property int rated: 0
27+ property int reviews: 0
28+
29+ spacing: units.gu(2)
30+
31+ UbuntuShape {
32+ id: imageShape
33+ width: units.gu(6)
34+ height: units.gu(6)
35+ visible: image.source.toString().length > 0
36+ image: Image {
37+ id: image
38+ sourceSize { width: imageShape.width; height: imageShape.height }
39+ asynchronous: true
40+ fillMode: Image.PreserveAspectFit
41+ }
42+ }
43+
44+ Column {
45+ spacing: units.gu(1)
46+
47+ Label {
48+ id: titleLabel
49+ fontSize: "large"
50+ color: "white"
51+ style: Text.Raised
52+ styleColor: "black"
53+ opacity: .9
54+ }
55+
56+ Row {
57+ visible: root.rating >= 0
58+ spacing: units.gu(1)
59+
60+ RatingStars {
61+ id: ratingStars
62+ maximumRating: 10
63+ }
64+
65+ Label {
66+ id: ratedLabel
67+ objectName: "ratedLabel"
68+ fontSize: "medium"
69+ color: "white"
70+ style: Text.Raised
71+ styleColor: "black"
72+ opacity: .6
73+ //TRANSLATORS: Number of persons who rated this app/video/whatever
74+ text: i18n.tr("(%1)").arg(root.rated)
75+ }
76+
77+ Label {
78+ id: reviewsLabel
79+ objectName: "reviewsLabel"
80+ fontSize: "medium"
81+ color: "white"
82+ style: Text.Raised
83+ styleColor: "black"
84+ opacity: .6
85+ //TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
86+ text: i18n.tr("%1 review", "%1 reviews", root.reviews).arg(root.reviews)
87+ }
88+ }
89+ }
90+}
Dash/Apps/AppReviews.qml → Dash/Previews/Reviews.qmlrenamed

The content is the same.