File indexing completed on 2024-03-24 03:52:48
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2013 Mihail Ivchenko <ematirov@gmail.com> 0004 // SPDX-FileCopyrightText: 2014 Sanjiban Bairagya <sanjiban22393@gmail.com> 0005 // SPDX-FileCopyrightText: 2014 Illya Kovalevskyy <illya.kovalevskyy@gmail.com> 0006 // 0007 0008 #include "TourItemDelegate.h" 0009 0010 #include <QAbstractTextDocumentLayout> 0011 #include <QStyleOptionButton> 0012 #include <QPainter> 0013 #include <QApplication> 0014 #include <QListView> 0015 #include <QPointer> 0016 0017 #include "MarblePlacemarkModel.h" 0018 #include "geodata/data/GeoDataContainer.h" 0019 #include "geodata/data/GeoDataFlyTo.h" 0020 #include "geodata/data/GeoDataObject.h" 0021 #include "geodata/data/GeoDataTourControl.h" 0022 #include "geodata/data/GeoDataWait.h" 0023 #include "geodata/data/GeoDataCoordinates.h" 0024 #include "geodata/data/GeoDataSoundCue.h" 0025 #include "geodata/data/GeoDataAnimatedUpdate.h" 0026 #include "FlyToEditWidget.h" 0027 #include "TourControlEditWidget.h" 0028 #include "SoundCueEditWidget.h" 0029 #include "WaitEditWidget.h" 0030 #include "RemoveItemEditWidget.h" 0031 #include "GeoDataPlacemark.h" 0032 #include "GeoDataCreate.h" 0033 #include "GeoDataUpdate.h" 0034 #include "GeoDataDelete.h" 0035 #include "GeoDataChange.h" 0036 #include "EditPlacemarkDialog.h" 0037 #include "MarbleWidget.h" 0038 #include "GeoDataPlaylist.h" 0039 #include "TourWidget.h" 0040 0041 namespace Marble 0042 { 0043 0044 TourItemDelegate::TourItemDelegate( QListView* view, MarbleWidget* widget, TourWidget* tour ): 0045 m_listView( view ), m_widget( widget ), m_editable( true ), m_tourWidget( tour ) 0046 { 0047 QObject::connect( this, SIGNAL(editingChanged(QModelIndex)), m_listView, SLOT(update(QModelIndex)) ); 0048 m_listView->setEditTriggers( QAbstractItemView::NoEditTriggers ); 0049 } 0050 0051 void TourItemDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const 0052 { 0053 QStyleOptionViewItem styleOption = option; 0054 styleOption.text = QString(); 0055 QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &styleOption, painter); 0056 0057 QAbstractTextDocumentLayout::PaintContext paintContext; 0058 if (styleOption.state & QStyle::State_Selected) { 0059 paintContext.palette.setColor(QPalette::Text, 0060 styleOption.palette.color(QPalette::Active, QPalette::HighlightedText)); 0061 } 0062 0063 if ( m_listView->currentIndex() == index && m_tourWidget->isPlaying() ) { 0064 painter->fillRect( option.rect, paintContext.palette.color( QPalette::Midlight ) ); 0065 QStyledItemDelegate::paint( painter, option, index ); 0066 } 0067 0068 QTextDocument label; 0069 QRect const labelRect = position(Label, option); 0070 label.setTextWidth( labelRect.width() ); 0071 label.setDefaultFont( option.font ); 0072 0073 QStyleOptionButton button; 0074 button.state = option.state; 0075 button.palette = option.palette; 0076 button.features = QStyleOptionButton::None; 0077 button.iconSize = QSize( 16, 16 ); 0078 button.state &= ~QStyle::State_HasFocus; 0079 if( !editable() ) { 0080 button.state &= ~QStyle::State_Enabled; 0081 } 0082 0083 QRect const iconRect = position( GeoDataElementIcon, option ); 0084 0085 const GeoDataObject *object = qvariant_cast<GeoDataObject*>(index.data(MarblePlacemarkModel::ObjectPointerRole)); 0086 if (!m_editingIndices.contains(index)) { 0087 if (const GeoDataTourControl *tourControl = geodata_cast<GeoDataTourControl>(object)) { 0088 GeoDataTourControl::PlayMode const playMode = tourControl->playMode(); 0089 0090 if ( playMode == GeoDataTourControl::Play ) { 0091 label.setHtml( tr("Play the tour") ); 0092 } else if ( playMode == GeoDataTourControl::Pause ) { 0093 label.setHtml( tr("Pause the tour") ); 0094 } 0095 painter->save(); 0096 painter->translate( labelRect.topLeft() ); 0097 painter->setClipRect( 0, 0, labelRect.width(), labelRect.height() ); 0098 label.documentLayout()->draw( painter, paintContext ); 0099 painter->restore(); 0100 button.icon = QIcon(QStringLiteral(":/marble/document-edit.png")); 0101 0102 QRect const buttonRect = position( EditButton, option ); 0103 button.rect = buttonRect; 0104 0105 QIcon const icon = QIcon(QStringLiteral(":/marble/media-playback-pause.png")); 0106 painter->drawPixmap( iconRect, icon.pixmap( iconRect.size() ) ); 0107 0108 } else if (geodata_cast<GeoDataFlyTo>(object)) { 0109 GeoDataCoordinates const flyToCoords = index.data( MarblePlacemarkModel::CoordinateRole ).value<GeoDataCoordinates>(); 0110 label.setHtml( flyToCoords.toString() ); 0111 button.icon = QIcon(QStringLiteral(":/marble/document-edit.png")); 0112 0113 painter->save(); 0114 painter->translate( labelRect.topLeft() ); 0115 painter->setClipRect( 0, 0, labelRect.width(), labelRect.height() ); 0116 label.documentLayout()->draw( painter, paintContext ); 0117 painter->restore(); 0118 0119 QRect const buttonRect = position( EditButton, option ); 0120 button.rect = buttonRect; 0121 0122 QIcon const icon = QIcon(QStringLiteral(":/marble/flag.png")); 0123 painter->drawPixmap( iconRect, icon.pixmap( iconRect.size() ) ); 0124 } else if (const GeoDataWait *wait = geodata_cast<GeoDataWait>(object)) { 0125 label.setHtml( tr("Wait for %1 seconds").arg( QString::number( wait->duration() ) ) ); 0126 0127 painter->save(); 0128 painter->translate( labelRect.topLeft() ); 0129 painter->setClipRect( 0, 0, labelRect.width(), labelRect.height() ); 0130 label.documentLayout()->draw( painter, paintContext ); 0131 painter->restore(); 0132 0133 button.icon = QIcon(QStringLiteral(":/marble/document-edit.png")); 0134 0135 QRect const buttonRect = position( EditButton, option ); 0136 button.rect = buttonRect; 0137 0138 QIcon const icon = QIcon(QStringLiteral(":/marble/player-time.png")); 0139 painter->drawPixmap( iconRect, icon.pixmap( iconRect.size() ) ); 0140 } else if (const GeoDataSoundCue *soundCue = geodata_cast<GeoDataSoundCue>(object)) { 0141 label.setHtml(soundCue->href().section(QLatin1Char('/'), -1)); 0142 0143 painter->save(); 0144 painter->translate( labelRect.topLeft() ); 0145 painter->setClipRect( 0, 0, labelRect.width(), labelRect.height() ); 0146 label.documentLayout()->draw( painter, paintContext ); 0147 painter->restore(); 0148 0149 QStyleOptionButton playButton = button; 0150 0151 button.icon = QIcon(QStringLiteral(":/marble/document-edit.png")); 0152 QRect const buttonRect = position( EditButton, option ); 0153 button.rect = buttonRect; 0154 0155 playButton.icon = QIcon(QStringLiteral(":/marble/playback-play.png")); 0156 QRect const playButtonRect = position( ActionButton, option ); 0157 playButton.rect = playButtonRect; 0158 QApplication::style()->drawControl( QStyle::CE_PushButton, &playButton, painter ); 0159 0160 QIcon const icon = QIcon(QStringLiteral(":/marble/audio-x-generic.png")); 0161 painter->drawPixmap( iconRect, icon.pixmap( iconRect.size() ) ); 0162 } else if (const GeoDataAnimatedUpdate *animUpdate = geodata_cast<GeoDataAnimatedUpdate>(object)) { 0163 const GeoDataUpdate *update = animUpdate->update(); 0164 bool ok = false; 0165 QString iconString; 0166 if( update && update->create() && update->create()->size() != 0 0167 && (dynamic_cast<const GeoDataContainer *>(&update->create()->first()))) { 0168 const GeoDataContainer *container = static_cast<const GeoDataContainer*>(update->create()->child(0)); 0169 if( container->size() > 0 ) { 0170 label.setHtml( tr( "Create item %1" ).arg( container->first().id() ) ); 0171 ok = true; 0172 iconString = QStringLiteral(":/icons/add-placemark.png"); 0173 } 0174 } else if( update && update->getDelete() && update->getDelete()->size() != 0 ){ 0175 label.setHtml( tr( "Remove item %1" ).arg( update->getDelete()->first().targetId() ) ); 0176 ok = true; 0177 iconString = QStringLiteral(":/icons/remove.png"); 0178 } else if( update && update->change() && update->change()->size() != 0 ){ 0179 label.setHtml( tr( "Change item %1" ).arg( update->change()->first().targetId() ) ); 0180 ok = true; 0181 iconString = QStringLiteral(":/marble/document-edit.png"); 0182 } 0183 if( update && !ok ) { 0184 label.setHtml( tr( "Update items" ) ); 0185 button.state &= ~QStyle::State_Enabled & ~QStyle::State_Sunken; 0186 } 0187 0188 painter->save(); 0189 painter->translate( labelRect.topLeft() ); 0190 painter->setClipRect( 0, 0, labelRect.width(), labelRect.height() ); 0191 label.documentLayout()->draw( painter, paintContext ); 0192 painter->restore(); 0193 0194 button.icon = QIcon(QStringLiteral(":/marble/document-edit.png")); 0195 QRect const buttonRect = position( EditButton, option ); 0196 button.rect = buttonRect; 0197 0198 QIcon const icon = QIcon( iconString ); 0199 painter->drawPixmap( iconRect, icon.pixmap( iconRect.size() ) ); 0200 } 0201 } 0202 0203 QApplication::style()->drawControl( QStyle::CE_PushButton, &button, painter ); 0204 } 0205 0206 QRect TourItemDelegate::position( Element element, const QStyleOptionViewItem &option ) 0207 { 0208 QPoint const topCol1 = option.rect.topLeft() + QPoint(10, 10); 0209 QPoint const topCol2 = topCol1 + QPoint(30, 0); 0210 QPoint const topCol3 = topCol2 + QPoint(210, 0); 0211 QPoint const topCol4 = topCol3 + QPoint(30, 0); 0212 QSize const labelSize = QSize(220, 30); 0213 QSize const iconsSize = QSize(22, 22); 0214 0215 switch(element) 0216 { 0217 case GeoDataElementIcon: 0218 return QRect( topCol1, iconsSize ); 0219 case Label: 0220 return QRect( topCol2, labelSize ); 0221 case EditButton: 0222 return QRect( topCol3, iconsSize ); 0223 case ActionButton: 0224 return QRect( topCol4, iconsSize ); 0225 } 0226 return QRect(); 0227 } 0228 0229 QStringList TourItemDelegate::findIds(const GeoDataPlaylist &playlist, bool onlyFeatures) 0230 { 0231 QStringList result; 0232 for (int i = 0; i < playlist.size(); ++i) { 0233 const GeoDataTourPrimitive *primitive = playlist.primitive(i); 0234 if( !primitive->id().isEmpty() && !onlyFeatures ) { 0235 result << primitive->id(); 0236 } 0237 if (const GeoDataAnimatedUpdate *animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(primitive)) { 0238 if( animatedUpdate->update() != nullptr ) { 0239 const GeoDataUpdate *update = animatedUpdate->update(); 0240 if( !update->id().isEmpty() && !onlyFeatures ) { 0241 result << update->id(); 0242 } 0243 if( update->create() != nullptr ) { 0244 if( !update->create()->id().isEmpty() && !onlyFeatures ) { 0245 result << update->create()->id(); 0246 } 0247 for( int j = 0; j < update->create()->size(); ++j ) { 0248 if( !update->create()->at( j ).id().isEmpty() ) { 0249 result << update->create()->at( j ).id(); 0250 } 0251 } 0252 } 0253 if( update->change() != nullptr ) { 0254 if( !update->change()->id().isEmpty() && !onlyFeatures ) { 0255 result << update->change()->id(); 0256 } 0257 for( int j = 0; j < update->change()->size(); ++j ) { 0258 if( !update->change()->at( j ).id().isEmpty() ) { 0259 result << update->change()->at( j ).id(); 0260 } 0261 } 0262 } 0263 if( update->getDelete() != nullptr ) { 0264 if( !update->getDelete()->id().isEmpty() && !onlyFeatures ) { 0265 result << update->getDelete()->id(); 0266 } 0267 for( int j = 0; j < update->getDelete()->size(); ++j ) { 0268 if( !update->getDelete()->at( j ).id().isEmpty() ) { 0269 result << update->getDelete()->at( j ).id(); 0270 } 0271 } 0272 } 0273 } 0274 } 0275 } 0276 return result; 0277 } 0278 0279 GeoDataPlaylist *TourItemDelegate::playlist() const 0280 { 0281 QModelIndex const rootIndex = m_listView->rootIndex(); 0282 if( rootIndex.isValid() ) { 0283 GeoDataObject *rootObject = static_cast<GeoDataObject*>( rootIndex.internalPointer() ); 0284 if (GeoDataPlaylist *playlist = geodata_cast<GeoDataPlaylist>(rootObject)) { 0285 return playlist; 0286 } 0287 } 0288 return nullptr; 0289 } 0290 0291 0292 QSize TourItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const 0293 { 0294 Q_UNUSED( option ); 0295 Q_UNUSED( index ); 0296 return QSize(290,50); 0297 } 0298 0299 QWidget* TourItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const 0300 { 0301 Q_UNUSED( option ); 0302 GeoDataObject *object = qvariant_cast<GeoDataObject*>(index.data( MarblePlacemarkModel::ObjectPointerRole ) ); 0303 if (geodata_cast<GeoDataFlyTo>(object)) { 0304 FlyToEditWidget* widget = new FlyToEditWidget(index, m_widget, parent); 0305 widget->setFirstFlyTo( m_firstFlyTo ); 0306 connect(widget, SIGNAL(editingDone(QModelIndex)), this, SLOT(closeEditor(QModelIndex))); 0307 connect( this, SIGNAL(editableChanged(bool)), widget, SLOT(setEditable(bool)) ); 0308 connect( this, SIGNAL(firstFlyToChanged(QPersistentModelIndex)), widget, SLOT(setFirstFlyTo(QPersistentModelIndex)) ); 0309 return widget; 0310 0311 } else if (geodata_cast<GeoDataTourControl>(object)) { 0312 TourControlEditWidget* widget = new TourControlEditWidget(index, parent); 0313 connect(widget, SIGNAL(editingDone(QModelIndex)), this, SLOT(closeEditor(QModelIndex))); 0314 connect( this, SIGNAL(editableChanged(bool)), widget, SLOT(setEditable(bool)) ); 0315 return widget; 0316 0317 } else if (geodata_cast<GeoDataWait>(object)) { 0318 WaitEditWidget* widget = new WaitEditWidget(index, parent); 0319 connect(widget, SIGNAL(editingDone(QModelIndex)), this, SLOT(closeEditor(QModelIndex))); 0320 connect( this, SIGNAL(editableChanged(bool)), widget, SLOT(setEditable(bool)) ); 0321 return widget; 0322 0323 } else if (geodata_cast<GeoDataSoundCue>(object)) { 0324 SoundCueEditWidget* widget = new SoundCueEditWidget(index, parent); 0325 connect(widget, SIGNAL(editingDone(QModelIndex)), this, SLOT(closeEditor(QModelIndex))); 0326 connect( this, SIGNAL(editableChanged(bool)), widget, SLOT(setEditable(bool)) ); 0327 return widget; 0328 0329 } else if (geodata_cast<GeoDataAnimatedUpdate>(object)) { 0330 RemoveItemEditWidget* widget = new RemoveItemEditWidget(index, parent); 0331 GeoDataPlaylist *playlistObject = playlist(); 0332 if( playlistObject != nullptr ) { 0333 widget->setFeatureIds(findIds(*playlistObject)); 0334 } 0335 widget->setDefaultFeatureId( m_defaultFeatureId ); 0336 connect(widget, SIGNAL(editingDone(QModelIndex)), this, SLOT(closeEditor(QModelIndex))); 0337 connect( this, SIGNAL(editableChanged(bool)), widget, SLOT(setEditable(bool)) ); 0338 connect( this, SIGNAL(featureIdsChanged(QStringList)), widget, SLOT(setFeatureIds(QStringList)) ); 0339 connect( this, SIGNAL(defaultFeatureIdChanged(QString)), widget, SLOT(setDefaultFeatureId(QString)) ); 0340 return widget; 0341 0342 } 0343 return nullptr; 0344 } 0345 0346 bool TourItemDelegate::editable() const 0347 { 0348 return m_editable; 0349 } 0350 0351 void TourItemDelegate::setEditable( bool editable ) 0352 { 0353 if( m_editable != editable ) { 0354 m_editable = editable; 0355 emit editableChanged( m_editable ); 0356 } 0357 } 0358 0359 QModelIndex TourItemDelegate::firstFlyTo() const 0360 { 0361 return m_firstFlyTo; 0362 } 0363 0364 bool TourItemDelegate::editAnimatedUpdate(GeoDataAnimatedUpdate *animatedUpdate, bool create) 0365 { 0366 if( animatedUpdate->update() == nullptr ) { 0367 return false; 0368 } 0369 GeoDataFeature *feature = nullptr; 0370 if( create && !( animatedUpdate->update()->create() == nullptr || animatedUpdate->update()->create()->size() == 0 ) ) { 0371 GeoDataContainer *container = dynamic_cast<GeoDataContainer*>( animatedUpdate->update()->create()->child( 0 ) ); 0372 if( container != nullptr && container->size() ) { 0373 feature = container->child( 0 ); 0374 } 0375 } else if ( !create && !( animatedUpdate->update()->change() == nullptr || animatedUpdate->update()->change()->size() == 0 ) ) { 0376 GeoDataContainer *container = dynamic_cast<GeoDataContainer*>( animatedUpdate->update()->change()->child( 0 ) ); 0377 if( container != nullptr && container->size() ) { 0378 feature = container->child( 0 ); 0379 } 0380 } 0381 if( feature == nullptr ) { 0382 return false; 0383 } 0384 0385 QStringList ids; 0386 0387 GeoDataPlacemark *placemark = static_cast<GeoDataPlacemark*>( feature ); 0388 0389 if( !create ) { 0390 if( placemark->targetId().isEmpty() && !defaultFeatureId().isEmpty() ) { 0391 GeoDataFeature *feature = findFeature( defaultFeatureId() ); 0392 if (GeoDataPlacemark *targetPlacemark = (feature != nullptr ? geodata_cast<GeoDataPlacemark>(feature) : nullptr)) { 0393 animatedUpdate->update()->change()->placemarkList().remove( 0 ); 0394 delete placemark; 0395 placemark = new GeoDataPlacemark( *targetPlacemark ); 0396 animatedUpdate->update()->change()->placemarkList().insert( 0, placemark ); 0397 placemark->setTargetId( defaultFeatureId() ); 0398 placemark->setId(QString()); 0399 } 0400 } 0401 } 0402 0403 QPointer<EditPlacemarkDialog> dialog = new EditPlacemarkDialog( placemark, nullptr, m_widget ); 0404 if( create ) { 0405 dialog->setWindowTitle( QObject::tr( "Add Placemark to Tour" ) ); 0406 } else { 0407 dialog->setWindowTitle( QObject::tr( "Change Placemark in Tour" ) ); 0408 dialog->setTargetIdFieldVisible( true ); 0409 dialog->setIdFieldVisible( false ); 0410 } 0411 GeoDataPlaylist* playlistObject = playlist(); 0412 if( playlistObject != nullptr ) { 0413 ids.append(findIds(*playlistObject, true)); 0414 } 0415 ids.removeOne( placemark->id() ); 0416 if( create ) { 0417 dialog->setIdFilter( ids ); 0418 } else { 0419 dialog->setTargetIds( ids ); 0420 } 0421 bool status = dialog->exec(); 0422 if( !create ) { 0423 placemark->setId(QString()); 0424 } 0425 return status; 0426 } 0427 0428 QString TourItemDelegate::defaultFeatureId() const 0429 { 0430 return m_defaultFeatureId; 0431 } 0432 0433 0434 0435 GeoDataFeature *TourItemDelegate::findFeature(const QString &id) const 0436 { 0437 GeoDataPlaylist *playlistObject = playlist(); 0438 if( playlistObject == nullptr ) { 0439 return nullptr; 0440 } 0441 GeoDataFeature *result = nullptr; 0442 for( int i = 0; i < playlistObject->size(); ++i ) { 0443 GeoDataTourPrimitive *primitive = playlistObject->primitive( i ); 0444 if (GeoDataAnimatedUpdate *animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(primitive)) { 0445 if( animatedUpdate->update() != nullptr ) { 0446 GeoDataUpdate *update = animatedUpdate->update(); 0447 if( update->create() != nullptr ) { 0448 for( int j = 0; j < update->create()->featureList().size(); ++j ) { 0449 if( update->create()->at( j ).id() == id ) { 0450 result = update->create()->featureList().at( j ); 0451 } 0452 } 0453 } 0454 if( update->change() != nullptr ) { 0455 for( int j = 0; j < update->change()->featureList().size(); ++j ) { 0456 if( update->change()->at( j ).id() == id ) { 0457 result = update->change()->featureList().at( j ); 0458 } 0459 } 0460 } 0461 if( update->getDelete() != nullptr ) { 0462 for( int j = 0; j < update->getDelete()->featureList().size(); ++j ) { 0463 if( update->getDelete()->at( j ).id() == id ) { 0464 result = update->getDelete()->featureList().at( j ); 0465 } 0466 } 0467 } 0468 } 0469 } 0470 } 0471 return result; 0472 } 0473 0474 void TourItemDelegate::setFirstFlyTo(const QPersistentModelIndex &index ) 0475 { 0476 m_firstFlyTo = index; 0477 emit firstFlyToChanged( m_firstFlyTo ); 0478 } 0479 0480 void TourItemDelegate::setDefaultFeatureId(const QString &id) 0481 { 0482 m_defaultFeatureId = id; 0483 const QStringList ids = playlist() ? findIds(*playlist()) : QStringList(); 0484 emit featureIdsChanged( ids ); 0485 emit defaultFeatureIdChanged( id ); 0486 } 0487 0488 bool TourItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index ) 0489 { 0490 Q_UNUSED( model ); 0491 if ( ( event->type() == QEvent::MouseButtonRelease ) && editable() ) { 0492 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>( event ); 0493 QRect editRect = position( EditButton, option ); 0494 if ( editRect.contains( mouseEvent->pos() ) ) { 0495 if( m_editingIndices.contains( index ) ) { 0496 m_editingIndices.removeOne( index ); 0497 emit editingChanged( index ); 0498 return true; 0499 }else{ 0500 GeoDataObject *object = qvariant_cast<GeoDataObject*>(index.data( MarblePlacemarkModel::ObjectPointerRole ) ); 0501 if (GeoDataAnimatedUpdate *animatedUpdate = geodata_cast<GeoDataAnimatedUpdate>(object)) { 0502 if( animatedUpdate->update() && animatedUpdate->update()->create() ) { 0503 if( editAnimatedUpdate( animatedUpdate ) ) { 0504 setDefaultFeatureId( m_defaultFeatureId ); 0505 } 0506 } else if( animatedUpdate->update() && animatedUpdate->update()->change() ) { 0507 editAnimatedUpdate( animatedUpdate, false ); 0508 } else if ( animatedUpdate->update() && animatedUpdate->update()->getDelete() ) { 0509 m_editingIndices.append( index ); 0510 m_listView->openPersistentEditor( index ); 0511 } 0512 } else { 0513 m_editingIndices.append( index ); 0514 m_listView->openPersistentEditor( index ); 0515 } 0516 } 0517 emit editingChanged( index ); 0518 return true; 0519 } 0520 } 0521 return false; 0522 } 0523 0524 void TourItemDelegate::closeEditor( const QModelIndex &index ) 0525 { 0526 emit edited( index ); 0527 m_listView->closePersistentEditor( index ); 0528 m_editingIndices.removeOne( index ); 0529 } 0530 0531 } 0532 0533 #include "moc_TourItemDelegate.cpp"