on xenial help sign in
Added music preview.

Approved by PS Jenkins bot, Michał Sawicz.

commit25523bd6d22b90d4be6850e50c9d3b53ca961ead authorMichael Zanetti <michael.zanetti@canonical.com> dateFri 29 Nov 2013, 14:39 (13 years ago) parent8e6ce656285a74
16 files changed+661
Dash/DashPreview.qml+1 Dash/GenericScopeView.qml+1 Dash/Music/MusicPreview.qml+203 Dash/Music/graphics/music_progress_bg.png Dash/PreviewDelegateMapper.qml+1 debian/control+1 tests/mocks/CMakeLists.txt+1 tests/mocks/QtMultimedia/CMakeLists.txt+19 tests/mocks/QtMultimedia/audio.cpp+107 tests/mocks/QtMultimedia/audio.h+78 tests/mocks/QtMultimedia/plugin.cpp+28 tests/mocks/QtMultimedia/plugin.h+34 tests/mocks/QtMultimedia/qmldir+2 tests/qmltests/CMakeLists.txt+1 tests/qmltests/Dash/Music/tst_MusicPreview.qml+174 tests/qmltests/Dash/tst_GenericScopeView.qml+10
Dash/DashPreview.qml+1
@@ -25,6 +25,7 @@ Item {
2525 property alias showProcessingAction: waitingForActionMouseArea.enabled
2626
2727 property real previewWidthRatio: 0.5
28+ property bool isCurrent: false
2829
2930 property Component previewImages
3031 property Component header
Dash/GenericScopeView.qml+1
@@ -527,6 +527,7 @@ FocusScope {
527527 onLoaded: {
528528 if (previewListView.onScreen && previewData !== undefined) {
529529 item.previewData = Qt.binding(function() { return previewData })
530+ item.isCurrent = Qt.binding(function() { return ListView.isCurrentItem })
530531 }
531532 }
532533
Dash/Music/MusicPreview.qmlnew file+203
@@ -0,0 +1,203 @@
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 QtMultimedia 5.0
19+import Ubuntu.Components 0.1
20+import Ubuntu.Components.ListItems 0.1
21+import ".."
22+import "../Generic"
23+import "../../Components"
24+import "../Previews"
25+
26+GenericPreview {
27+ id: root
28+
29+ previewImages: previewImageComponent
30+ header: headerComponent
31+ description: descriptionComponent
32+
33+ Component {
34+ id: previewImageComponent
35+ LazyImage {
36+ height: units.gu(22)
37+ scaleTo: "height"
38+ source: previewData ? previewData.image : ""
39+ initialHeight: height
40+ initialWidth: height
41+ }
42+ }
43+
44+ Component {
45+ id: headerComponent
46+ Header {
47+ title: previewData.title
48+ subtitle: previewData.subtitle
49+ }
50+ }
51+
52+ Component {
53+ id: descriptionComponent
54+
55+ Item {
56+ height: childrenRect.height
57+ Audio {
58+ id: audioPlayer
59+ objectName: "audioPlayer"
60+ property real progress: audioPlayer.position / audioPlayer.duration
61+
62+ property Item playingItem
63+
64+ Component.onDestruction: {
65+ audioPlayer.stop();
66+ }
67+
68+ onErrorStringChanged: console.warn("Audio player error:", errorString)
69+
70+ }
71+
72+ Connections {
73+ target: root
74+ onIsCurrentChanged: {
75+ if (!root.isCurrent) {
76+ audioPlayer.stop();
77+ }
78+ }
79+ }
80+
81+ Column {
82+ anchors { left: parent.left; right: parent.right }
83+ visible: trackRepeater.count > 0
84+
85+ ThinDivider {
86+ objectName: "topDivider"
87+ anchors { left: parent.left; right: parent.right }
88+ }
89+
90+ Repeater {
91+ id: trackRepeater
92+ objectName: "trackRepeater"
93+
94+ model: previewData.tracks
95+
96+ delegate: Item {
97+ id: trackItem
98+ objectName: "trackItem" + index
99+ anchors { left: parent.left; right: parent.right }
100+ height: units.gu(5)
101+ property bool isPlayingItem: audioPlayer.playingItem == trackItem
102+
103+ function play() {
104+ audioPlayer.stop();
105+ // Make sure we change the source, even if two items point to the same uri location
106+ audioPlayer.source = "";
107+ audioPlayer.source = model.uri;
108+ audioPlayer.playingItem = trackItem;
109+ audioPlayer.play();
110+ }
111+
112+ Row {
113+ id: trackRow
114+ width: parent.width
115+ spacing: units.gu(1)
116+ property int column1Width: units.gu(3)
117+ property int column2Width: width - (2 * spacing) - column1Width - column3Width
118+ property int column3Width: units.gu(4)
119+ anchors.verticalCenter: parent.verticalCenter
120+
121+ Button {
122+ objectName: "playButton"
123+ width: trackRow.column1Width
124+ height: width
125+ iconSource: audioPlayer.playbackState == Audio.PlayingState && trackItem.isPlayingItem ? "image://theme/media-playback-pause" : "image://theme/media-playback-start"
126+
127+ // Can't be "transparent" or "#00xxxxxx" as the button optimizes away the surrounding shape
128+ // FIXME when this is resolved: https://bugs.launchpad.net/ubuntu-ui-toolkit/+bug/1251685
129+ color: "#01000000"
130+
131+ onClicked: {
132+ if (trackItem.isPlayingItem) {
133+ if (audioPlayer.playbackState == Audio.PlayingState) {
134+ audioPlayer.pause();
135+ } else if (audioPlayer.playbackState == Audio.PausedState){
136+ audioPlayer.play();
137+ }
138+ } else {
139+ trackItem.play();
140+ }
141+ }
142+ }
143+
144+ Label {
145+ objectName: "trackTitleLabel"
146+ fontSize: "small"
147+ opacity: 0.9
148+ color: "white"
149+ horizontalAlignment: Text.AlignLeft
150+ anchors.verticalCenter: parent.verticalCenter
151+ width: parent.column2Width
152+ text: title
153+ style: Text.Raised
154+ styleColor: "black"
155+ elide: Text.ElideRight
156+
157+ UbuntuShape {
158+ id: progressBarFill
159+ objectName: "progressBarFill"
160+ color: UbuntuColors.orange
161+ anchors.left: progressBarImage.left
162+ anchors.right: progressBarImage.right
163+ anchors.verticalCenter: progressBarImage.verticalCenter
164+ height: units.dp(2)
165+ anchors.margins: units.dp(2)
166+ anchors.rightMargin: maxWidth - (maxWidth * audioPlayer.progress) + units.dp(2)
167+ visible: progressBarImage.visible
168+ property int maxWidth: progressBarImage.width - units.dp(4)
169+ }
170+
171+ Image {
172+ id: progressBarImage
173+ anchors { left: parent.left; top: parent.bottom; right: parent.right }
174+ height: units.dp(6)
175+ visible: audioPlayer.playbackState != Audio.StoppedState && trackItem.isPlayingItem && model.length.length > 0
176+ source: "graphics/music_progress_bg.png"
177+ }
178+ }
179+
180+ Label {
181+ id: valueLabel
182+ objectName: "timeLabel"
183+ fontSize: "small"
184+ opacity: 0.9
185+ color: "white"
186+ anchors.verticalCenter: parent.verticalCenter
187+ horizontalAlignment: Text.AlignRight
188+ width: parent.column3Width
189+ text: length
190+ style: Text.Raised
191+ styleColor: "black"
192+ }
193+ }
194+
195+ ThinDivider {
196+ anchors { left: parent.left; bottom: parent.bottom; right: parent.right }
197+ }
198+ }
199+ }
200+ }
201+ }
202+ }
203+}
Dash/Music/graphics/music_progress_bg.pngnew file

Binary file not shown.

Dash/PreviewDelegateMapper.qml+1
@@ -23,6 +23,7 @@ QtObject {
2323 property var previewDelegateMapping: {"preview-generic": genericPreview,
2424 "preview-application": appPreview,
2525 "preview-movie": "Movie/MoviePreview.qml",
26+ "preview-music": "Music/MusicPreview.qml",
2627 }
2728 }
2829
debian/control+1
@@ -34,6 +34,7 @@ Build-Depends: cmake,
3434 qtbase5-private-dev,
3535 qtdeclarative5-dev,
3636 qtdeclarative5-dev-tools,
37+ qtdeclarative5-qtmultimedia-plugin,
3738 qtdeclarative5-private-dev,
3839 qtdeclarative5-qtquick2-plugin,
3940 qtdeclarative5-test-plugin,
tests/mocks/CMakeLists.txt+1
@@ -7,6 +7,7 @@ add_subdirectory(Powerd)
77add_subdirectory(QMenuModel)
88add_subdirectory(Ubuntu)
99add_subdirectory(Unity)
10+add_subdirectory(QtMultimedia)
1011
1112install(
1213 DIRECTORY data
tests/mocks/QtMultimedia/CMakeLists.txtnew file+19
@@ -0,0 +1,19 @@
1+add_library(QtMultimedia-qml MODULE
2+ plugin.cpp
3+ audio.cpp
4+ )
5+
6+qt5_use_modules(QtMultimedia-qml Qml)
7+
8+# copy qmldir file into build directory for shadow builds
9+file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/qmldir"
10+ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}
11+ )
12+
13+install(TARGETS QtMultimedia-qml
14+ DESTINATION ${SHELL_INSTALL_QML}/mocks/QtMultimedia
15+ )
16+
17+install(FILES qmldir
18+ DESTINATION ${SHELL_INSTALL_QML}/mocks/QtMultimedia
19+ )
tests/mocks/QtMultimedia/audio.cppnew file+107
@@ -0,0 +1,107 @@
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+ * Author: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#include "audio.h"
20+
21+Audio::Audio(QObject* parent):
22+ QObject(parent),
23+ m_playbackState(StoppedState)
24+{
25+ qsrand(time(NULL));
26+ m_timer.setInterval(1000);
27+ connect(&m_timer, SIGNAL(timeout()), SLOT(timerEvent()));
28+}
29+
30+QUrl Audio::source() const
31+{
32+ return m_source;
33+}
34+
35+void Audio::setSource(const QUrl &source)
36+{
37+ if (m_source != source) {
38+ m_source = source;
39+ Q_EMIT sourceChanged(source);
40+
41+ m_position = 0;
42+ Q_EMIT positionChanged(m_position);
43+
44+ m_duration = (qrand() % 20000) + 10000;
45+ Q_EMIT durationChanged(m_duration);
46+ }
47+}
48+
49+Audio::PlaybackState Audio::playbackState() const
50+{
51+ return m_playbackState;
52+}
53+
54+int Audio::position() const
55+{
56+ return m_position;
57+}
58+
59+int Audio::duration() const
60+{
61+ return m_duration;
62+}
63+
64+QString Audio::errorString() const
65+{
66+ return QString();
67+}
68+
69+void Audio::pause()
70+{
71+ if (m_playbackState == PlayingState) {
72+ m_playbackState = PausedState;
73+ Q_EMIT playbackStateChanged(m_playbackState);
74+ m_timer.stop();
75+ }
76+}
77+
78+void Audio::play()
79+{
80+ if (m_playbackState != PlayingState && m_source.isValid()) {
81+ m_playbackState = PlayingState;
82+ Q_EMIT playbackStateChanged(m_playbackState);
83+
84+ m_timer.start();
85+ }
86+}
87+
88+void Audio::stop()
89+{
90+ if (m_playbackState != StoppedState) {
91+ m_playbackState = StoppedState;
92+ Q_EMIT playbackStateChanged(m_playbackState);
93+ m_timer.stop();
94+ m_position = 0;
95+ Q_EMIT positionChanged(m_position);
96+ }
97+}
98+
99+void Audio::timerEvent()
100+{
101+ if (m_position + 1000 < m_duration) {
102+ m_position += 1000;
103+ Q_EMIT positionChanged(m_position);
104+ } else {
105+ stop();
106+ }
107+}
tests/mocks/QtMultimedia/audio.hnew file+78
@@ -0,0 +1,78 @@
1+/*
2+ * Copyright (C) 2012,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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#ifndef MOCK_AUDIO_H
20+#define MOCK_AUDIO_H
21+
22+#include <QObject>
23+#include <QUrl>
24+#include <QTimer>
25+
26+class Audio: public QObject
27+{
28+ Q_OBJECT
29+ Q_ENUMS(PlaybackState)
30+ Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
31+ Q_PROPERTY(PlaybackState playbackState READ playbackState NOTIFY playbackStateChanged)
32+ Q_PROPERTY(int position READ position NOTIFY positionChanged)
33+ Q_PROPERTY(int duration READ duration NOTIFY durationChanged)
34+ Q_PROPERTY(QString errorString READ errorString NOTIFY errorStringChanged)
35+public:
36+ enum PlaybackState {
37+ PlayingState,
38+ PausedState,
39+ StoppedState
40+ };
41+
42+ explicit Audio(QObject *parent = 0);
43+
44+ QUrl source() const;
45+ void setSource(const QUrl &source);
46+
47+ PlaybackState playbackState() const;
48+
49+ int position() const;
50+
51+ int duration() const;
52+
53+ QString errorString() const;
54+
55+public Q_SLOTS:
56+ void pause();
57+ void play();
58+ void stop();
59+
60+Q_SIGNALS:
61+ void sourceChanged(const QUrl &source);
62+ void playbackStateChanged(PlaybackState playbackState);
63+ void positionChanged(int position);
64+ void durationChanged(int duration);
65+ void errorStringChanged(const QString &errorString);
66+
67+private Q_SLOTS:
68+ void timerEvent();
69+
70+private:
71+ QUrl m_source;
72+ PlaybackState m_playbackState;
73+ QTimer m_timer;
74+ int m_position;
75+ int m_duration;
76+};
77+
78+#endif
tests/mocks/QtMultimedia/plugin.cppnew file+28
@@ -0,0 +1,28 @@
1+/*
2+ * Copyright (C) 2012,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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#include "plugin.h"
20+#include "audio.h"
21+
22+#include <QtQml/qqml.h>
23+
24+void MockQtMultimediaPlugin::registerTypes(const char *uri)
25+{
26+ Q_ASSERT(uri == QLatin1String("QtMultimedia"));
27+ qmlRegisterType<Audio>(uri, 5, 0, "Audio");
28+}
tests/mocks/QtMultimedia/plugin.hnew file+34
@@ -0,0 +1,34 @@
1+/*
2+ * Copyright (C) 2012,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+ * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17+ */
18+
19+#ifndef MOCK_QTMULTIMEDIA_PLUGIN_H
20+#define MOCK_QTMULTIMEDIA_PLUGIN_H
21+
22+#include <QtQml/QQmlEngine>
23+#include <QtQml/QQmlExtensionPlugin>
24+
25+class MockQtMultimediaPlugin : public QQmlExtensionPlugin
26+{
27+ Q_OBJECT
28+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29+
30+public:
31+ void registerTypes(const char *uri);
32+};
33+
34+#endif
tests/mocks/QtMultimedia/qmldirnew file+2
@@ -0,0 +1,2 @@
1+module QtMultimedia
2+plugin QtMultimedia-qml
tests/qmltests/CMakeLists.txt+1
@@ -49,6 +49,7 @@ add_qml_test(Dash FilterGrids IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMA
4949add_qml_test(Dash/Apps RunningApplicationsGrid IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
5050add_qml_test(Dash/Apps AppPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
5151add_qml_test(Dash/Movie MoviePreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
52+add_qml_test(Dash/Music MusicPreview IMPORT_PATHS ${qmltest_DEFAULT_IMPORT_PATHS} ${CMAKE_BINARY_DIR}/tests/mocks)
5253add_qml_test(Greeter Lockscreen IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
5354 PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/full")
5455add_qml_test(Greeter Tablet IMPORT_PATHS ${CMAKE_BINARY_DIR}/plugins ${qmltest_DEFAULT_IMPORT_PATHS}
tests/qmltests/Dash/Music/tst_MusicPreview.qmlnew file+174
@@ -0,0 +1,174 @@
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/Music"
20+import Unity.Test 0.1 as UT
21+import QtMultimedia 5.0
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(60)
26+ height: units.gu(80)
27+ color: "lightgrey"
28+
29+ MusicPreview {
30+ id: musicPreview
31+ anchors.fill: parent
32+ isCurrent: true
33+
34+ previewData: QtObject {
35+ property string rendererName: "preview-music"
36+ property string title: "Music Preview"
37+ property string subtitle: "Subtitle"
38+ property string description: "This is the description"
39+ property string image: "../../tests/qmltests/Components/tst_LazyImage/square.png"
40+ property var actions: [
41+ { id: 123, displayName: "Play"},
42+ { id: 456, displayName: "Show in folder"}
43+ ]
44+ property var tracks: tracksModel2
45+ }
46+ }
47+
48+ ListModel {
49+ id: tracksModel0
50+ }
51+ ListModel {
52+ id: tracksModel1
53+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound1.ogg"; trackNo: 1; title: "Some track name"; length: "0:30"}
54+ }
55+ ListModel {
56+ id: tracksModel2
57+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound1.ogg"; trackNo: 1; title: "Some track name"; length: "0:30"}
58+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound1.ogg"; trackNo: 2; title: "Some track name"; length: "0:30"}
59+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound2.ogg"; trackNo: 3; title: "Some other track name"; length: "1:23"}
60+ ListElement { uri: "../../tests/qmltests/Dash/Music/data/testsound3.ogg"; trackNo: 4; title: "And another one"; length: "123:45"}
61+ }
62+
63+ UT.UnityTestCase {
64+ name: "MusicPreviewTest"
65+ when: windowShown
66+
67+ function init() {
68+ waitForRendering(musicPreview);
69+ }
70+
71+ function test_tracks_data() {
72+ return [
73+ {tag: "0 tracks", tracksModel: tracksModel0, dividerVisible: false},
74+ {tag: "1 track", tracksModel: tracksModel1, dividerVisible: true},
75+ {tag: "4 track", tracksModel: tracksModel2, dividerVisible: true}
76+ ];
77+ }
78+
79+ function test_tracks(data) {
80+ musicPreview.previewData.tracks = data.tracksModel;
81+ waitForRendering(musicPreview);
82+
83+ var trackRepeater = findChild(musicPreview, "trackRepeater");
84+ compare(trackRepeater.count, data.tracksModel.count)
85+
86+ var topDivider = findChild(musicPreview, "topDivider");
87+ compare(topDivider.visible, data.dividerVisible);
88+
89+ for (var i = 0; i < data.tracksModel.count; ++i) {
90+ var trackItem = findChild(musicPreview, "trackItem" + i);
91+ var titleLabel = findChild(trackItem, "trackTitleLabel");
92+ compare(titleLabel.text, data.tracksModel.get(i).title)
93+ var timeLabel = findChild(trackItem, "timeLabel");
94+ compare(timeLabel.text, data.tracksModel.get(i).length)
95+ }
96+ }
97+
98+ function checkPlayerUri(index) {
99+ var modelFilename = musicPreview.previewData.tracks.get(index).uri.replace(/^.*[\\\/]/, '');
100+ var playerFilename = findInvisibleChild(musicPreview, "audioPlayer").source.toString().replace(/^.*[\\\/]/, '');
101+
102+ compare(modelFilename, playerFilename, "Player source is not set correctly.");
103+ }
104+
105+ function test_playback() {
106+ musicPreview.previewData.tracks = tracksModel2;
107+ waitForRendering(musicPreview);
108+
109+ var track0Item = findChild(musicPreview, "trackItem0");
110+ var track1Item = findChild(musicPreview, "trackItem1");
111+ var track2Item = findChild(musicPreview, "trackItem2");
112+
113+ var track0ProgressBar = findChild(track0Item, "progressBarFill");
114+ var track1ProgressBar = findChild(track1Item, "progressBarFill");
115+ var track2ProgressBar = findChild(track2Item, "progressBarFill");
116+
117+ var track0PlayButton = findChild(track0Item, "playButton");
118+ var track1PlayButton = findChild(track1Item, "playButton");
119+ var track2PlayButton = findChild(track2Item, "playButton");
120+
121+ var audioPlayer = findInvisibleChild(musicPreview, "audioPlayer");
122+
123+ // All progress bars must be hidden in the beginning
124+ compare(track0ProgressBar.visible, false);
125+ compare(track1ProgressBar.visible, false);
126+ compare(track2ProgressBar.visible, false);
127+
128+ // Playing track 0 should make progress bar 0 visible
129+ mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
130+
131+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
132+ checkPlayerUri(0);
133+
134+ tryCompare(track0ProgressBar, "visible", true);
135+ tryCompare(track1ProgressBar, "visible", false);
136+ tryCompare(track2ProgressBar, "visible", false);
137+
138+ // Clicking the button again should pause it. The progress bar should stay visible
139+ mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
140+ tryCompare(audioPlayer, "playbackState", Audio.PausedState);
141+ checkPlayerUri(0);
142+ tryCompare(track0ProgressBar, "visible", true);
143+
144+ // Continue playback
145+ mouseClick(track0PlayButton, track0PlayButton.width / 2, track0PlayButton.height / 2);
146+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
147+ checkPlayerUri(0);
148+
149+ // Playing track 1 should make progress bar 1 visible and hide progress bar 0 again
150+ mouseClick(track1PlayButton, track1PlayButton.width / 2, track1PlayButton.height / 2);
151+
152+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
153+ checkPlayerUri(1);
154+
155+ tryCompare(track0ProgressBar, "visible", false);
156+ tryCompare(track1ProgressBar, "visible", true);
157+ tryCompare(track2ProgressBar, "visible", false);
158+
159+ // Playing track 2 should make progress bar 1 visible and hide progress bar 0 again
160+ mouseClick(track2PlayButton, track2PlayButton.width / 2, track2PlayButton.height / 2);
161+
162+ tryCompare(audioPlayer, "playbackState", Audio.PlayingState);
163+ checkPlayerUri(2);
164+
165+ tryCompare(track0ProgressBar, "visible", false);
166+ tryCompare(track1ProgressBar, "visible", false);
167+ tryCompare(track2ProgressBar, "visible", true);
168+
169+ // Switching away from this preview should make all players shut up!
170+ musicPreview.isCurrent = false
171+ tryCompare(audioPlayer, "playbackState", Audio.StoppedState);
172+ }
173+ }
174+}
tests/qmltests/Dash/tst_GenericScopeView.qml+10
@@ -186,8 +186,18 @@ Item {
186186 true);
187187 tryCompare(nextPreviewItem, "progress", 1);
188188 waitForRendering(nextPreviewItem);
189+ tryCompareFunction(function() {return nextPreviewItem.item !== null}, true);
189190
190191 checkArrowPosition(i);
192+
193+ // Make sure only the new one has isCurrent set to true
194+ compare(nextPreviewItem.item.isCurrent, true);
195+
196+ if (currentPreviewItem.item !== undefined && currentPreviewItem.item !== null) {
197+ compare(currentPreviewItem.item.isCurrent, false);
198+ }
199+
200+ currentPreviewItem = nextPreviewItem;
191201 }
192202 closePreview();
193203 }