8#include "FlyToEditWidget.h"
9#include "SoundCueEditWidget.h"
10#include "TourControlEditWidget.h"
11#include "TourItemDelegate.h"
12#include "WaitEditWidget.h"
14#include "EditPlacemarkDialog.h"
15#include "GeoDataAnimatedUpdate.h"
16#include "GeoDataCamera.h"
17#include "GeoDataChange.h"
18#include "GeoDataCreate.h"
19#include "GeoDataDelete.h"
20#include "GeoDataDocument.h"
21#include "GeoDataDocumentWriter.h"
22#include "GeoDataFlyTo.h"
23#include "GeoDataIconStyle.h"
24#include "GeoDataLookAt.h"
25#include "GeoDataPlacemark.h"
26#include "GeoDataPlaylist.h"
27#include "GeoDataSoundCue.h"
28#include "GeoDataStyle.h"
29#include "GeoDataTour.h"
30#include "GeoDataTourControl.h"
31#include "GeoDataTreeModel.h"
32#include "GeoDataUpdate.h"
33#include "GeoDataWait.h"
34#include "KmlElementDictionary.h"
35#include "MarbleDebug.h"
36#include "MarbleDirs.h"
38#include "MarblePlacemarkModel.h"
40#include "MovieCapture.h"
41#include "ParsingRunnerManager.h"
42#include "PlaybackFlyToItem.h"
43#include "TourCaptureDialog.h"
44#include "TourPlayback.h"
45#include "ui_TourWidget.h"
62class TourWidgetPrivate
65 explicit TourWidgetPrivate(TourWidget *parent);
67 GeoDataFeature *getPlaylistFeature()
const;
68 void updateRootIndex();
72 bool openFile(
const QString &filename);
81 void addRemovePlacemark();
82 void addChangePlacemark();
83 void addTourPrimitive(GeoDataTourPrimitive *primitive);
84 void deleteSelected();
85 void updateButtonsStates();
89 void handlePlaybackProgress(
const double position);
90 void handlePlaybackFinish();
91 GeoDataObject *rootIndexObject()
const;
94 GeoDataTour *findTour(GeoDataFeature *feature)
const;
95 bool openDocument(GeoDataDocument *document);
96 bool saveTourAs(
const QString &filename);
97 bool overrideModifications();
101 MarbleWidget *m_widget;
102 Ui::TourWidget m_tourUi;
103 TourCaptureDialog *m_tourCaptureDialog;
104 TourPlayback m_playback;
105 TourItemDelegate *m_delegate;
108 bool m_isLoopingStopped;
109 GeoDataDocument *m_document;
110 QAction *m_actionToggleLoopPlay;
116 QAction *m_actionAddRemovePlacemark;
117 QAction *m_actionAddChangePlacemark;
120TourWidgetPrivate::TourWidgetPrivate(TourWidget *parent)
123 , m_playback(nullptr)
124 , m_delegate(nullptr)
127 , m_document(nullptr)
130 m_tourUi.setupUi(parent);
131 m_tourUi.m_actionRecord->setEnabled(
false);
133 QAction *separator = m_tourUi.m_toolBarControl->insertSeparator(m_tourUi.m_actionMoveUp);
135 m_addPrimitiveButton->
setIcon(
QIcon(QStringLiteral(
":/marble/flag.png")));
136 m_addPrimitiveButton->setToolTip(
QObject::tr(
"Add FlyTo"));
139 auto addPrimitiveMenu =
new QMenu(q);
141 m_actionAddFlyTo =
new QAction(
QIcon(QStringLiteral(
":/marble/flag.png")),
QObject::tr(
"Add FlyTo"), addPrimitiveMenu);
142 addPrimitiveMenu->addAction(m_actionAddFlyTo);
143 m_actionAddWait =
new QAction(
QIcon(QStringLiteral(
":/marble/player-time.png")),
QObject::tr(
"Add Wait"), addPrimitiveMenu);
144 addPrimitiveMenu->addAction(m_actionAddWait);
145 m_actionAddSoundCue =
new QAction(
QIcon(QStringLiteral(
":/marble/audio-x-generic.png")),
QObject::tr(
"Add SoundCue"), addPrimitiveMenu);
146 addPrimitiveMenu->addAction(m_actionAddSoundCue);
147 addPrimitiveMenu->addSeparator();
148 m_actionAddPlacemark =
new QAction(
QIcon(QStringLiteral(
":/icons/add-placemark.png")),
QObject::tr(
"Add Placemark"), addPrimitiveMenu);
149 addPrimitiveMenu->addAction(m_actionAddPlacemark);
150 m_actionAddRemovePlacemark =
new QAction(
QIcon(QStringLiteral(
":/icons/remove.png")),
QObject::tr(
"Remove placemark"), addPrimitiveMenu);
151 addPrimitiveMenu->addAction(m_actionAddRemovePlacemark);
152 m_actionAddChangePlacemark =
new QAction(
QIcon(QStringLiteral(
":/marble/document-edit.png")),
QObject::tr(
"Change placemark"), addPrimitiveMenu);
153 addPrimitiveMenu->addAction(m_actionAddChangePlacemark);
155 m_actionToggleLoopPlay->setCheckable(
true);
156 m_actionToggleLoopPlay->setChecked(
false);
158 m_tourUi.m_slider->addAction(m_actionToggleLoopPlay);
160 m_addPrimitiveButton->setMenu(addPrimitiveMenu);
161 m_addPrimitiveButton->setEnabled(
false);
163 m_tourUi.m_toolBarControl->insertWidget(separator, m_addPrimitiveButton);
166 QObject::connect(m_addPrimitiveButton, SIGNAL(clicked()), q, SLOT(addFlyTo()));
167 QObject::connect(m_actionAddFlyTo, SIGNAL(triggered()), q, SLOT(addFlyTo()));
169 QObject::connect(m_actionAddSoundCue, SIGNAL(triggered()), q, SLOT(addSoundCue()));
170 QObject::connect(m_actionAddPlacemark, SIGNAL(triggered()), q, SLOT(addPlacemark()));
171 QObject::connect(m_actionAddRemovePlacemark, SIGNAL(triggered()), q, SLOT(addRemovePlacemark()));
172 QObject::connect(m_actionAddChangePlacemark, SIGNAL(triggered()), q, SLOT(addChangePlacemark()));
173 QObject::connect(m_tourUi.m_actionDelete, SIGNAL(triggered()), q, SLOT(deleteSelected()));
174 QObject::connect(m_tourUi.m_actionMoveUp, SIGNAL(triggered()), q, SLOT(moveUp()));
175 QObject::connect(m_tourUi.m_actionMoveDown, SIGNAL(triggered()), q, SLOT(moveDown()));
176 QObject::connect(m_tourUi.m_actionNewTour, SIGNAL(triggered()), q, SLOT(createTour()));
177 QObject::connect(m_tourUi.m_actionOpenTour, SIGNAL(triggered()), q, SLOT(openFile()));
178 QObject::connect(m_tourUi.m_actionSaveTour, SIGNAL(triggered()), q, SLOT(saveTour()));
179 QObject::connect(m_tourUi.m_actionSaveTourAs, SIGNAL(triggered()), q, SLOT(saveTourAs()));
180 QObject::connect(m_tourUi.m_actionRecord, SIGNAL(triggered()), q, SLOT(captureTour()));
182 QObject::connect(&m_playback, SIGNAL(itemFinished(
int)), q, SLOT(setHighlightedItemIndex(
int)));
185TourWidgetPrivate::~TourWidgetPrivate()
192 , d(new TourWidgetPrivate(this))
196 connect(d->m_tourUi.actionPlay, SIGNAL(triggered()),
this, SLOT(togglePlaying()));
197 connect(d->m_tourUi.actionStop, SIGNAL(triggered()),
this, SLOT(stopLooping()));
198 connect(d->m_tourUi.actionStop, SIGNAL(triggered()),
this, SLOT(stopPlaying()));
199 connect(d->m_tourUi.m_slider, SIGNAL(sliderMoved(
int)),
this, SLOT(handleSliderMove(
int)));
201 d->m_tourUi.m_toolBarPlayback->setDisabled(
true);
202 d->m_tourUi.m_slider->setDisabled(
true);
203 d->m_tourUi.m_listView->installEventFilter(
this);
206TourWidget::~TourWidget()
215 Q_ASSERT(watched == d->m_tourUi.m_listView);
216 GeoDataObject *rootObject = d->rootIndexObject();
224 QModelIndexList selectedIndexes = d->m_tourUi.m_listView->selectionModel()->selectedIndexes();
227 if (!selectedIndexes.isEmpty()) {
234 QModelIndexList::iterator
end = selectedIndexes.end() - 1;
235 if (
const GeoDataPlaylist *playlist = (rootObject ? geodata_cast<GeoDataPlaylist>(rootObject) :
nullptr)) {
236 if (
end->row() != playlist->size() - 1) {
244 QModelIndexList::iterator
start = selectedIndexes.begin();
245 if (
start->row() != 0) {
255void TourWidget::setMarbleWidget(MarbleWidget *widget)
257 d->m_widget = widget;
258 delete d->m_delegate;
259 d->m_delegate =
new TourItemDelegate(d->m_tourUi.m_listView, d->m_widget,
this);
261 connect(d->m_delegate, SIGNAL(edited(
QModelIndex)), &d->m_playback, SLOT(updateTracks()));
262 d->m_tourUi.m_listView->setItemDelegate(d->m_delegate);
265void TourWidget::togglePlaying()
267 if (!d->m_playState) {
268 d->m_playState =
true;
271 d->m_playState =
false;
276void TourWidget::startPlaying()
278 setHighlightedItemIndex(0);
279 d->m_isLoopingStopped =
false;
280 d->m_playback.play();
281 d->m_tourUi.actionPlay->setIcon(
QIcon(QStringLiteral(
":/marble/playback-pause.png")));
282 d->m_tourUi.actionPlay->setEnabled(
true);
283 d->m_tourUi.actionStop->setEnabled(
true);
284 d->m_tourUi.m_actionRecord->setEnabled(
false);
285 d->m_delegate->setEditable(
false);
286 d->m_addPrimitiveButton->setEnabled(
false);
287 d->m_playState =
true;
290void TourWidget::pausePlaying()
292 d->m_playback.pause();
293 d->m_tourUi.actionPlay->setIcon(
QIcon(QStringLiteral(
":/marble/playback-play.png")));
294 d->m_tourUi.actionPlay->setEnabled(
true);
295 d->m_tourUi.actionStop->setEnabled(
true);
298void TourWidget::stopPlaying()
301 d->m_playback.stop();
302 d->m_tourUi.actionPlay->setIcon(
QIcon(QStringLiteral(
":/marble/playback-play.png")));
303 d->m_tourUi.actionPlay->setEnabled(
true);
304 d->m_tourUi.m_actionRecord->setEnabled(
true);
305 d->m_tourUi.actionStop->setEnabled(
false);
306 d->m_playState =
false;
307 d->m_delegate->setEditable(
true);
308 d->m_addPrimitiveButton->setEnabled(
true);
311 if (d->m_actionToggleLoopPlay->isChecked() && !d->m_isLoopingStopped) {
316void TourWidget::stopLooping()
318 d->m_isLoopingStopped =
true;
323 if (!d->m_document || !d->m_isChanged) {
330 QObject::tr(
"There are unsaved Tours. Do you want to save your changes?"),
346void TourWidget::handleSliderMove(
int value)
349 d->m_playback.seek(value / 100.0);
350 QTime nullTime(0, 0, 0);
355void TourWidgetPrivate::openFile()
357 if (overrideModifications()) {
360 ParsingRunnerManager manager(m_widget->model()->pluginManager());
361 GeoDataDocument *document = manager.openFile(filename);
363 openDocument(document);
368bool TourWidgetPrivate::openFile(
const QString &filename)
370 if (overrideModifications()) {
372 ParsingRunnerManager manager(m_widget->model()->pluginManager());
373 GeoDataDocument *document = manager.openFile(filename);
375 return openDocument(document);
382GeoDataTour *TourWidgetPrivate::findTour(GeoDataFeature *feature)
const
384 if (GeoDataTour *tour = (feature ? geodata_cast<GeoDataTour>(feature) :
nullptr)) {
388 auto container =
dynamic_cast<GeoDataContainer *
>(feature);
392 for (; iter !=
end; ++iter) {
393 GeoDataTour *tour = findTour(*iter);
402void TourWidgetPrivate::mapCenterOn(
const QModelIndex &index)
404 QVariant coordinatesVariant = m_widget->model()->treeModel()->
data(index, MarblePlacemarkModel::CoordinateRole);
405 if (!coordinatesVariant.
isNull()) {
406 auto const coordinates = coordinatesVariant.
value<GeoDataCoordinates>();
407 GeoDataLookAt lookat;
408 lookat.setCoordinates(coordinates);
409 lookat.setRange(coordinates.altitude());
410 m_widget->flyTo(lookat, Instant);
414void TourWidgetPrivate::addFlyTo()
416 auto flyTo =
new GeoDataFlyTo();
417 auto lookat =
new GeoDataLookAt(m_widget->lookAt());
418 lookat->setAltitude(lookat->range());
419 flyTo->setView(lookat);
420 bool isMainTrackEmpty = m_playback.mainTrackSize() == 0;
421 flyTo->setDuration(isMainTrackEmpty ? 0.0 : 1.0);
422 addTourPrimitive(flyTo);
425void TourWidgetPrivate::addWait()
427 auto wait =
new GeoDataWait();
428 wait->setDuration(1.0);
429 addTourPrimitive(wait);
432void TourWidgetPrivate::addSoundCue()
434 auto soundCue =
new GeoDataSoundCue();
435 addTourPrimitive(soundCue);
438void TourWidgetPrivate::addPlacemark()
442 qreal lat = m_widget->focusPoint().latitude();
443 qreal lon = m_widget->focusPoint().longitude();
444 GeoDataCoordinates::normalizeLonLat(lon, lat);
446 auto document =
new GeoDataDocument;
447 if (m_document->id().isEmpty()) {
448 if (m_document->name().isEmpty()) {
449 m_document->setId(QStringLiteral(
"untitled_tour"));
454 document->setTargetId(m_document->id());
456 auto placemark =
new GeoDataPlacemark;
457 placemark->setCoordinate(lon, lat);
458 placemark->setVisible(
true);
459 placemark->setBalloonVisible(
true);
460 auto newStyle =
new GeoDataStyle(*placemark->style());
461 newStyle->iconStyle().setIconPath(MarbleDirs::path(QStringLiteral(
"bitmaps/redflag_22.png")));
462 placemark->setStyle(GeoDataStyle::Ptr(newStyle));
464 document->append(placemark);
466 auto create =
new GeoDataCreate;
468 auto update =
new GeoDataUpdate;
469 update->setCreate(create);
470 auto animatedUpdate =
new GeoDataAnimatedUpdate;
471 animatedUpdate->setUpdate(update);
473 if (m_delegate->editAnimatedUpdate(animatedUpdate)) {
474 addTourPrimitive(animatedUpdate);
475 m_delegate->setDefaultFeatureId(placemark->id());
477 delete animatedUpdate;
481void TourWidgetPrivate::addRemovePlacemark()
483 auto deleteItem =
new GeoDataDelete;
484 auto placemark =
new GeoDataPlacemark;
485 placemark->setTargetId(m_delegate->defaultFeatureId());
486 deleteItem->append(placemark);
487 auto update =
new GeoDataUpdate;
488 update->setDelete(deleteItem);
489 auto animatedUpdate =
new GeoDataAnimatedUpdate;
490 animatedUpdate->setUpdate(update);
491 addTourPrimitive(animatedUpdate);
494void TourWidgetPrivate::addChangePlacemark()
496 auto change =
new GeoDataChange;
497 GeoDataPlacemark *placemark =
nullptr;
498 GeoDataFeature *lastFeature = m_delegate->findFeature(m_delegate->defaultFeatureId());
499 if (GeoDataPlacemark *target = (lastFeature !=
nullptr ? geodata_cast<GeoDataPlacemark>(lastFeature) :
nullptr)) {
500 placemark =
new GeoDataPlacemark(*target);
501 placemark->setTargetId(m_delegate->defaultFeatureId());
504 placemark =
new GeoDataPlacemark;
506 change->append(placemark);
507 auto update =
new GeoDataUpdate;
508 update->setChange(change);
509 auto animatedUpdate =
new GeoDataAnimatedUpdate;
510 animatedUpdate->setUpdate(update);
511 addTourPrimitive(animatedUpdate);
514void TourWidgetPrivate::addTourPrimitive(GeoDataTourPrimitive *primitive)
516 GeoDataObject *rootObject = rootIndexObject();
517 if (
auto playlist = geodata_cast<GeoDataPlaylist>(rootObject)) {
518 QModelIndex currentIndex = m_tourUi.m_listView->currentIndex();
520 int row = currentIndex.
isValid() ? currentIndex.
row() + 1 : playlist->size();
521 m_widget->model()->treeModel()->addTourPrimitive(playlistIndex, primitive, row);
523 m_tourUi.m_actionSaveTour->setEnabled(
true);
527 m_tourUi.m_listView->scrollTo(currentIndex);
529 m_tourUi.m_listView->scrollToBottom();
534void TourWidgetPrivate::deleteSelected()
541 GeoDataObject *rootObject = rootIndexObject();
542 if (GeoDataPlaylist *playlist = (rootObject ? geodata_cast<GeoDataPlaylist>(rootObject) :
nullptr)) {
544 QModelIndexList selected = m_tourUi.m_listView->selectionModel()->selectedIndexes();
548 QModelIndexList::iterator
end = selected.end();
549 QModelIndexList::iterator iter = selected.begin();
550 for (; iter !=
end; ++iter) {
551 m_widget->model()->treeModel()->removeTourPrimitive(playlistIndex, iter->row());
554 m_tourUi.m_actionSaveTour->setEnabled(
true);
560void TourWidgetPrivate::updateButtonsStates()
562 QModelIndexList selectedIndexes = m_tourUi.m_listView->selectionModel()->selectedIndexes();
563 if (selectedIndexes.isEmpty()) {
564 m_tourUi.m_actionDelete->setEnabled(
false);
565 m_tourUi.m_actionMoveDown->setEnabled(
false);
566 m_tourUi.m_actionMoveUp->setEnabled(
false);
568 m_tourUi.m_actionDelete->setEnabled(
true);
569 std::sort(selectedIndexes.begin(), selectedIndexes.end(), std::less<QModelIndex>());
570 QModelIndexList::iterator
end = selectedIndexes.end() - 1;
571 QModelIndexList::iterator
start = selectedIndexes.begin();
572 m_tourUi.m_actionMoveUp->setEnabled((
start->row() != 0));
573 GeoDataObject *rootObject = rootIndexObject();
574 if (GeoDataPlaylist *playlist = (rootObject ? geodata_cast<GeoDataPlaylist>(rootObject) :
nullptr)) {
575 m_tourUi.m_actionMoveDown->setEnabled((
end->row() != playlist->size() - 1));
580void TourWidgetPrivate::moveUp()
582 GeoDataObject *rootObject = rootIndexObject();
583 if (GeoDataPlaylist *playlist = (rootObject ? geodata_cast<GeoDataPlaylist>(rootObject) :
nullptr)) {
585 QModelIndexList selected = m_tourUi.m_listView->selectionModel()->selectedIndexes();
586 std::sort(selected.begin(), selected.end(), std::less<QModelIndex>());
587 QModelIndexList::iterator
end = selected.end();
588 QModelIndexList::iterator iter = selected.begin();
589 for (; iter !=
end; ++iter) {
590 int const index = iter->
row();
592 m_widget->model()->treeModel()->swapTourPrimitives(playlistIndex, index - 1, index);
595 m_tourUi.m_actionSaveTour->setEnabled(
true);
596 updateButtonsStates();
600void TourWidgetPrivate::moveDown()
602 GeoDataObject *rootObject = rootIndexObject();
603 if (GeoDataPlaylist *playlist = (rootObject ? geodata_cast<GeoDataPlaylist>(rootObject) :
nullptr)) {
605 QModelIndexList selected = m_tourUi.m_listView->selectionModel()->selectedIndexes();
609 QModelIndexList::iterator
end = selected.end();
610 QModelIndexList::iterator iter = selected.begin();
611 for (; iter !=
end; ++iter) {
612 int const index = iter->row();
613 Q_ASSERT(index < playlist->size() - 1);
614 m_widget->model()->treeModel()->swapTourPrimitives(playlistIndex, index, index + 1);
617 m_tourUi.m_actionSaveTour->setEnabled(
true);
618 updateButtonsStates();
622GeoDataFeature *TourWidgetPrivate::getPlaylistFeature()
const
624 GeoDataObject *rootObject = rootIndexObject();
625 if (GeoDataPlaylist *playlist = (rootObject ? geodata_cast<GeoDataPlaylist>(rootObject) :
nullptr)) {
626 GeoDataObject *
object = playlist->parent();
627 if (GeoDataTour *tour = (
object ? geodata_cast<GeoDataTour>(
object) :
nullptr)) {
634void TourWidgetPrivate::updateRootIndex()
636 GeoDataTour *tour = findTour(m_document);
638 GeoDataPlaylist *playlist = tour->playlist();
640 m_tourUi.m_listView->setModel(m_widget->model()->treeModel());
641 m_tourUi.m_listView->setRootIndex(m_widget->model()->treeModel()->index(playlist));
644 m_playback.setMarbleWidget(m_widget);
645 m_playback.setTour(tour);
646 m_tourUi.m_slider->setMaximum(m_playback.duration() * 100);
647 QTime nullTime(0, 0, 0);
650 QObject::connect(&m_playback, SIGNAL(progressChanged(
double)), q, SLOT(handlePlaybackProgress(
double)));
652 m_tourUi.m_toolBarPlayback->setEnabled(
true);
653 bool isPlaybackEmpty = m_playback.mainTrackSize() != 0;
654 m_tourUi.actionPlay->setEnabled(isPlaybackEmpty);
655 m_tourUi.m_slider->setEnabled(isPlaybackEmpty);
656 m_tourUi.m_actionRecord->setEnabled(isPlaybackEmpty);
657 m_tourUi.actionStop->setEnabled(
false);
658 if (m_playback.mainTrackSize() > 0) {
659 if (
dynamic_cast<PlaybackFlyToItem *
>(m_playback.mainTrackItemAt(0))) {
661 for (
int i = 0; playlist && i < playlist->size(); ++i) {
662 if (geodata_cast<GeoDataFlyTo>(playlist->primitive(i))) {
663 m_delegate->setFirstFlyTo(m_widget->model()->treeModel()->index(i, 0, playlistIndex));
674void TourWidget::addFlyTo()
680void TourWidget::addWait()
686void TourWidget::addSoundCue()
692void TourWidget::addPlacemark()
698void TourWidget::addRemovePlacemark()
700 d->addRemovePlacemark();
704void TourWidget::addChangePlacemark()
706 d->addChangePlacemark();
710void TourWidget::deleteSelected()
713 GeoDataFeature *feature = d->getPlaylistFeature();
715 Q_EMIT featureUpdated(feature);
716 d->updateRootIndex();
720void TourWidget::updateDuration()
722 d->m_tourUi.m_slider->setMaximum(d->m_playback.duration() * 100);
723 QTime nullTime(0, 0, 0);
724 QTime totalTime = nullTime.
addSecs(d->m_playback.duration());
725 d->m_tourUi.m_totalTime->setText(
727 d->m_tourUi.m_slider->setValue(0);
728 d->m_tourUi.m_elapsedTime->setText(QStringLiteral(
"%L1:%L2").arg(0, 2, 10,
QLatin1Char(
'0')).arg(0, 2, 10,
QLatin1Char(
'0')));
731void TourWidget::finishAddingItem()
733 GeoDataFeature *feature = d->getPlaylistFeature();
735 Q_EMIT featureUpdated(feature);
736 d->updateRootIndex();
740void TourWidget::moveDown()
743 GeoDataFeature *feature = d->getPlaylistFeature();
745 Q_EMIT featureUpdated(feature);
746 d->updateRootIndex();
750void TourWidget::moveUp()
753 GeoDataFeature *feature = d->getPlaylistFeature();
755 Q_EMIT featureUpdated(feature);
756 d->updateRootIndex();
760GeoDataObject *TourWidgetPrivate::rootIndexObject()
const
762 QModelIndex const rootIndex = m_tourUi.m_listView->rootIndex();
766void TourWidgetPrivate::createTour()
768 if (overrideModifications()) {
769 auto document =
new GeoDataDocument();
770 document->setDocumentRole(UserDocument);
771 document->setName(QStringLiteral(
"New Tour"));
772 document->setId(QStringLiteral(
"new_tour"));
773 auto tour =
new GeoDataTour();
774 tour->setName(QStringLiteral(
"New Tour"));
775 auto playlist =
new GeoDataPlaylist;
776 tour->setPlaylist(playlist);
777 document->append(
static_cast<GeoDataFeature *
>(tour));
779 openDocument(document);
781 m_tourUi.m_actionSaveTour->setEnabled(
true);
782 m_tourUi.m_slider->setEnabled(
true);
786bool TourWidgetPrivate::openDocument(GeoDataDocument *document)
790 m_widget->model()->treeModel()->removeDocument(m_document);
793 m_document = document;
794 m_widget->model()->treeModel()->addDocument(m_document);
797 m_addPrimitiveButton->setEnabled(
true);
798 m_tourUi.m_actionSaveTourAs->setEnabled(
true);
799 m_tourUi.m_actionSaveTour->setEnabled(
false);
806void TourWidgetPrivate::saveTour()
809 if (!m_document->fileName().isEmpty()) {
810 saveTourAs(m_document->fileName());
817void TourWidgetPrivate::saveTourAs()
822 saveTourAs(filename);
827bool TourWidgetPrivate::saveTourAs(
const QString &filename)
830 if (GeoDataDocumentWriter::write(filename, *m_document)) {
831 m_tourUi.m_actionSaveTour->setEnabled(
false);
833 GeoDataDocument *document = m_document;
834 if (!document->fileName().isNull()) {
835 m_widget->model()->removeGeoData(document->fileName());
837 m_widget->model()->addGeoDataFile(filename);
838 m_document->setFileName(filename);
845void TourWidgetPrivate::captureTour()
847 auto widget =
new MarbleWidget;
848 widget->setMapThemeId(m_widget->mapThemeId());
849 widget->resize(1280, 720);
851 m_widget->model()->treeModel()->removeDocument(m_document);
852 widget->model()->treeModel()->addDocument(m_document);
854 GeoDataTour *tour = findTour(m_document);
855 auto playback =
new TourPlayback;
856 playback->setMarbleWidget(widget);
857 playback->setTour(tour);
859 m_tourUi.m_listView->setModel(widget->model()->treeModel());
861 m_tourUi.m_listView->setRootIndex(widget->model()->treeModel()->index(tour->playlist()));
862 m_tourUi.m_listView->repaint();
865 tourCaptureDialog->setDefaultFilename(tour->name());
866 tourCaptureDialog->setTourPlayback(playback);
867 tourCaptureDialog->exec();
871 widget->model()->treeModel()->removeDocument(m_document);
872 m_widget->model()->treeModel()->addDocument(m_document);
877bool TourWidgetPrivate::overrideModifications()
879 if (m_document && m_isChanged) {
881 QString text =
QObject::tr(
"Are you sure want to discard all unsaved changes and close current document?");
893bool TourWidget::openTour(
const QString &filename)
895 return d->openFile(filename);
898void TourWidgetPrivate::handlePlaybackProgress(
const double position)
900 if (!m_tourUi.m_slider->isSliderDown()) {
901 m_tourUi.m_slider->setValue(position * 100);
902 QTime nullTime(0, 0, 0);
908void TourWidget::setHighlightedItemIndex(
int index)
910 GeoDataObject *rootObject = d->rootIndexObject();
911 auto playlist =
static_cast<GeoDataPlaylist *
>(rootObject);
915 int searchedIndex = 0;
916 for (
int i = 0; i < playlist->size(); i++) {
918 auto object = qvariant_cast<GeoDataObject *>(currentIndex.
data(MarblePlacemarkModel::ObjectPointerRole));
920 if (geodata_cast<GeoDataFlyTo>(
object) || geodata_cast<GeoDataWait>(
object))
923 if (index == searchedIndex) {
925 d->m_tourUi.m_listView->scrollTo(currentIndex);
929 d->m_tourUi.m_listView->viewport()->update();
932void TourWidget::removeHighlight()
938 if (d->m_tourUi.m_listView->selectionModel()->hasSelection()) {
939 index = d->m_tourUi.m_listView->selectionModel()->selectedIndexes().last();
945 d->m_tourUi.m_listView->viewport()->update();
948bool TourWidget::isPlaying()
const
950 return d->m_playState;
955#include "moc_TourWidget.cpp"
This file contains the headers for MarbleModel.
Q_SCRIPTABLE Q_NOREPLY void start()
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void update(Part *part, const QByteArray &data, qint64 dataSize)
QAction * create(StandardAction id, const Receiver *recvr, Func slot, QObject *parent, std::optional< Qt::ConnectionType > connectionType=std::nullopt)
const QList< QKeySequence > & end()
Binds a QML item to a specific geodetic location in screen coordinates.
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
void setIcon(const QIcon &icon)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, Options options)
StandardButton question(QWidget *parent, const QString &title, const QString &text, StandardButtons buttons, StandardButton defaultButton)
QVariant data(int role) const const
void * internalPointer() const const
bool isValid() const const
const QAbstractItemModel * model() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QTime addSecs(int s) const const
QUrl fromLocalFile(const QString &localFile)
bool isNull() const const
void setContentsMargins(const QMargins &margins)