on xenial help sign in
merge with prerequisite branch
commit41c158fa2680aa8608b9e81ef86bc7b9f5ffb380 authorMichael Zanetti <michael.zanetti@canonical.com> dateFri 4 Oct 2013, 19:46 (13 years ago) parentac3780db064b8d
15 files changed+840−616
Components/Tile.qml+6−2 Dash/Apps/AppPreview.qml+78−131 Dash/DashPreview.qml+91−95 Dash/Generic/GenericPreview.qml+158−70 Dash/Movie/MoviePreview.qml+71 Dash/PreviewDelegateMapper.qml+1 Dash/Previews/Header.qml+109 Dash/Apps/AppReviews.qml → Dash/Previews/Reviews.qml Dash/Video/VideoPreview.qml−210 tests/qmltests/CMakeLists.txt+2−1 tests/qmltests/Dash/Apps/tst_AppPreview.qml+57−25 tests/qmltests/Dash/Movie/tst_MoviePreview.qml+85 tests/qmltests/Dash/Video/tst_VideoPreview.qml−63 tests/qmltests/Dash/tst_DashPreview.qml+66−19 tests/qmltests/Dash/tst_GenericPreview.qml+116
Components/Tile.qml+6−2
@@ -25,10 +25,14 @@ AbstractButton {
2525 property string text
2626 property int imageWidth
2727 property int imageHeight
28− opacity: GridView.view.highlightIndex === -1 ? 1 :
29− GridView.view.highlightIndex === index ? 0.6 : 0.2
3028 readonly property int center: (index % GridView.view.columns * width) + (width / 2)
3129 property int maximumLineCount: 1
30+ opacity: GridView.view.highlightIndex === -1 ? 1 :
31+ GridView.view.highlightIndex === index ? 0.6 : 0.2
3232
3333 style: TileStyle {}
34+
35+ Behavior on opacity {
36+ UbuntuNumberAnimation {}
37+ }
3438}
Dash/Apps/AppPreview.qml+78−131
@@ -16,162 +16,110 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19−import Ubuntu.Components.ListItems 0.1 as ListItem
20−import Ubuntu.DownloadDaemonListener 0.1
19+import Ubuntu.Components.ListItems 0.1 as ListItems
2120import ".."
21+import "../Generic"
22+import "../Previews"
2223import "../../Components"
2324
24−DashPreview {
25+GenericPreview {
2526 id: root
2627
2728 signal sendUserReview(string review)
2829
29− title: root.previewData.title
30+ previewImages: previewImagesComponent
31+ description: descriptionComponent
32+ header: headerComponent
3033
31− header: ListView {
32− spacing: units.gu(1)
33− orientation: ListView.Horizontal
34− height: units.gu(22)
35− anchors {
36− left: parent.left
37− right: parent.right
38− margins: units.gu(1)
39− }
40− model: previewData.infoMap["more-screenshots"] != null ? previewData.infoMap["more-screenshots"].value : [previewData.image]
41−
42− // FIXME: Because of ListViews inside ListViews inside Flickables inside ListViews (and some more)
43− // we finally reached the point where this ListView doesn't correctly get swipe input any more but
44− // instead the parent ListView is the one that is swiped. This MouseArea sort of creates a blocking
45− // layer to make sure this ListView can be swiped, regardless of what's behind it.
46− MouseArea {
47− anchors.fill: parent
48− enabled: parent.contentWidth > parent.width
49− }
50−
51− delegate: UbuntuShape {
52− id: shape
53− anchors {
54− top: parent.top
55− bottom: parent.bottom
56− }
57− width: units.gu(12)
58− radius: "medium"
59− borderSource: ""
60− image: Image {
61− asynchronous: true
62− sourceSize { width: shape.width; height: shape.height }
63− source: modelData ? modelData : ""
64− fillMode: Image.PreserveAspectCrop
65− }
66− }
67− }
34+ // TODO: Ratings are not yet complete... enable this once they work
35+ //ratings: ratingsComponent
6836
6937 Component {
70− id: buttonsComponent
71−
72− GridView {
73− id: buttonsGrid
74− objectName: "gridButtons"
75−
76− property int numOfRows: (count + 1) / 2
77− property int spacing: units.gu(1)
78− height: Math.max(units.gu(5), units.gu(5)*numOfRows + spacing*(numOfRows - 1))
79−
80− interactive: false
81− cellWidth: Math.max(units.gu(9), width / 2)
82− cellHeight: buttonHeight + spacing
83− property int buttonWidth: count > 1 ? Math.max(0, width / 2 - spacing) : width
84− property int buttonHeight: units.gu(5)
85−
86− delegate: Button {
87− width: Math.max(units.gu(4), buttonsGrid.buttonWidth)
88− height: buttonsGrid.buttonHeight
89− color: Theme.palette.selected.foreground
90− text: modelData.displayName
91− iconSource: modelData.iconHint
92− iconPosition: "right"
93− onClicked: root.previewData.execute(modelData.id, { })
38+ id: previewImagesComponent
39+ ListView {
40+ id: previewImageListView
41+ spacing: units.gu(1)
42+ orientation: ListView.Horizontal
43+ height: units.gu(22)
44+ model: previewData.infoMap["more-screenshots"] != null ? previewData.infoMap["more-screenshots"].value : [previewData.image]
45+ cacheBuffer: width * 3
46+
47+ // FIXME: Because of ListViews inside ListViews inside Flickables inside ListViews (and some more)
48+ // we finally reached the point where this ListView doesn't correctly get swipe input any more but
49+ // instead the parent ListView is the one that is swiped. This MouseArea sort of creates a blocking
50+ // layer to make sure this ListView can be swiped, regardless of what's behind it.
51+ MouseArea {
52+ anchors.fill: parent
53+ enabled: parent.contentWidth > parent.width
9454 }
95− }
96− }
9755
98− Component {
99− id: progressComponent
100−
101− ProgressBar {
102− id: progressBar
103− objectName: "progressBar"
104− value: 0
105− maximumValue: 100
106− height: units.gu(5)
107−
108− property var model
109−
110− DownloadTracker {
111− service: "com.canonical.applications.Downloader"
112− dbusPath: root.previewData.infoMap["progressbar_source"] ? root.previewData.infoMap["progressbar_source"].value : ""
113−
114− onProgress: {
115− var percentage = parseInt(received * 100 / total);
116− progressBar.value = percentage;
117− }
118−
119− onFinished: {
120− root.previewData.execute(progressBar.model[0].id, { })
56+ LazyImage {
57+ objectName: "placeholderScreenshot"
58+ anchors {
59+ top: parent.top
60+ bottom: parent.bottom
12161 }
62+ scaleTo: "height"
63+ source: "broken_image"
64+ initialWidth: units.gu(13)
65+ visible: previewImageListView.count == 0
66+ }
12267
123− onError: {
124− root.previewData.execute(progressBar.model[1].id, { "error": error });
68+ delegate: LazyImage {
69+ id: shape
70+ anchors {
71+ top: parent.top
72+ bottom: parent.bottom
12573 }
74+ source: modelData ? modelData : ""
75+ scaleTo: "height"
76+ initialWidth: units.gu(13)
12677 }
127−
12878 }
12979 }
13080
131− buttons: Loader {
132− anchors {
133− left: parent.left
134− right: parent.right
135− }
136−
137− sourceComponent: root.previewData.infoMap["show_progressbar"] ? progressComponent : buttonsComponent
138−
139− onLoaded: {
140− item.model = root.previewData.actions;
141− }
142− }
143−
144− body: Column {
145− spacing: units.gu(1)
146−
147− AppInfo {
148− objectName: "appInfo"
149− anchors { left: parent.left; right: parent.right }
150−
151− appName: root.previewData.title
152− icon: root.previewData.appIcon
81+ Component {
82+ id: headerComponent
83+ Header {
84+ objectName: "previewHeader"
85+ title: previewData.title
86+ icon: previewData.appIcon
87+ subtitle: root.previewData.infoMap["publisher"] ? root.previewData.infoMap["publisher"].value : ""
15388 rating: Math.round(root.previewData.rating * 10)
15489 reviews: root.previewData.numRatings
15590 rated: root.previewData.infoMap["rated"] ? root.previewData.infoMap["rated"].value : 0
15691 }
92+ }
15793
158− Label {
159− anchors { left: parent.left; right: parent.right }
160− text: root.previewData.description
161− fontSize: "medium"
162− color: Theme.palette.selected.backgroundText
163− opacity: .6
164− wrapMode: Text.WordWrap
165− style: Text.Raised
166− styleColor: "black"
94+ Component {
95+ id: descriptionComponent
96+ Column {
97+ spacing: units.gu(1)
98+
99+ Label {
100+ anchors { left: parent.left; right: parent.right }
101+ text: root.previewData.description
102+ fontSize: "medium"
103+ color: Theme.palette.selected.backgroundText
104+ opacity: .6
105+ wrapMode: Text.WordWrap
106+ style: Text.Raised
107+ styleColor: "black"
108+ }
167109 }
110+ }
168111
112+ Component {
113+ id: ratingsComponent
169114 Column {
115+ id: columnReviewRating
116+ objectName: "columnReviewRating"
170117 visible: root.previewData.rating >= 0
171− anchors { left: parent.left; right: parent.right }
172− spacing: parent.spacing
173118
174− ListItem.ThinDivider { }
119+ spacing: units.gu(1)
120+ height: childrenRect.height
121+
122+ ListItems.ThinDivider { }
175123
176124 Item {
177125 anchors { left: parent.left; right: parent.right }
@@ -197,13 +145,12 @@ DashPreview {
197145 }
198146 }
199147
200− ListItem.ThinDivider { }
148+ ListItems.ThinDivider { }
201149
202− AppReviews {
150+ Reviews {
203151 id: appReviews
204152 objectName: "appReviews"
205− // TODO: This should make this visible when the feature for reviews/comments is complete.
206− visible: false
153+
207154 anchors { left: parent.left; right: parent.right }
208155
209156 model: root.previewData.infoMap["comments"] ? root.previewData.infoMap["comments"].value : undefined
Dash/DashPreview.qml+91−95
@@ -23,19 +23,18 @@ Item {
2323 property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0
2424 property var previewData
2525
26− property string title: ""
2726 property real previewWidthRatio: 0.5
2827
28+ property Component previewImages
2929 property Component header
30− property Component buttons
31− property Component body
30+ property Component actions
31+ property Component description
32+ property Component ratings
3233
33− readonly property bool narrowMode: width <= height
34+ readonly property bool narrowMode: width <= height * 1.5
35+ readonly property int columnWidth: narrowMode ? contentRow.width : (contentRow.width / 3) - contentRow.spacing
3436 readonly property int contentSpacing: units.gu(3)
3537
36− signal close()
37− signal previewImageClicked()
38−
3938 clip: true
4039
4140 function ensureVisible(item) {
@@ -60,88 +59,31 @@ Item {
6059 anchors.fill: parent
6160 }
6261
63− Item {
64− id: headerRow
65− height: units.gu(4)
66− anchors {
67− top: parent.top
68− left: parent.left
69− right: parent.right
70− margins: root.contentSpacing
71− }
72−
73− MouseArea {
74− anchors {
75− fill: parent
76− leftMargin: -root.contentSpacing
77− rightMargin: -root.contentSpacing
78− topMargin: -root.contentSpacing
79− }
80−
81− onClicked: root.close();
82− }
83−
84− Item {
85− id: labelItem
86− anchors {
87− fill: parent
88− rightMargin: closePreviewImage.width + spacing
89− }
90−
91− property int spacing: units.gu(2)
92−
93− Label {
94− id: title
95− objectName: "titleLabel"
96− anchors {
97− left: parent.left
98− right: parent.right
99− }
100−
101− elide: Text.ElideRight
102− fontSize: "x-large"
103− font.weight: Font.Light
104− color: Theme.palette.selected.backgroundText
105− opacity: 0.9
106− text: root.title
107− style: Text.Raised
108− styleColor: "black"
109− }
110− Image {
111− id: closePreviewImage
112− source: "graphics/tablet/icon_close_preview.png"
113− width: units.gu(4)
114− height: units.gu(1.5)
115− anchors {
116− bottom: title.bottom
117− bottomMargin: units.dp(7)
118− left: parent.left
119− leftMargin: title.paintedWidth + labelItem.spacing
120− }
121− visible: title.text !== ""
122− }
123− }
124− }
125−
12662 Row {
12763 id: contentRow
12864 anchors {
12965 left: parent.left
66+ top: parent.top
13067 right: parent.right
131− top: headerRow.bottom
13268 bottom: parent.bottom
133− margins: root.contentSpacing
69+ topMargin: root.contentSpacing
70+ leftMargin: root.contentSpacing
71+ rightMargin: root.contentSpacing
13472 }
73+ height: childrenRect.height
13574
13675 spacing: units.gu(2)
13776
77+
13878 Flickable {
13979 id: leftFlickable
14080 objectName: "leftFlickable"
141− anchors.top: parent.top
142− anchors.bottom: parent.bottom
143− width: root.narrowMode ? contentRow.width : contentRow.width * root.previewWidthRatio
144− contentHeight: leftColumn.height
81+ anchors {
82+ top: parent.top
83+ bottom: parent.bottom
84+ }
85+ width: root.columnWidth
86+ contentHeight: leftColumn.height + root.contentSpacing
14587 anchors.bottomMargin: root.keyboardSize
14688 clip: true
14789
@@ -150,33 +92,44 @@ Item {
15092 Column {
15193 id: leftColumn
15294 objectName: "leftColumn"
95+ height: childrenRect.height
96+ spacing: root.contentSpacing
15397 anchors {
15498 left: parent.left
15599 right: parent.right
156100 }
157− height: childrenRect.height
158− spacing: units.gu(1)
101+ }
102+ }
159103
160− Loader {
161− id: headerLoader
162− anchors.left: parent.left
163− anchors.right: parent.right
164− sourceComponent: root.header
165− }
166− Loader {
167− id: buttonLoader
168− anchors.left: parent.left
169− anchors.right: parent.right
170− sourceComponent: root.buttons
104+ Flickable {
105+ id: centerFlickable
106+ anchors {
107+ top: parent.top
108+ bottom: parent.bottom
109+ }
110+ width: root.columnWidth
111+ contentHeight: centerColumn.height
112+ clip: true
113+
114+ Column {
115+ id: centerColumn
116+ objectName: "centerColumn"
117+ height: childrenRect.height
118+ anchors {
119+ left: parent.left
120+ right: parent.right
171121 }
122+ spacing: root.contentSpacing
172123 }
173124 }
174125
175126 Flickable {
176127 id: rightFlickable
177− anchors.top: parent.top
178− anchors.bottom: parent.bottom
179− width: narrowMode ? 0 : (contentRow.width - leftColumn.width - contentRow.spacing)
128+ anchors {
129+ top: parent.top
130+ bottom: parent.bottom
131+ }
132+ width: root.columnWidth
180133 contentHeight: rightColumn.height
181134 clip: true
182135
@@ -193,9 +146,52 @@ Item {
193146 }
194147
195148 Loader {
149+ id: previewImageLoader
150+ parent: leftColumn
151+ sourceComponent: root.previewImages
152+ anchors {
153+ left: parent.left
154+ right: parent.right
155+ }
156+ }
157+
158+ Loader {
159+ id: ratingsLoader
196160 parent: root.narrowMode ? leftColumn : rightColumn
197− anchors.left: parent.left
198− anchors.right: parent.right
199− sourceComponent: root.body
161+ anchors {
162+ left: parent.left
163+ right: parent.right
164+ }
165+ sourceComponent: root.ratings
166+ }
167+
168+ Loader {
169+ id: descriptionLoader
170+ parent: root.narrowMode ? leftColumn : centerColumn
171+ anchors {
172+ left: parent.left
173+ right: parent.right
174+ }
175+ sourceComponent: root.description
176+ }
177+
178+ Loader {
179+ id: actionsLoader
180+ parent: root.narrowMode ? leftColumn : centerColumn
181+ anchors {
182+ left: parent.left
183+ right: parent.right
184+ }
185+ sourceComponent: root.actions
186+ }
187+
188+ Loader {
189+ id: headerLoader
190+ parent: root.narrowMode ? leftColumn : centerColumn
191+ anchors {
192+ left: parent.left
193+ right: parent.right
194+ }
195+ sourceComponent: root.header
200196 }
201197}
Dash/Generic/GenericPreview.qml+158−70
@@ -16,90 +16,178 @@
1616
1717import QtQuick 2.0
1818import Ubuntu.Components 0.1
19+import Ubuntu.Components.ListItems 0.1 as ListItems
20+import Ubuntu.DownloadDaemonListener 0.1
1921import "../../Components"
20−import "../../Components/ListItems" as ListItems
2122import ".."
23+import "../Previews"
2224
2325DashPreview {
2426 id: genericPreview
2527
26− title: previewData.title
27− previewWidthRatio: 0.6
28−
29− property url url: previewData.image
30−
31− header: UbuntuShape {
32− id: urlLoader
33− anchors.left: parent.left
34− anchors.right: parent.right
35− height: width * previewImage.sourceSize.height / previewImage.sourceSize.width
36− radius: "medium"
37− image: Image {
38− id: previewImage
39− asynchronous: true
40− source: genericPreview.url
41− fillMode: Image.PreserveAspectCrop
28+ previewImages: previewImagesComponent
29+ header: headerComponent
30+ actions: (previewData.infoMap !== undefined && previewData.infoMap["show_progressbar"]) ? progressComponent : actionsComponent
31+ description: descriptionComponent
32+
33+ Component {
34+ id: previewImagesComponent
35+
36+ LazyImage {
37+ objectName: "genericPreviewImage"
38+ anchors {
39+ left: parent.left
40+ right: parent.right
41+ }
42+ scaleTo: "width"
43+ source: genericPreview.previewData.image
44+ initialHeight: width
45+ }
46+ }
47+
48+ Component {
49+ id: headerComponent
50+ Header {
51+ title: previewData.title
52+ subtitle: previewData.subtitle.replace(/[\r\n]+/g, "<br />")
4253 }
4354 }
4455
45− buttons: GridView {
46− id: buttons
47− model: genericPreview.previewData.actions
48−
49− property int numOfRows: (count + 1) / 2
50− property int spacing: units.gu(1)
51− height: Math.max(units.gu(4), units.gu(4)*numOfRows + spacing*(numOfRows - 1))
52−
53− cellWidth: Math.max(units.gu(9), width / 2)
54− cellHeight: buttonHeight + spacing
55− property int buttonWidth: Math.max(0, width / 2 - spacing)
56− property int buttonHeight: units.gu(4)
57−
58− delegate: Button {
59− width: Math.max(units.gu(4), buttons.buttonWidth)
60− height: buttons.buttonHeight
61− color: "#dd4814"
62− text: modelData.displayName
63− iconSource: modelData.iconHint
64− iconPosition: "right"
65− visible: true
66− onClicked: {
67− genericPreview.previewData.execute(modelData.id, { })
56+ Component {
57+ id: actionsComponent
58+
59+ Column {
60+ id: buttonList
61+ spacing: units.gu(1)
62+ Repeater {
63+ objectName: "buttonList"
64+ model: previewData.actions
65+
66+ delegate: Button {
67+ objectName: "button" + index
68+ width: parent.width
69+ height: buttonList.buttonHeight
70+ color: Theme.palette.selected.foreground
71+ text: modelData.displayName
72+ iconSource: modelData.iconHint
73+ iconPosition: "right"
74+ onClicked: previewData.execute(modelData.id, { })
75+ }
6876 }
6977 }
70− focus: false
7178 }
72− body: Column {
73− spacing: units.gu(2)
74−
75− Label {
76− anchors { left: parent.left; right: parent.right }
77− visible: text != ""
78− fontSize: "medium"
79− opacity: 0.6
80− color: "white"
81− text: previewData.subtitle.replace(/[\r\n]+/g, "<br />")
82− style: Text.Raised
83− styleColor: "black"
84− wrapMode: Text.WordWrap
85− textFormat: Text.RichText
86− // FIXME: workaround for https://bugreports.qt-project.org/browse/QTBUG-33020
87− onWidthChanged: { wrapMode = Text.NoWrap; wrapMode = Text.WordWrap }
79+
80+ Component {
81+ id: progressComponent
82+
83+ ProgressBar {
84+ id: progressBar
85+ objectName: "progressBar"
86+ value: 0
87+ maximumValue: 100
88+ height: units.gu(5)
89+
90+ property var model: previewData.actions
91+
92+ DownloadTracker {
93+ service: "com.canonical.applications.Downloader"
94+ dbusPath: previewData.infoMap["progressbar_source"] ? previewData.infoMap["progressbar_source"].value : ""
95+
96+ onProgress: {
97+ var percentage = parseInt(received * 100 / total);
98+ progressBar.value = percentage;
99+ }
100+
101+ onFinished: {
102+ previewData.execute(progressBar.model[0].id, { })
103+ }
104+
105+ onError: {
106+ previewData.execute(progressBar.model[1].id, { "error": error });
107+ }
108+ }
109+
88110 }
111+ }
89112
90− Label {
91− anchors { left: parent.left; right: parent.right }
92− visible: text != ""
93− fontSize: "small"
94− opacity: 0.6
95− color: "white"
96− text: previewData.description.replace(/[\r\n]+/g, "<br />")
97− style: Text.Raised
98− styleColor: "black"
99− wrapMode: Text.WordWrap
100− textFormat: Text.RichText
101− // FIXME: workaround for https://bugreports.qt-project.org/browse/QTBUG-33020
102− onWidthChanged: { wrapMode = Text.NoWrap; wrapMode = Text.WordWrap }
113+ Component {
114+ id: descriptionComponent
115+ Column {
116+ spacing: units.gu(2)
117+
118+ Label {
119+ id: descriptionLabel
120+ anchors { left: parent.left; right: parent.right }
121+ visible: text != ""
122+ fontSize: "small"
123+ opacity: 0.6
124+ color: "white"
125+ text: previewData.description.replace(/[\r\n]+/g, "<br />")
126+ style: Text.Raised
127+ styleColor: "black"
128+ wrapMode: Text.WordWrap
129+ textFormat: Text.RichText
130+ // FIXME: workaround for https://bugreports.qt-project.org/browse/QTBUG-33020
131+ onWidthChanged: { wrapMode = Text.NoWrap; wrapMode = Text.WordWrap }
132+ }
133+
134+ Column {
135+ objectName: "infoHintColumn"
136+ anchors {
137+ left: parent.left
138+ right: parent.right
139+ }
140+ Repeater {
141+ objectName: "infoHintRepeater"
142+ model: previewData.infoHints
143+
144+ delegate: Item {
145+ objectName: "infoHintItem" + index
146+ width: parent.width
147+ height: units.gu(5)
148+ Row {
149+ width: parent.width
150+ spacing: units.gu(1)
151+ property int columnWidth: (width - spacing) / 2
152+ anchors.verticalCenter: parent.verticalCenter
153+
154+ Label {
155+ objectName: "displayNameLabel"
156+ visible: valueLabel.visible
157+ fontSize: "small"
158+ opacity: 0.9
159+ color: "white"
160+ horizontalAlignment: Text.AlignLeft
161+ width: parent.columnWidth
162+ text: modelData.displayName
163+ style: Text.Raised
164+ styleColor: "black"
165+ }
166+ Label {
167+ id: valueLabel
168+ objectName: "valueLabel"
169+ visible: modelData.value != ""
170+ fontSize: "small"
171+ opacity: 0.6
172+ color: "white"
173+ horizontalAlignment: Text.AlignRight
174+ width: parent.columnWidth
175+ text: modelData.value ? modelData.value : ""
176+ style: Text.Raised
177+ styleColor: "black"
178+ wrapMode: Text.WordWrap
179+ }
180+ }
181+ ListItems.ThinDivider {
182+ anchors {
183+ left: parent.left
184+ bottom: parent.bottom
185+ right: parent.right
186+ }
187+ }
188+ }
189+ }
190+ }
103191 }
104192 }
105193}
Dash/Movie/MoviePreview.qmlnew file+71
@@ -0,0 +1,71 @@
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 ".."
20+import "../Generic"
21+import "../../Components"
22+import "../Previews"
23+
24+GenericPreview {
25+ id: root
26+
27+ property bool ready: previewData ? true : false
28+ property url url: ready ? previewData.image : ""
29+
30+ previewImages: previewImageComponent
31+ header: headerComponent
32+
33+ Component {
34+ id: previewImageComponent
35+ LazyImage {
36+ anchors.left: parent.left
37+ anchors.right: parent.right
38+ scaleTo: "width"
39+ visible: height > 0
40+ source: root.url
41+ initialHeight: width * 10 / 16
42+
43+ Image {
44+ objectName: "playButton"
45+ anchors.centerIn: parent
46+ readonly property bool bigButton: parent.width > units.gu(40)
47+ width: bigButton ? units.gu(8) : units.gu(4.5)
48+ height: width
49+ source: "../graphics/play_button%1%2.png".arg(previewImageMouseArea.pressed ? "_active" : "").arg(bigButton ? "_big" : "")
50+ }
51+
52+ MouseArea {
53+ id: previewImageMouseArea
54+ anchors.fill: parent
55+ onClicked: {
56+ Qt.openUrlExternally(previewData.result.uri);
57+ }
58+ }
59+ }
60+ }
61+
62+ Component {
63+ id: headerComponent
64+ Header {
65+ title: previewData.title
66+ rating: Math.round(previewData.rating * 10)
67+ reviews: previewData.numRatings
68+ rated: previewData.infoMap["rated"] ? previewData.infoMap["rated"].value : 0
69+ }
70+ }
71+}
Dash/PreviewDelegateMapper.qml+1
@@ -22,6 +22,7 @@ QtObject {
2222 readonly property string appPreview: "Apps/AppPreview.qml"
2323 property var previewDelegateMapping: {"preview-generic": genericPreview,
2424 "preview-application": appPreview,
25+ "preview-movie": "Movie/MoviePreview.qml",
2526 }
2627 }
2728
Dash/Previews/Header.qmlnew file+109
@@ -0,0 +1,109 @@
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 subtitle: subtitleLabel.text
26+ property alias rating: ratingStars.rating
27+ property int rated: 0
28+ property int reviews: 0
29+
30+ spacing: units.gu(2)
31+ height: imageShape.visible ? imageShape.height : contentColumn.height
32+
33+ UbuntuShape {
34+ id: imageShape
35+ width: height
36+ height: Math.max(units.gu(6), contentColumn.height)
37+ visible: image.source.toString().length > 0
38+ image: Image {
39+ id: image
40+ sourceSize { width: imageShape.width; height: imageShape.height }
41+ asynchronous: true
42+ fillMode: Image.PreserveAspectFit
43+ }
44+ }
45+
46+ Column {
47+ id: contentColumn
48+ spacing: units.gu(1)
49+ width: parent.width - x
50+
51+ Label {
52+ id: titleLabel
53+ objectName: "titleLabel"
54+ fontSize: "large"
55+ color: "white"
56+ style: Text.Raised
57+ styleColor: "black"
58+ opacity: .9
59+ width: parent.width
60+ elide: Text.ElideRight
61+ }
62+
63+ Label {
64+ id: subtitleLabel
65+ objectName: "subtitleLabel"
66+ fontSize: "medium"
67+ color: "white"
68+ style: Text.Raised
69+ styleColor: "black"
70+ opacity: .6
71+ visible: text.length > 0
72+ }
73+
74+ Row {
75+ visible: root.rating >= 0
76+ spacing: units.gu(1)
77+
78+ RatingStars {
79+ id: ratingStars
80+ maximumRating: 10
81+ rating: -1
82+ }
83+
84+ Label {
85+ id: ratedLabel
86+ objectName: "ratedLabel"
87+ fontSize: "medium"
88+ color: "white"
89+ style: Text.Raised
90+ styleColor: "black"
91+ opacity: .6
92+ //TRANSLATORS: Number of persons who rated this app/video/whatever
93+ text: i18n.tr("(%1)").arg(root.rated)
94+ }
95+
96+ Label {
97+ id: reviewsLabel
98+ objectName: "reviewsLabel"
99+ fontSize: "medium"
100+ color: "white"
101+ style: Text.Raised
102+ styleColor: "black"
103+ opacity: .6
104+ //TRANSLATORS: Number of persons who wrote reviews for this app/video/whatever
105+ text: i18n.tr("%1 review", "%1 reviews", root.reviews).arg(root.reviews)
106+ }
107+ }
108+ }
109+}
Dash/Apps/AppReviews.qml → Dash/Previews/Reviews.qmlrenamed

The content is the same.

Dash/Video/VideoPreview.qmldeleted−210
@@ -1,210 +0,0 @@
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 ".."
20−import "../../Components"
21−
22−DashPreview {
23− id: root
24−
25− property var item
26− property alias ready: nfo.ready
27− property bool playable: fileUri != ""
28− readonly property url fileUri: item ? item.fileUri : ""
29− property url url: item ? item.nfoUri.replace(/\.nfo$/, "-fanart.jpg") : ""
30−
31− VideoInfo {
32− id: nfo
33− source: item ? item.nfoUri : ""
34− }
35−
36− title: nfo.ready ? nfo.video.title : ""
37− previewWidthRatio: 0.6
38−
39− onPreviewImageClicked: {
40− if (playable) {
41− shell.activateApplication('/usr/share/applications/mediaplayer-app.desktop', root.fileUri);
42− }
43− }
44−
45− // TODO: replace this UbuntuShape with the Video component once that lands
46− // with the player.
47− header: UbuntuShape {
48− id: urlLoader
49− anchors.left: parent.left
50− anchors.right: parent.right
51− height: width * previewImage.sourceSize.height / previewImage.sourceSize.width
52− radius: "medium"
53− image: Image {
54− id: previewImage
55− asynchronous: true
56− source: root.url
57− fillMode: Image.PreserveAspectCrop
58− }
59−
60− Image {
61− objectName: "playButton"
62− anchors.centerIn: parent
63− visible: root.playable
64− readonly property bool bigButton: parent.width > units.gu(40)
65− width: bigButton ? units.gu(8) : units.gu(4.5)
66− height: width
67− source: "../graphics/play_button%1%2.png".arg(previewImageMouseArea.pressed ? "_active" : "").arg(bigButton ? "_big" : "")
68− }
69−
70− MouseArea {
71− id: previewImageMouseArea
72− anchors.fill: parent
73− onClicked: root.previewImageClicked()
74− }
75− }
76−
77− buttons: Row {
78− spacing: units.gu(2)
79−
80− property int buttonWidth: Math.min(units.gu(22), (width - spacing) / 2)
81− Button {
82− width: parent.buttonWidth
83− color: Theme.palette.selected.foreground
84− text: nfo.ready && nfo.video.buyPrice != "" ? "Buy for " + nfo.video.buyPrice : ""
85− visible: text != ""
86− iconSource: "graphics/icon_button_amazon.png"
87− iconPosition: "right"
88− }
89− Button {
90− width: parent.buttonWidth
91− color: Theme.palette.selected.foreground
92− text: nfo.ready && nfo.video.buyPrice != "" ? "Rent for " + nfo.video.rentPrice : ""
93− visible: text != ""
94− iconSource: "graphics/icon_button_u1.png"
95− iconPosition: "right"
96− }
97− }
98−
99− body: Column {
100− spacing: units.gu(2)
101− RatingStars {
102− maximumRating: 10 // FIXME: this should happen on the backend side
103− rating: nfo.ready ? nfo.video.rating: 0
104− }
105−
106− Label {
107− text: nfo.ready ? nfo.video.plot : ""
108− color: Theme.palette.selected.backgroundText
109− opacity: .6
110− fontSize: "medium"
111− width: parent.width
112− wrapMode: Text.WordWrap
113− style: Text.Raised
114− styleColor: "black"
115− }
116−
117− Grid {
118− columns: 2
119− spacing: units.gu(1)
120− width: parent.width
121− property int firstColWidth: units.gu(9)
122− property int secondColWidth: width - firstColWidth - spacing
123− Label {
124− visible: directedLabel.visible
125− fontSize: "small"
126− opacity: 0.9
127− color: "white"
128− horizontalAlignment: Text.AlignRight
129− width: parent.firstColWidth
130− text: i18n.tr("Directed by:")
131− style: Text.Raised
132− styleColor: "black"
133− }
134− Label {
135− id: directedLabel
136− visible: text != ""
137− fontSize: "small"
138− opacity: 0.6
139− color: "white"
140− width: parent.secondColWidth
141− text: nfo.ready ? nfo.video.director : ""
142− style: Text.Raised
143− styleColor: "black"
144− wrapMode: Text.WordWrap
145− }
146− Label {
147− visible: starringLabel.visible
148− fontSize: "small"
149− opacity: 0.9
150− horizontalAlignment: Text.AlignRight
151− color: "white"
152− width: parent.firstColWidth
153− text: i18n.tr("Starring:")
154− style: Text.Raised
155− styleColor: "black"
156− }
157− Label {
158− id: starringLabel
159− visible: text != ""
160− fontSize: "small"
161− opacity: 0.6
162− color: "white"
163− width: parent.secondColWidth
164− text: nfo.ready ? nfo.getActors().join(", ") : ""
165− wrapMode: Text.WordWrap
166− style: Text.Raised
167− styleColor: "black"
168− }
169− Label {
170− visible: authorLabel.visible
171− fontSize: "small"
172− opacity: 0.9
173− horizontalAlignment: Text.AlignRight
174− color: "white"
175− width: parent.firstColWidth
176− text: i18n.tr("Author:")
177− style: Text.Raised
178− styleColor: "black"
179− }
180− Label {
181− id: authorLabel
182− visible: text != ""
183− fontSize: "small"
184− opacity: 0.6
185− color: "white"
186− width: parent.secondColWidth
187− text: nfo.ready ? nfo.video.author : ""
188− wrapMode: Text.WordWrap
189− style: Text.Raised
190− styleColor: "black"
191− }
192− }
193−
194− Label {
195− fontSize: "small"
196− opacity: 0.6
197− color: "white"
198− text: {
199− var parts = []
200− if (nfo.ready) {
201− if (nfo.video.year) parts.push(nfo.video.year)
202− if (nfo.video.runtime) parts.push("%1 minutes".arg(nfo.video.runtime))
203− }
204− return parts.join(", ");
205− }
206− style: Text.Raised
207− styleColor: "black"
208− }
209− }
210−}
tests/qmltests/CMakeLists.txt+2−1
@@ -45,13 +45,14 @@ add_qml_test(Dash Dash IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAUL
4545add_qml_test(Dash DashBar IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
4646add_qml_test(Dash DashContent IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS})
4747add_qml_test(Dash DashPreview)
48+add_qml_test(Dash GenericPreview)
4849add_qml_test(Dash GenericScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
4950add_qml_test(Dash ScopeView IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS})
5051add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/plugins ${CMAKE_CURRENT_SOURCE_DIR}/plugins
5152 ${CMAKE_BINARY_DIR}/tests/mocks)
5253add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
5354add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
54−add_qml_test(Dash/Video VideoPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
55+add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
5556add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
5657 PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
5758add_qml_test(Greeter Tablet IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
tests/qmltests/Dash/Apps/tst_AppPreview.qml+57−25
@@ -42,6 +42,7 @@ Item {
4242 QtObject { id: rated; property int value: 120 }
4343 QtObject { id: reviews; property int value: 8 }
4444 QtObject { id: progress; property string value: "source" }
45+ QtObject { id: publisher; property string value: "Ubuntu Developer" }
4546 QtObject { id: comments; property var value: [
4647 ["Unity User", 4, "08/20/2013", root.commentary],
4748 ["Unity User", 8, "01/15/2013", root.commentary],
@@ -62,7 +63,8 @@ Item {
6263 property var infoMap: {
6364 "more-screenshots": screenshots,
6465 "rated": rated,
65− "comments": comments
66+ "comments": comments,
67+ "publisher": publisher
6668 }
6769 property var actions: [
6870 { "id": 123, "displayName": "action1" },
@@ -84,6 +86,7 @@ Item {
8486 "more-screenshots": screenshots,
8587 "rated": rated,
8688 "comments": comments,
89+ "publisher": publisher,
8790 "progressbar_source": progressSource
8891 }
8992 property var actions: [
@@ -109,26 +112,31 @@ Item {
109112 name: "AppPreview"
110113 when: windowShown
111114
115+ function init() {
116+ waitForRendering(appPreview)
117+ }
118+
112119 function cleanup() {
113120 root.calls = new Array();
114121 sendPreviewSpy.clear();
115− var reviewField = findChild(appPreview, "reviewField");
116− reviewField.focus = false;
117− reviewField.text = "";
118− data.rating = rating.value;
122+ // TODO: This doesn't work right now as Reviews are disabled
123+ //var reviewField = findChild(appPreview, "reviewField");
124+ //reviewField.focus = false;
125+ //reviewField.text = "";
126+ //data.rating = rating.value;
119127 dataProgress.infoMap["progressbar_source"].value = "service";
120− var appReviews = findChild(appPreview, "appReviews");
121− appReviews.visible = false;
122− appPreview.keyboardSize = 0;
128+ //var appReviews = findChild(appPreview, "appReviews");
129+ //appReviews.visible = false;
130+ //appPreview.keyboardSize = 0;
123131 }
124132
125133 function test_actions() {
126− var buttons = findChild(appPreview, "gridButtons");
134+ var buttons = findChild(appPreview, "buttonList");
127135 compare(buttons.count, 3, "Not the proper amount of actions detected.");
128136
129137 for(var i = 0; i < buttons.count; i++) {
130− buttons.currentIndex = i;
131− buttons.currentItem.clicked();
138+ var button = findChild(appPreview, "button" + i);
139+ mouseClick(button, 1, 1);
132140 }
133141
134142 var actions = data.actions;
@@ -137,6 +145,14 @@ Item {
137145 }
138146 }
139147
148+ function test_check_app_info() {
149+ var appInfo = findChild(appPreview, "previewHeader");
150+ var titleLabel = findChild(appInfo, "titleLabel");
151+ var subtitleLabel = findChild(appInfo, "subtitleLabel");
152+ compare(titleLabel.text, data.title, "App Title doesn't match.");
153+ compare(subtitleLabel.text, publisher.value, "Publisher name doesn't match.");
154+ }
155+
140156 function test_rated() {
141157 var rated = findChild(appPreview, "ratedLabel");
142158 compare(rated.text, "(120)", "Rates not equal");
@@ -147,13 +163,16 @@ Item {
147163 compare(rated.text, "8 reviews", "Reviews don't match");
148164 }
149165
150− function test_send_review() {
166+ // TODO: Disabled as reviewing and commenting is currently disabled
167+/* function test_send_review() {
151168 var appReviews = findChild(appPreview, "appReviews");
152169 appReviews.sendReview("review");
153170 sendPreviewSpy.wait();
154171 }
155172
156173 function test_review_focus() {
174+ var columnReviewRating = findChild(appPreview, "columnReviewRating");
175+ columnReviewRating.visible = true;
157176 var appReviews = findChild(appPreview, "appReviews");
158177 appReviews.visible = true;
159178 var sendButton = findChild(appReviews, "sendButton");
@@ -194,6 +213,22 @@ Item {
194213 verify(buttons.visible == true);
195214 }
196215
216+ function test_automatic_scroll_on_keyboard_shown() {
217+ waitForRendering(appPreview);
218+ var appReviews = findChild(appPreview, "appReviews");
219+ appReviews.visible = true;
220+
221+ var leftFlickable = findChild(appPreview, "leftFlickable");
222+ leftFlickable.contentY = leftFlickable.contentHeight;
223+ var reviewField = findChild(appReviews, "reviewField");
224+ appPreview.keyboardSize = 400;
225+ appReviews.editing(reviewField);
226+ var newFlickPos = leftFlickable.contentY;
227+ var keyboardY = shell.height - appPreview.keyboardSize;
228+ verify(newFlickPos < keyboardY);
229+ }
230+
231+*/
197232 function test_progress_show() {
198233 appPreview.previewData = dataProgress;
199234 var progress = findChild(appPreview, "progressBar");
@@ -220,20 +255,17 @@ Item {
220255 compare(root.calls[0][1], {"error": "DOWNLOAD ERROR"}, "Data of action not found.");
221256 }
222257
223− function test_automatic_scroll_on_keyboard_shown() {
224− waitForRendering(appPreview);
225− var appReviews = findChild(appPreview, "appReviews");
226− appReviews.visible = true;
258+ function test_placeholderScreenshot() {
259+ var placeholderScreenshot = findChild(appPreview, "placeholderScreenshot");
260+ compare(placeholderScreenshot.visible, false);
227261
228− var leftFlickable = findChild(appPreview, "leftFlickable");
229− leftFlickable.contentY = leftFlickable.contentHeight;
230− var reviewField = findChild(appReviews, "reviewField");
231− appPreview.keyboardSize = 400;
232− appReviews.editing(reviewField);
233− var newFlickPos = leftFlickable.contentY;
234− var keyboardY = shell.height - appPreview.keyboardSize;
235− verify(newFlickPos < keyboardY);
236− }
262+ data.infoMap["more-screenshots"] = [];
263+ appPreview.previewData = data;
264+ tryCompare(placeholderScreenshot, "visible", true);
237265
266+ data.infoMap["more-screenshots"] = screenshots;
267+ appPreview.previewData = data;
268+ tryCompare(placeholderScreenshot, "visible", false);
269+ }
238270 }
239271}
tests/qmltests/Dash/Movie/tst_MoviePreview.qmlnew file+85
@@ -0,0 +1,85 @@
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 "../../../../Dash/Movie"
20+import Unity.Test 0.1 as UT
21+
22+Item {
23+ id: root
24+ width: units.gu(60)
25+ height: units.gu(80)
26+
27+ property var calls: []
28+ property int counter: 0
29+
30+ function get_actions_data() {
31+ return [
32+ { id: 123, displayName: "Play", iconHint: "image://theme/search" },
33+ { id: 456, displayName: "Buy", iconHint: "image://theme/search" },
34+ { id: 789, displayName: "Delete", iconHint: "image//theme/search" }
35+ ]
36+ }
37+
38+ function fake_callback(id, data){
39+ root.calls[root.calls.length] = id;
40+ }
41+
42+ // The component under test
43+ MoviePreview {
44+ id: moviePreview
45+ anchors.fill: parent
46+
47+ previewData: QtObject {
48+ property string rendererName: "preview-movie"
49+ property string title: "Unity Movie"
50+ property string subtitle: "Subtitle"
51+ property string description: "This is the description"
52+ property string image: "../../tests/qmltests/Components/tst_LazyImage/square.png"
53+ property var actions: get_actions_data()
54+ property string year: "2013"
55+ property real rating: 0.3
56+ property int numRatings: 1
57+ property var execute: fake_callback
58+ }
59+ }
60+
61+ UT.UnityTestCase {
62+ name: "MoviePreviewTest"
63+ when: windowShown
64+
65+ function init() {
66+ waitForRendering(moviePreview);
67+ root.calls = new Array();
68+ }
69+
70+ function test_actions() {
71+ var buttons = findChild(moviePreview, "buttonList");
72+ compare(buttons.count, 3);
73+
74+ for(var i = 0; i < buttons.count; i++) {
75+ var button = findChild(moviePreview, "button" + i);
76+ mouseClick(button, 1, 1);
77+ }
78+
79+ var actions = get_actions_data();
80+ for(var i = 0; i < actions.length; i++) {
81+ compare(root.calls[i], actions[i].id);
82+ }
83+ }
84+ }
85+}
tests/qmltests/Dash/Video/tst_VideoPreview.qmldeleted−63
@@ -1,63 +0,0 @@
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 "../../../../Dash/Video"
20−import Unity.Test 0.1 as UT
21−
22−Item {
23− id: root
24− width: units.gu(60)
25− height: units.gu(80)
26−
27− SignalSpy {
28− id: previewClickedSpy
29− target: preview
30− signalName: "previewImageClicked"
31− }
32−
33− // The component under test
34− VideoPreview {
35− id: preview
36− anchors.fill: parent
37− }
38−
39− UT.UnityTestCase {
40− name: "VideoPreview"
41− when: windowShown
42−
43− function test_play_button_data() {
44− return [
45− {tag: "playable", playable: true},
46− {tag: "not playable", playable: false}
47− ]
48− }
49−
50− function test_play_button(data) {
51− var playButton = findChild(preview, "playButton")
52− preview.playable = data.playable
53− compare(playButton.visible, data.playable)
54− }
55−
56− function test_play_button_click() {
57− preview.playable = true
58− var playButton = findChild(preview, "playButton")
59− mouseClick(playButton, 1, 1)
60− tryCompare(previewClickedSpy, "count", 1)
61− }
62− }
63−}
tests/qmltests/Dash/tst_DashPreview.qml+66−19
@@ -31,15 +31,38 @@ Item {
3131 DashPreview {
3232 id: preview
3333 anchors.fill: parent
34− title: "Testing rocks, debugging sucks!"
3534
36− buttons: Row {
35+ previewImages: Rectangle {
36+ width: parent.width
37+ height: units.gu(20)
38+ color: "honeydew"
39+ Label {
40+ anchors.centerIn: parent
41+ text: "Preview images"
42+ }
43+ }
44+
45+ header: Rectangle {
46+ width: parent.width
47+ height: units.gu(10)
48+ color: "papayawhip"
49+ Label {
50+ anchors.centerIn: parent
51+ text: "Caption label"
52+ }
53+ }
54+
55+ actions: Row {
3756 width: parent.width
3857 height: units.gu(5)
3958 Rectangle {
4059 width: parent.width / 3
4160 height: parent.height
4261 color: "blue"
62+ Label {
63+ anchors.centerIn: parent
64+ text: "Button 1"
65+ }
4366 MouseArea {
4467 id: buttonMouseArea
4568 objectName: "buttonMouseArea"
@@ -51,12 +74,15 @@ Item {
5174 width: parent.width / 3
5275 height: parent.height
5376 color: "green"
77+ Label {
78+ anchors.centerIn: parent
79+ text: "Button 2"
80+ }
81+
5482 }
5583 }
5684
57− header: Label { text: "Caption label" }
58−
59− body: Column {
85+ description: Column {
6086 id: testContent
6187 objectName: "testContent"
6288 width: parent.width
@@ -65,16 +91,38 @@ Item {
6591 width: parent.width
6692 height: parent.height / 3
6793 color: "green"
94+ Label {
95+ anchors.centerIn: parent
96+ text: "Description part 1"
97+ }
6898 }
6999 Rectangle {
70100 width: parent.width
71101 height: parent.height / 3
72102 color: "red"
103+ Label {
104+ anchors.centerIn: parent
105+ text: "Description part 2"
106+ }
73107 }
74108 Rectangle {
75109 width: parent.width
76110 height: parent.height / 3
77111 color: "blue"
112+ Label {
113+ anchors.centerIn: parent
114+ text: "Description part 3"
115+ }
116+ }
117+ }
118+
119+ ratings: Rectangle {
120+ objectName: "ratings"
121+ width: parent.width
122+ height: units.gu(20)
123+ Label {
124+ anchors.centerIn: parent
125+ text: "Ratings"
78126 }
79127 }
80128 }
@@ -95,42 +143,41 @@ Item {
95143 name: "DashPreview"
96144 when: windowShown
97145
98− function test_close() {
99− var title = findChild(preview, "titleLabel")
100− mouseClick(title, 1, 1)
101− compare(closeSpy.count, 1, "Close signal not emitted")
102− }
103−
104146 function test_columns_data() {
105147 return [
106148 {tag: "1 columns", width: units.gu(5), height: units.gu(10), columns: 1},
107− {tag: "2 columns", width: units.gu(50), height: units.gu(10), columns: 2}
149+ {tag: "3 columns", width: units.gu(50), height: units.gu(10), columns: 3}
108150 ]
109151 }
110152
111153 function test_columns(data) {
112154 var leftCol = findChild(preview, "leftColumn")
155+ var centerCol = findChild(preview, "centerColumn")
113156 var rightCol = findChild(preview, "rightColumn")
114157
115158 root.width = data.width
116159 root.height = data.height
117160
118− // there are 2 columns in DashPreview. On portrait form factors
119− // only the left one is used and the right one should be empty.
120− // to find out if the content is in the correct column, we get a
161+ // there are 3 columns in DashPreview. On portrait form factors
162+ // only the left one is used and the center and right ones should be empty.
163+ // To find out if the content is in the correct column, we get a
121164 // reference to the column objects and search only the subtree
122165 // to see if the content is in the correct column.
123− // 1 colum -> content should be in leftColumn
124− // 2 colums -> content should be in rightColumn
166+ // 1 colum -> all content should be in leftColumn
167+ // 3 colums -> content should be in centerColumn, rating in rightColumn
125168
126169 switch(data.columns) {
127170 case 1:
128171 var testContent = findChild(leftCol, "testContent")
129172 compare(testContent.objectName, "testContent")
173+ testContent = findChild(leftCol, "ratings")
174+ compare(testContent.objectName, "ratings")
130175 break
131− case 2:
132− var testContent = findChild(rightCol, "testContent")
176+ case 3:
177+ var testContent = findChild(centerCol, "testContent")
133178 compare(testContent.objectName, "testContent")
179+ testContent = findChild(rightCol, "ratings")
180+ compare(testContent.objectName, "ratings")
134181 break
135182 }
136183
tests/qmltests/Dash/tst_GenericPreview.qmlnew file+116
@@ -0,0 +1,116 @@
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 "../../../Dash/Generic"
20+import Unity.Test 0.1 as UT
21+
22+Item {
23+ id: root
24+ width: units.gu(60)
25+ height: units.gu(80)
26+
27+ property var calls: []
28+ property int counter: 0
29+
30+ function get_actions_data() {
31+ return [
32+ { id: 123, displayName: "Button 1", iconHint: "image://theme/search" },
33+ { id: 456, displayName: "Button 2", iconHint: "image://theme/search" },
34+ { id: 789, displayName: "Button 3", iconHint: "image://theme/search" }
35+ ]
36+ }
37+
38+ function fake_callback(id, data){
39+ root.calls[root.calls.length] = id;
40+ }
41+
42+ // The component under test
43+ GenericPreview {
44+ id: genericPreview
45+ anchors.fill: parent
46+
47+ previewData: QtObject {
48+ id: dataObject
49+ property string rendererName: "preview-generic"
50+ property string title: "Unity Generic Preview"
51+ property string subtitle: "Subtitle"
52+ property string description: "This is the description"
53+ property string image: "../../tests/qmltests/Components/tst_LazyImage/square.png"
54+ property var actions: get_actions_data()
55+ property string year: "2013"
56+ property var execute: fake_callback
57+ property var infoHints: [{displayName: "info 1", value: "value 1"},
58+ {displayName: "info 2", value: "value 2"}
59+ ]
60+ }
61+ }
62+
63+ UT.UnityTestCase {
64+ name: "GenericPreviewTest"
65+ when: windowShown
66+
67+ function init() {
68+ waitForRendering(genericPreview)
69+ root.calls = new Array();
70+ }
71+
72+ function test_actions() {
73+ var buttons = findChild(genericPreview, "buttonList");
74+ compare(buttons.count, 3);
75+
76+ for(var i = 0; i < buttons.count; i++) {
77+ var button = findChild(genericPreview, "button" + i);
78+ mouseClick(button, 1, 1);
79+ }
80+
81+ var actions = get_actions_data();
82+ for(var i = 0; i < actions.length; i++) {
83+ compare(root.calls[i], actions[i].id);
84+ }
85+ }
86+
87+ function test_title() {
88+ var titleLabel = findChild(genericPreview, "titleLabel");
89+ compare(titleLabel.text, dataObject.title)
90+ }
91+
92+ function test_subtitle() {
93+ var subtitleLabel = findChild(genericPreview, "subtitleLabel");
94+ compare(subtitleLabel.text, dataObject.subtitle)
95+ }
96+
97+ function test_image() {
98+ var image = findChild(genericPreview, "genericPreviewImage");
99+ tryCompare(image, "height", genericPreview.width - units.gu(6))
100+ }
101+
102+ function test_infoHints() {
103+ var infoHintColumn = findChild(genericPreview, "infoHintColumn")
104+ var infoHintRepeater = findChild(genericPreview, "infoHintRepeater")
105+ compare(infoHintRepeater.count, dataObject.infoHints.length)
106+
107+ for (var i = 0; i < dataObject.infoHints.length; ++i) {
108+ var infoItem = findChild(infoHintColumn, "infoHintItem" + i)
109+ var displayName = findChild(infoItem, "displayNameLabel")
110+ compare(displayName.text, dataObject.infoHints[i].displayName)
111+ var value = findChild(infoItem, "valueLabel")
112+ compare(value.text, dataObject.infoHints[i].value)
113+ }
114+ }
115+ }
116+}