8#include "TourItemDelegate.h"
10#include <QAbstractTextDocumentLayout>
11#include <QStyleOptionButton>
13#include <QApplication>
17#include "MarblePlacemarkModel.h"
18#include "geodata/data/GeoDataContainer.h"
19#include "geodata/data/GeoDataFlyTo.h"
20#include "geodata/data/GeoDataObject.h"
21#include "geodata/data/GeoDataTourControl.h"
22#include "geodata/data/GeoDataWait.h"
23#include "geodata/data/GeoDataCoordinates.h"
24#include "geodata/data/GeoDataSoundCue.h"
25#include "geodata/data/GeoDataAnimatedUpdate.h"
26#include "FlyToEditWidget.h"
27#include "TourControlEditWidget.h"
28#include "SoundCueEditWidget.h"
29#include "WaitEditWidget.h"
30#include "RemoveItemEditWidget.h"
31#include "GeoDataPlacemark.h"
32#include "GeoDataCreate.h"
33#include "GeoDataUpdate.h"
34#include "GeoDataDelete.h"
35#include "GeoDataChange.h"
36#include "EditPlacemarkDialog.h"
38#include "GeoDataPlaylist.h"
39#include "TourWidget.h"
44TourItemDelegate::TourItemDelegate(
QListView* view, MarbleWidget* widget, TourWidget* tour ):
45 m_listView( view ), m_widget( widget ), m_editable( true ), m_tourWidget( tour )
63 if ( m_listView->currentIndex() == index && m_tourWidget->isPlaying() ) {
69 QRect const labelRect = position(Label, option);
71 label.setDefaultFont( option.font );
74 button.state = option.state;
75 button.palette = option.palette;
77 button.iconSize =
QSize( 16, 16 );
78 button.state &=
~QStyle::State_HasFocus;
80 button.state &=
~QStyle::State_Enabled;
83 QRect const iconRect = position( GeoDataElementIcon, option );
85 const GeoDataObject *
object = qvariant_cast<GeoDataObject*>(index.
data(MarblePlacemarkModel::ObjectPointerRole));
86 if (!m_editingIndices.contains(index)) {
87 if (
const GeoDataTourControl *tourControl = geodata_cast<GeoDataTourControl>(
object)) {
88 GeoDataTourControl::PlayMode
const playMode = tourControl->playMode();
90 if ( playMode == GeoDataTourControl::Play ) {
91 label.setHtml( tr(
"Play the tour") );
92 }
else if ( playMode == GeoDataTourControl::Pause ) {
93 label.setHtml( tr(
"Pause the tour") );
98 label.documentLayout()->draw( painter, paintContext );
100 button.icon =
QIcon(QStringLiteral(
":/marble/document-edit.png"));
102 QRect const buttonRect = position( EditButton, option );
103 button.rect = buttonRect;
105 QIcon const icon =
QIcon(QStringLiteral(
":/marble/media-playback-pause.png"));
108 }
else if (geodata_cast<GeoDataFlyTo>(
object)) {
109 GeoDataCoordinates
const flyToCoords = index.
data( MarblePlacemarkModel::CoordinateRole ).
value<GeoDataCoordinates>();
110 label.setHtml( flyToCoords.toString() );
111 button.icon =
QIcon(QStringLiteral(
":/marble/document-edit.png"));
116 label.documentLayout()->draw( painter, paintContext );
119 QRect const buttonRect = position( EditButton, option );
120 button.rect = buttonRect;
122 QIcon const icon =
QIcon(QStringLiteral(
":/marble/flag.png"));
124 }
else if (
const GeoDataWait *wait = geodata_cast<GeoDataWait>(
object)) {
130 label.documentLayout()->draw( painter, paintContext );
133 button.icon =
QIcon(QStringLiteral(
":/marble/document-edit.png"));
135 QRect const buttonRect = position( EditButton, option );
136 button.rect = buttonRect;
138 QIcon const icon =
QIcon(QStringLiteral(
":/marble/player-time.png"));
140 }
else if (
const GeoDataSoundCue *soundCue = geodata_cast<GeoDataSoundCue>(
object)) {
146 label.documentLayout()->draw( painter, paintContext );
151 button.icon =
QIcon(QStringLiteral(
":/marble/document-edit.png"));
152 QRect const buttonRect = position( EditButton, option );
153 button.rect = buttonRect;
155 playButton.icon =
QIcon(QStringLiteral(
":/marble/playback-play.png"));
156 QRect const playButtonRect = position( ActionButton, option );
157 playButton.rect = playButtonRect;
160 QIcon const icon =
QIcon(QStringLiteral(
":/marble/audio-x-generic.png"));
162 }
else if (
const GeoDataAnimatedUpdate *animUpdate = geodata_cast<GeoDataAnimatedUpdate>(
object)) {
163 const GeoDataUpdate *
update = animUpdate->update();
166 if( update &&
update->create() &&
update->create()->size() != 0
167 && (
dynamic_cast<const GeoDataContainer *
>(&
update->create()->first()))) {
168 const GeoDataContainer *container =
static_cast<const GeoDataContainer*
>(
update->create()->child(0));
169 if( container->size() > 0 ) {
170 label.setHtml( tr(
"Create item %1" ).arg( container->first().id() ) );
172 iconString = QStringLiteral(
":/icons/add-placemark.png");
174 }
else if( update &&
update->getDelete() &&
update->getDelete()->size() != 0 ){
175 label.setHtml( tr(
"Remove item %1" ).arg(
update->getDelete()->first().targetId() ) );
177 iconString = QStringLiteral(
":/icons/remove.png");
178 }
else if( update &&
update->change() &&
update->change()->size() != 0 ){
179 label.setHtml( tr(
"Change item %1" ).arg(
update->change()->first().targetId() ) );
181 iconString = QStringLiteral(
":/marble/document-edit.png");
183 if( update && !ok ) {
184 label.setHtml( tr(
"Update items" ) );
191 label.documentLayout()->draw( painter, paintContext );
194 button.icon =
QIcon(QStringLiteral(
":/marble/document-edit.png"));
195 QRect const buttonRect = position( EditButton, option );
196 button.rect = buttonRect;
208 QPoint const topCol1 = option.rect.topLeft() +
QPoint(10, 10);
217 case GeoDataElementIcon:
218 return QRect( topCol1, iconsSize );
220 return QRect( topCol2, labelSize );
222 return QRect( topCol3, iconsSize );
224 return QRect( topCol4, iconsSize );
229QStringList TourItemDelegate::findIds(
const GeoDataPlaylist &playlist,
bool onlyFeatures)
232 for (
int i = 0; i < playlist.size(); ++i) {
233 const GeoDataTourPrimitive *primitive = playlist.primitive(i);
234 if( !primitive->id().isEmpty() && !onlyFeatures ) {
235 result << primitive->id();
237 if (
const GeoDataAnimatedUpdate *animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(primitive)) {
238 if( animatedUpdate->update() !=
nullptr ) {
239 const GeoDataUpdate *
update = animatedUpdate->update();
240 if( !
update->id().isEmpty() && !onlyFeatures ) {
243 if(
update->create() !=
nullptr ) {
244 if( !
update->create()->id().isEmpty() && !onlyFeatures ) {
245 result <<
update->create()->id();
247 for(
int j = 0; j <
update->create()->size(); ++j ) {
248 if( !
update->create()->at( j ).id().isEmpty() ) {
249 result <<
update->create()->at( j ).id();
253 if(
update->change() !=
nullptr ) {
254 if( !
update->change()->id().isEmpty() && !onlyFeatures ) {
255 result <<
update->change()->id();
257 for(
int j = 0; j <
update->change()->size(); ++j ) {
258 if( !
update->change()->at( j ).id().isEmpty() ) {
259 result <<
update->change()->at( j ).id();
263 if(
update->getDelete() !=
nullptr ) {
264 if( !
update->getDelete()->id().isEmpty() && !onlyFeatures ) {
265 result <<
update->getDelete()->id();
267 for(
int j = 0; j <
update->getDelete()->size(); ++j ) {
268 if( !
update->getDelete()->at( j ).id().isEmpty() ) {
269 result <<
update->getDelete()->at( j ).id();
279GeoDataPlaylist *TourItemDelegate::playlist()
const
281 QModelIndex const rootIndex = m_listView->rootIndex();
283 GeoDataObject *rootObject =
static_cast<GeoDataObject*
>( rootIndex.
internalPointer() );
284 if (GeoDataPlaylist *playlist = geodata_cast<GeoDataPlaylist>(rootObject)) {
296 return QSize(290,50);
302 GeoDataObject *
object = qvariant_cast<GeoDataObject*>(index.
data( MarblePlacemarkModel::ObjectPointerRole ) );
303 if (geodata_cast<GeoDataFlyTo>(
object)) {
304 FlyToEditWidget* widget =
new FlyToEditWidget(index, m_widget, parent);
305 widget->setFirstFlyTo( m_firstFlyTo );
307 connect(
this, SIGNAL(editableChanged(
bool)), widget, SLOT(setEditable(
bool)) );
311 }
else if (geodata_cast<GeoDataTourControl>(
object)) {
312 TourControlEditWidget* widget =
new TourControlEditWidget(index, parent);
314 connect(
this, SIGNAL(editableChanged(
bool)), widget, SLOT(setEditable(
bool)) );
317 }
else if (geodata_cast<GeoDataWait>(
object)) {
318 WaitEditWidget* widget =
new WaitEditWidget(index, parent);
320 connect(
this, SIGNAL(editableChanged(
bool)), widget, SLOT(setEditable(
bool)) );
323 }
else if (geodata_cast<GeoDataSoundCue>(
object)) {
324 SoundCueEditWidget* widget =
new SoundCueEditWidget(index, parent);
326 connect(
this, SIGNAL(editableChanged(
bool)), widget, SLOT(setEditable(
bool)) );
329 }
else if (geodata_cast<GeoDataAnimatedUpdate>(
object)) {
330 RemoveItemEditWidget* widget =
new RemoveItemEditWidget(index, parent);
331 GeoDataPlaylist *playlistObject = playlist();
332 if( playlistObject !=
nullptr ) {
333 widget->setFeatureIds(findIds(*playlistObject));
335 widget->setDefaultFeatureId( m_defaultFeatureId );
337 connect(
this, SIGNAL(editableChanged(
bool)), widget, SLOT(setEditable(
bool)) );
339 connect(
this, SIGNAL(defaultFeatureIdChanged(
QString)), widget, SLOT(setDefaultFeatureId(
QString)) );
346bool TourItemDelegate::editable()
const
351void TourItemDelegate::setEditable(
bool editable )
353 if( m_editable != editable ) {
354 m_editable = editable;
355 emit editableChanged( m_editable );
364bool TourItemDelegate::editAnimatedUpdate(GeoDataAnimatedUpdate *animatedUpdate,
bool create)
366 if( animatedUpdate->update() ==
nullptr ) {
369 GeoDataFeature *feature =
nullptr;
370 if( create && !( animatedUpdate->update()->create() ==
nullptr || animatedUpdate->update()->create()->size() == 0 ) ) {
371 GeoDataContainer *container =
dynamic_cast<GeoDataContainer*
>( animatedUpdate->update()->create()->child( 0 ) );
372 if( container !=
nullptr && container->size() ) {
373 feature = container->child( 0 );
375 }
else if ( !create && !( animatedUpdate->update()->change() ==
nullptr || animatedUpdate->update()->change()->size() == 0 ) ) {
376 GeoDataContainer *container =
dynamic_cast<GeoDataContainer*
>( animatedUpdate->update()->change()->child( 0 ) );
377 if( container !=
nullptr && container->size() ) {
378 feature = container->child( 0 );
381 if( feature ==
nullptr ) {
387 GeoDataPlacemark *placemark =
static_cast<GeoDataPlacemark*
>( feature );
390 if( placemark->targetId().isEmpty() && !defaultFeatureId().isEmpty() ) {
391 GeoDataFeature *feature = findFeature( defaultFeatureId() );
392 if (GeoDataPlacemark *targetPlacemark = (feature !=
nullptr ? geodata_cast<GeoDataPlacemark>(feature) : nullptr)) {
393 animatedUpdate->update()->change()->placemarkList().remove( 0 );
395 placemark =
new GeoDataPlacemark( *targetPlacemark );
396 animatedUpdate->update()->change()->placemarkList().insert( 0, placemark );
397 placemark->setTargetId( defaultFeatureId() );
405 dialog->setWindowTitle(
QObject::tr(
"Add Placemark to Tour" ) );
407 dialog->setWindowTitle(
QObject::tr(
"Change Placemark in Tour" ) );
408 dialog->setTargetIdFieldVisible(
true );
409 dialog->setIdFieldVisible(
false );
411 GeoDataPlaylist* playlistObject = playlist();
412 if( playlistObject !=
nullptr ) {
413 ids.
append(findIds(*playlistObject,
true));
417 dialog->setIdFilter( ids );
419 dialog->setTargetIds( ids );
421 bool status = dialog->exec();
428QString TourItemDelegate::defaultFeatureId()
const
430 return m_defaultFeatureId;
435GeoDataFeature *TourItemDelegate::findFeature(
const QString &
id)
const
437 GeoDataPlaylist *playlistObject = playlist();
438 if( playlistObject ==
nullptr ) {
441 GeoDataFeature *result =
nullptr;
442 for(
int i = 0; i < playlistObject->size(); ++i ) {
443 GeoDataTourPrimitive *primitive = playlistObject->primitive( i );
444 if (GeoDataAnimatedUpdate *animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(primitive)) {
445 if( animatedUpdate->update() !=
nullptr ) {
446 GeoDataUpdate *
update = animatedUpdate->update();
447 if(
update->create() !=
nullptr ) {
448 for(
int j = 0; j <
update->create()->featureList().size(); ++j ) {
449 if(
update->create()->at( j ).id() ==
id ) {
450 result =
update->create()->featureList().at( j );
454 if(
update->change() !=
nullptr ) {
455 for(
int j = 0; j <
update->change()->featureList().size(); ++j ) {
456 if(
update->change()->at( j ).id() ==
id ) {
457 result =
update->change()->featureList().at( j );
461 if(
update->getDelete() !=
nullptr ) {
462 for(
int j = 0; j <
update->getDelete()->featureList().size(); ++j ) {
463 if(
update->getDelete()->at( j ).id() ==
id ) {
464 result =
update->getDelete()->featureList().at( j );
476 m_firstFlyTo = index;
477 emit firstFlyToChanged( m_firstFlyTo );
480void TourItemDelegate::setDefaultFeatureId(
const QString &
id)
482 m_defaultFeatureId = id;
484 emit featureIdsChanged( ids );
485 emit defaultFeatureIdChanged(
id );
493 QRect editRect = position( EditButton, option );
495 if( m_editingIndices.contains( index ) ) {
496 m_editingIndices.removeOne( index );
497 emit editingChanged( index );
500 GeoDataObject *
object = qvariant_cast<GeoDataObject*>(index.
data( MarblePlacemarkModel::ObjectPointerRole ) );
501 if (GeoDataAnimatedUpdate *animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(
object)) {
502 if( animatedUpdate->update() && animatedUpdate->update()->create() ) {
503 if( editAnimatedUpdate( animatedUpdate ) ) {
504 setDefaultFeatureId( m_defaultFeatureId );
506 }
else if( animatedUpdate->update() && animatedUpdate->update()->change() ) {
507 editAnimatedUpdate( animatedUpdate,
false );
508 }
else if ( animatedUpdate->update() && animatedUpdate->update()->getDelete() ) {
509 m_editingIndices.append( index );
510 m_listView->openPersistentEditor( index );
513 m_editingIndices.append( index );
514 m_listView->openPersistentEditor( index );
517 emit editingChanged( index );
524void TourItemDelegate::closeEditor(
const QModelIndex &index )
526 emit edited( index );
527 m_listView->closePersistentEditor( index );
528 m_editingIndices.removeOne( index );
533#include "moc_TourItemDelegate.cpp"
Q_SCRIPTABLE CaptureState status()
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
void update(Part *part, const QByteArray &data, qint64 dataSize)
QString label(StandardShortcut id)
Binds a QML item to a specific geodetic location in screen coordinates.
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
void append(QList< T > &&value)
bool removeOne(const AT &t)
QVariant data(int role) const const
void * internalPointer() const const
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString tr(const char *sourceText, const char *disambiguation, int n)
void drawPixmap(const QPoint &point, const QPixmap &pixmap)
void fillRect(const QRect &rectangle, QGradient::Preset preset)
void setClipRect(const QRect &rectangle, Qt::ClipOperation operation)
void translate(const QPoint &offset)
bool contains(const QPoint &point, bool proper) const const
QPoint topLeft() const const
QString number(double n, char format, int precision)
virtual void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const const override
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)