on xenial help sign in
Add a PreviewSingleton module to store some data for previews (LP: #1595235)
385fda6Andrea Cimitan
qml/Dash/GenericScopeView.qml+4
@@ -23,6 +23,7 @@ import Unity 0.2
23import Dash 0.1
23import Dash 0.1
24import "../Components"
24import "../Components"
25import "../Components/ListItems" as ListItems
25import "../Components/ListItems" as ListItems
26+import "Previews/PreviewSingleton"
26
27
27FocusScope {
28FocusScope {
28 id: scopeView
29 id: scopeView
@@ -824,6 +825,9 @@ FocusScope {
824 }
825 }
825
826
826 function closeSubPage() {
827 function closeSubPage() {
828+ if (subPage == "preview") {
829+ PreviewSingleton.widgetExtraData = new Object();
830+ }
827 open = false;
831 open = false;
828 }
832 }
829
833
qml/Dash/Previews/PreviewInlineVideo.qml+47
@@ -18,6 +18,7 @@ import QtQuick 2.4
18import QtMultimedia 5.0
18import QtMultimedia 5.0
19import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
20import Ubuntu.Thumbnailer 0.1
20import Ubuntu.Thumbnailer 0.1
21+import "PreviewSingleton"
21import "../../Components"
22import "../../Components"
22import "../../Components/MediaServices"
23import "../../Components/MediaServices"
23
24
@@ -36,9 +37,35 @@ PreviewWidget {
36 orientationLock: services.fullscreen
37 orientationLock: services.fullscreen
37
38
38 property alias rootItem: services.rootItem
39 property alias rootItem: services.rootItem
40+ readonly property string widgetExtraDataKey: services.source.toString()
41+
42+ onWidgetExtraDataKeyChanged: {
43+ root.restorePlaybackState();
44+ }
45+
46+ function seek() {
47+ services.mediaPlayer.seek(services.initialPosition);
48+ services.initialPosition = -1;
49+ }
50+
51+ function storePlaybackState() {
52+ if ((services.mediaPlayer.duration - services.mediaPlayer.position) < 1000) {
53+ // we're at the end of the video
54+ PreviewSingleton.widgetExtraData[widgetExtraDataKey] = 0;
55+ } else {
56+ PreviewSingleton.widgetExtraData[widgetExtraDataKey] = services.mediaPlayer.position;
57+ }
58+ }
59+
60+ function restorePlaybackState() {
61+ if (PreviewSingleton.widgetExtraData[widgetExtraDataKey] > 0) {
62+ services.initialPosition = PreviewSingleton.widgetExtraData[widgetExtraDataKey];
63+ }
64+ }
39
65
40 MediaServices {
66 MediaServices {
41 id: services
67 id: services
68+ objectName: "services"
42 width: parent.width
69 width: parent.width
43
70
44 actions: sharingAction
71 actions: sharingAction
@@ -47,8 +74,28 @@ PreviewWidget {
47 fullscreen: false
74 fullscreen: false
48 maximumEmbeddedHeight: rootItem.height / 2
75 maximumEmbeddedHeight: rootItem.height / 2
49
76
77+ property int initialPosition: -1
78+
79+ readonly property var mediaPlayer: footer.mediaPlayer
80+ readonly property url source: mediaPlayer.source
81+ readonly property int position: mediaPlayer.position
82+
50 onClose: fullscreen = false
83 onClose: fullscreen = false
51
84
85+ onPositionChanged: {
86+ if (mediaPlayer.playbackState === MediaPlayer.StoppedState) return;
87+ root.storePlaybackState();
88+ }
89+
90+ Connections {
91+ target: services.mediaPlayer
92+ ignoreUnknownSignals: true
93+ onPlaying: {
94+ // at the first playback of the file, do a seek()
95+ if (services.initialPosition > 0) root.seek();
96+ }
97+ }
98+
52 Action {
99 Action {
53 id: sharingAction
100 id: sharingAction
54 iconName: "share"
101 iconName: "share"
qml/Dash/Previews/PreviewSingleton/PreviewSingleton.qmlnew file+22
@@ -0,0 +1,22 @@
1+/*
2+ * Copyright (C) 2016 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+pragma Singleton
18+import QtQuick 2.4
19+
20+QtObject {
21+ property var widgetExtraData: new Object();
22+}
qml/Dash/Previews/PreviewSingleton/qmldirnew file+1
@@ -0,0 +1 @@
1+singleton PreviewSingleton 1.0 PreviewSingleton.qml
tests/mocks/QtMultimedia/mediaplayer.cpp+1
@@ -161,6 +161,7 @@ void MediaPlayer::play()
161 if (m_playbackState != PlayingState) {
161 if (m_playbackState != PlayingState) {
162 m_playbackState = PlayingState;
162 m_playbackState = PlayingState;
163 Q_EMIT playbackStateChanged(m_playbackState);
163 Q_EMIT playbackStateChanged(m_playbackState);
164+ Q_EMIT playing();
164
165
165 m_timer.start();
166 m_timer.start();
166 }
167 }
tests/mocks/QtMultimedia/mediaplayer.h+1
@@ -131,6 +131,7 @@ public Q_SLOTS:
131
131
132Q_SIGNALS:
132Q_SIGNALS:
133 void playlistChanged();
133 void playlistChanged();
134+ void playing();
134 void sourceChanged(const QUrl &source);
135 void sourceChanged(const QUrl &source);
135 void playbackStateChanged(PlaybackState playbackState);
136 void playbackStateChanged(PlaybackState playbackState);
136 void positionChanged(int position);
137 void positionChanged(int position);
tests/qmltests/Dash/Previews/tst_PreviewInlineVideo.qml+43
@@ -76,6 +76,23 @@ Rectangle {
76
76
77 rootItem: inner
77 rootItem: inner
78 }
78 }
79+
80+ Loader {
81+ id: videoPlaybackLoader
82+ anchors {
83+ left: parent.left
84+ right: parent.right
85+ top: videoPlayback.bottom
86+ topMargin: units.gu(2)
87+ }
88+
89+ sourceComponent: PreviewInlineVideo {
90+ width: parent.width
91+ widgetData: widgetData0
92+
93+ rootItem: inner
94+ }
95+ }
79 }
96 }
80
97
81 }
98 }
@@ -98,6 +115,11 @@ Rectangle {
98 }
115 }
99 }
116 }
100
117
118+ SignalSpy {
119+ id: spy
120+ signalName: "playing"
121+ }
122+
101 UT.UnityTestCase {
123 UT.UnityTestCase {
102 name: "PreviewInlineVideoTest"
124 name: "PreviewInlineVideoTest"
103 when: windowShown
125 when: windowShown
@@ -110,5 +132,26 @@ Rectangle {
110 var screenshotSource = screenshot.source
132 var screenshotSource = screenshot.source
111 compare(screenshotSource.toString(), "file:///test-video2-screenshot");
133 compare(screenshotSource.toString(), "file:///test-video2-screenshot");
112 }
134 }
135+
136+ function test_singleton() {
137+ var services = findChild(videoPlaybackLoader, "services");
138+ spy.clear();
139+ spy.target = services.mediaPlayer;
140+ mouseClick(videoPlaybackLoader, videoPlaybackLoader.width / 2, videoPlaybackLoader.height / 2);
141+ tryCompare(spy, "count", 1);
142+ tryCompareFunction(function() { return services.position > 3000; }, true);
143+
144+ // Simulate widget being destroyed and recreated
145+ videoPlaybackLoader.active = false;
146+ videoPlaybackLoader.active = true;
147+
148+ services = findChild(videoPlaybackLoader, "services");
149+ spy.clear();
150+ spy.target = services.mediaPlayer;
151+ compare(services.position, 0);
152+ mouseClick(videoPlaybackLoader, videoPlaybackLoader.width / 2, videoPlaybackLoader.height / 2);
153+ tryCompare(spy, "count", 1);
154+ tryCompareFunction(function() { return services.position > 3000; }, true, 1000);
155+ }
113 }
156 }
114}
157}