6#include "TourPlayback.h"
12#include "MarbleDebug.h"
14#include "PopupLayer.h"
15#include "GeoDataPoint.h"
16#include "GeoDataPlacemark.h"
17#include "GeoDataPlaylist.h"
18#include "GeoDataTour.h"
19#include "GeoDataWait.h"
20#include "GeoDataFlyTo.h"
21#include "GeoDataLookAt.h"
22#include "GeoDataTourControl.h"
23#include "GeoDataSoundCue.h"
24#include "GeoDataAnimatedUpdate.h"
26#include "GeoDataTreeModel.h"
27#include "PlaybackFlyToItem.h"
28#include "PlaybackAnimatedUpdateItem.h"
29#include "PlaybackWaitItem.h"
30#include "PlaybackTourControlItem.h"
31#include "PlaybackSoundCueItem.h"
32#include "SerialTrack.h"
33#include "SoundTrack.h"
34#include "AnimatedUpdateTrack.h"
39class TourPlaybackPrivate
42 TourPlaybackPrivate();
43 ~TourPlaybackPrivate();
47 SerialTrack m_mainTrack;
50 GeoDataFlyTo m_mapCenter;
55TourPlaybackPrivate::TourPlaybackPrivate() :
64TourPlaybackPrivate::~TourPlaybackPrivate()
66 qDeleteAll(m_soundTracks);
67 qDeleteAll(m_animatedUpdateTracks);
70TourPlayback::TourPlayback(
QObject *parent) :
72 d(new TourPlaybackPrivate())
74 connect( &d->m_mainTrack, SIGNAL(centerOn(GeoDataCoordinates)),
this, SLOT(centerOn(GeoDataCoordinates)) );
75 connect( &d->m_mainTrack, SIGNAL(progressChanged(
double)),
this, SIGNAL(progressChanged(
double)) );
76 connect( &d->m_mainTrack, SIGNAL(finished()),
this, SLOT(stopTour()) );
77 connect( &d->m_mainTrack, SIGNAL(itemFinished(
int)),
this, SLOT(handleFinishedItem(
int)) );
82TourPlayback::~TourPlayback()
88void TourPlayback::handleFinishedItem(
int index )
90 emit itemFinished( index );
93void TourPlayback::stopTour()
95 for( SoundTrack* track: d->m_soundTracks ){
97 track->setPaused(
false );
99 for(
int i = d->m_animatedUpdateTracks.size()-1; i >= 0; i-- ){
100 d->m_animatedUpdateTracks[ i ]->stop();
101 d->m_animatedUpdateTracks[ i ]->setPaused(
false );
106void TourPlayback::showBalloon( GeoDataPlacemark* placemark )
108 GeoDataPoint* point =
static_cast<GeoDataPoint*
>( placemark->geometry() );
110 d->m_widget->popupLayer()->setContent( placemark->description(), d->m_baseUrl );
111 d->m_widget->popupLayer()->setVisible(
true );
112 d->m_widget->popupLayer()->setSize(
QSizeF(500, 520));
115void TourPlayback::hideBalloon()
118 d->m_widget->popupLayer()->setVisible(
false );
122bool TourPlayback::isPlaying()
const
127void TourPlayback::setMarbleWidget(MarbleWidget* widget)
129 d->m_widget = widget;
131 connect(
this, SIGNAL(added(GeoDataContainer*,GeoDataFeature*,
int)),
132 d->m_widget->model()->treeModel(), SLOT(addFeature(GeoDataContainer*,GeoDataFeature*,
int)) );
133 connect(
this, SIGNAL(removed(GeoDataFeature*)),
134 d->m_widget->model()->treeModel(), SLOT(removeFeature(GeoDataFeature*)) );
135 connect(
this, SIGNAL(updated(GeoDataFeature*)),
136 d->m_widget->model()->treeModel(), SLOT(updateFeature(GeoDataFeature*)) );
139void TourPlayback::setBaseUrl(
const QUrl &baseUrl )
141 d->m_baseUrl = baseUrl;
144QUrl TourPlayback::baseUrl()
const
149void TourPlayback::centerOn(
const GeoDataCoordinates &coordinates )
152 GeoDataLookAt lookat;
153 lookat.setCoordinates( coordinates );
154 lookat.setRange( coordinates.altitude() );
155 d->m_widget->flyTo( lookat, Instant );
159void TourPlayback::setTour(GeoDataTour *tour)
170void TourPlayback::play()
173 GeoDataLookAt* lookat =
new GeoDataLookAt( d->m_widget->lookAt() );
174 lookat->setAltitude( lookat->range() );
175 d->m_mapCenter.setView( lookat );
176 d->m_mainTrack.play();
177 for( SoundTrack* track: d->m_soundTracks) {
180 for( AnimatedUpdateTrack* track: d->m_animatedUpdateTracks) {
185void TourPlayback::pause()
188 d->m_mainTrack.pause();
189 for( SoundTrack* track: d->m_soundTracks) {
192 for( AnimatedUpdateTrack* track: d->m_animatedUpdateTracks) {
197void TourPlayback::stop()
200 d->m_mainTrack.stop();
201 for( SoundTrack* track: d->m_soundTracks) {
204 for(
int i = d->m_animatedUpdateTracks.size()-1; i >= 0; i-- ){
205 d->m_animatedUpdateTracks[ i ]->stop();
210void TourPlayback::seek(
double value )
212 double const offset = qBound( 0.0, value, d->m_mainTrack.duration() );
213 d->m_mainTrack.seek( offset );
214 for( SoundTrack* track: d->m_soundTracks ){
215 track->seek( offset );
217 for( AnimatedUpdateTrack* track: d->m_animatedUpdateTracks ){
218 track->seek( offset );
222int TourPlayback::mainTrackSize()
224 return d->m_mainTrack.size();
227PlaybackItem* TourPlayback::mainTrackItemAt(
int i )
229 return d->m_mainTrack.at( i );
232void TourPlayback::updateTracks()
236 for(
int i = 0; i < d->m_tour->playlist()->size(); i++){
237 GeoDataTourPrimitive* primitive = d->m_tour->playlist()->primitive( i );
238 if (
const auto flyTo = geodata_cast<GeoDataFlyTo>(primitive)){
239 d->m_mainTrack.append(
new PlaybackFlyToItem( flyTo ) );
240 delay += flyTo->duration();
242 else if (
const auto wait = geodata_cast<GeoDataWait>(primitive)) {
243 d->m_mainTrack.append(
new PlaybackWaitItem( wait ) );
244 delay += wait->duration();
246 else if (
const auto tourControl = geodata_cast<GeoDataTourControl>(primitive)) {
247 d->m_mainTrack.append(
new PlaybackTourControlItem( tourControl ) );
249 else if (
const auto soundCue = geodata_cast<GeoDataSoundCue>(primitive)) {
250 PlaybackSoundCueItem *item =
new PlaybackSoundCueItem( soundCue );
251 SoundTrack *track =
new SoundTrack( item );
252 track->setDelayBeforeTrackStarts( delay );
253 d->m_soundTracks.append( track );
255 else if (
const auto animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(primitive)) {
256 PlaybackAnimatedUpdateItem *item =
new PlaybackAnimatedUpdateItem( animatedUpdate );
257 AnimatedUpdateTrack *track =
new AnimatedUpdateTrack( item );
258 track->setDelayBeforeTrackStarts( delay + animatedUpdate->delayedStart() );
259 d->m_animatedUpdateTracks.append( track );
260 connect( track, SIGNAL(balloonHidden()),
this, SLOT(hideBalloon()) );
261 connect( track, SIGNAL(balloonShown(GeoDataPlacemark*)),
this, SLOT(showBalloon(GeoDataPlacemark*)) );
262 connect( track, SIGNAL(updated(GeoDataFeature*)),
this, SIGNAL(updated(GeoDataFeature*)) );
263 connect( track, SIGNAL(added(GeoDataContainer*,GeoDataFeature*,
int)),
this, SIGNAL(added(GeoDataContainer*,GeoDataFeature*,
int)) );
264 connect( track, SIGNAL(removed(
const GeoDataFeature*)),
this, SIGNAL(removed(
const GeoDataFeature*)) );
267 Q_ASSERT( d->m_widget );
268 GeoDataLookAt* lookat =
new GeoDataLookAt( d->m_widget->lookAt() );
269 lookat->setAltitude( lookat->range() );
270 d->m_mapCenter.setView( lookat );
271 PlaybackFlyToItem* mapCenterItem =
new PlaybackFlyToItem( &d->m_mapCenter );
272 PlaybackFlyToItem* before = mapCenterItem;
273 for (
int i=0; i<d->m_mainTrack.size(); ++i ) {
274 PlaybackFlyToItem* item = qobject_cast<PlaybackFlyToItem*>( d->m_mainTrack.at(i) );
276 item->setBefore( before );
280 PlaybackFlyToItem*
next =
nullptr;
281 for (
int i=d->m_mainTrack.size()-1; i>=0; --i ) {
282 PlaybackFlyToItem* item = qobject_cast<PlaybackFlyToItem*>( d->m_mainTrack.at(i) );
284 item->setNext( next );
290void TourPlayback::clearTracks()
292 d->m_mainTrack.clear();
293 qDeleteAll(d->m_soundTracks);
294 qDeleteAll(d->m_animatedUpdateTracks);
295 d->m_soundTracks.clear();
296 d->m_animatedUpdateTracks.clear();
299double TourPlayback::duration()
const
301 return d->m_mainTrack.duration();
306#include "moc_TourPlayback.cpp"
This file contains the headers for MarbleModel.
void stop(Ekos::AlignState mode)
const QList< QKeySequence > & next()
Binds a QML item to a specific geodetic location in screen coordinates.
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)