File indexing completed on 2024-04-28 15:16:02

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2014 Sanjiban Bairagya <sanjiban22393@gmail.com>
0004 //
0005 
0006 #include "PlaybackAnimatedUpdateItem.h"
0007 
0008 #include "GeoDataAnimatedUpdate.h"
0009 #include "GeoDataDocument.h"
0010 #include "GeoDataPlacemark.h"
0011 #include "GeoDataCreate.h"
0012 #include "GeoDataUpdate.h"
0013 #include "GeoDataDelete.h"
0014 #include "GeoDataChange.h"
0015 #include "GeoDataFolder.h"
0016 #include "GeoDataGroundOverlay.h"
0017 #include "GeoDataPhotoOverlay.h"
0018 #include "GeoDataScreenOverlay.h"
0019 
0020 #include <QString>
0021 
0022 namespace Marble
0023 {
0024 PlaybackAnimatedUpdateItem::PlaybackAnimatedUpdateItem( GeoDataAnimatedUpdate* animatedUpdate )
0025 {
0026     m_animatedUpdate = animatedUpdate;
0027     m_rootDocument = rootDocument( m_animatedUpdate );
0028     m_playing = false;
0029 }
0030 
0031 const GeoDataAnimatedUpdate* PlaybackAnimatedUpdateItem::animatedUpdate() const
0032 {
0033     return m_animatedUpdate;
0034 }
0035 
0036 double PlaybackAnimatedUpdateItem::duration() const
0037 {
0038     return m_animatedUpdate->duration();
0039 }
0040 
0041 void PlaybackAnimatedUpdateItem::play()
0042 {
0043     if( m_playing ){
0044         return;
0045     }
0046     m_playing = true;
0047 
0048     if ( !m_rootDocument || !m_animatedUpdate->update() ) {
0049         return;
0050     }
0051 
0052     // Apply updates of elements
0053     if ( m_animatedUpdate->update()->change() ) {
0054         QVector<GeoDataPlacemark*> placemarkList = m_animatedUpdate->update()->change()->placemarkList();
0055         for( int i = 0; i < placemarkList.size(); i++ ){
0056             GeoDataPlacemark* placemark = placemarkList.at( i );
0057             QString targetId = placemark->targetId();
0058             if( targetId.isEmpty() ) {
0059                 continue;
0060             }
0061             if( placemark->isBalloonVisible() ){
0062                 GeoDataFeature* feature = findFeature( m_rootDocument, targetId );
0063                 if (auto placemark = geodata_cast<GeoDataPlacemark>(feature)) {
0064                     emit balloonShown(placemark);
0065                 }
0066             } else {
0067                 emit balloonHidden();
0068             }
0069         }
0070     }
0071 
0072     // Create new elements
0073     if( m_animatedUpdate->update()->create() ){
0074         for( int index = 0; index < m_animatedUpdate->update()->create()->size(); ++index ) {
0075             GeoDataFeature* child = m_animatedUpdate->update()->create()->child( index );
0076             if( child &&
0077                     (geodata_cast<GeoDataDocument>(child)||
0078                      geodata_cast<GeoDataFolder>(child))) {
0079                 GeoDataContainer *addContainer = static_cast<GeoDataContainer*>( child );
0080                 QString targetId = addContainer->targetId();
0081                 GeoDataFeature* feature = findFeature( m_rootDocument, targetId );
0082                 if( feature &&
0083                         (geodata_cast<GeoDataDocument>(feature) ||
0084                          geodata_cast<GeoDataFolder>(feature))) {
0085                     GeoDataContainer* container = static_cast<GeoDataContainer*>( feature );
0086                     for( int i = 0; i < addContainer->size(); ++i ) {
0087                         emit added( container, addContainer->child( i ), -1 );
0088                         if (auto placemark = geodata_cast<GeoDataPlacemark>(addContainer->child(i)))
0089                         {
0090                             if( placemark->isBalloonVisible() ) {
0091                                 emit balloonShown( placemark );
0092                             }
0093                         }
0094                     }
0095                 }
0096 
0097             }
0098         }
0099     }
0100 
0101     // Delete elements
0102     if( m_animatedUpdate->update()->getDelete() ){
0103         for( int index = 0; index < m_animatedUpdate->update()->getDelete()->size(); ++index ) {
0104             GeoDataFeature* child = m_animatedUpdate->update()->getDelete()->child( index );
0105             QString targetId = child->targetId();
0106             if( targetId.isEmpty() ) {
0107                 continue;
0108             }
0109             GeoDataFeature* feature = findFeature( m_rootDocument, targetId );
0110             if (feature && canDelete(*feature)) {
0111                 m_deletedObjects.append( feature );
0112                 emit removed( feature );
0113                 if (auto placemark = geodata_cast<GeoDataPlacemark>(feature))
0114                 {
0115                     if( placemark->isBalloonVisible() ) {
0116                         emit balloonHidden();
0117                     }
0118                 }
0119             }
0120         }
0121     }
0122 }
0123 
0124 GeoDataFeature* PlaybackAnimatedUpdateItem::findFeature(GeoDataFeature* feature, const QString& id ) const
0125 {
0126     if ( feature && feature->id() == id ){
0127         return feature;
0128     }
0129 
0130     GeoDataContainer *container = dynamic_cast<GeoDataContainer*>( feature );
0131     if ( container ){
0132         QVector<GeoDataFeature*>::Iterator end = container->end();
0133         QVector<GeoDataFeature*>::Iterator iter = container->begin();
0134         for( ; iter != end; ++iter ){
0135             GeoDataFeature *foundFeature = findFeature( *iter, id );
0136             if ( foundFeature ){
0137                 return foundFeature;
0138             }
0139         }
0140     }
0141     return nullptr;
0142 }
0143 
0144 GeoDataDocument *PlaybackAnimatedUpdateItem::rootDocument( GeoDataObject* object ) const
0145 {
0146     if( !object || !object->parent() ){
0147         GeoDataDocument* document = dynamic_cast<GeoDataDocument*>( object );
0148         return document;
0149     } else {
0150         return rootDocument( object->parent() );
0151     }
0152     return nullptr;
0153 }
0154 
0155 void PlaybackAnimatedUpdateItem::pause()
0156 {
0157     //do nothing
0158 }
0159 
0160 void PlaybackAnimatedUpdateItem::seek( double position )
0161 {
0162     Q_UNUSED( position );
0163     play();
0164 }
0165 
0166 void PlaybackAnimatedUpdateItem::stop()
0167 {
0168     if( !m_playing ){
0169         return;
0170     }
0171     m_playing = false;
0172 
0173     if ( m_animatedUpdate->update()->change() ) {
0174         QVector<GeoDataPlacemark*> placemarkList = m_animatedUpdate->update()->change()->placemarkList();
0175         for( int i = 0; i < placemarkList.size(); i++ ){
0176             GeoDataPlacemark* placemark = placemarkList.at( i );
0177             QString targetId = placemark->targetId();
0178             if( targetId.isEmpty() ) {
0179                 continue;
0180             }
0181             GeoDataFeature* feature = findFeature( m_rootDocument, targetId );
0182             if( placemark->isBalloonVisible() ){
0183                 if (geodata_cast<GeoDataPlacemark>(feature)) {
0184                     emit balloonHidden();
0185                 }
0186             } else {
0187                 emit balloonShown( static_cast<GeoDataPlacemark*>( feature ) );
0188             }
0189         }
0190     }
0191 
0192     if( m_animatedUpdate->update()->create() ){
0193         for( int index = 0; index < m_animatedUpdate->update()->create()->size(); ++index ) {
0194             GeoDataFeature* feature = m_animatedUpdate->update()->create()->child( index );
0195             if( feature &&
0196                     (geodata_cast<GeoDataDocument>(feature) ||
0197                      geodata_cast<GeoDataFolder>(feature))) {
0198                 GeoDataContainer* container = static_cast<GeoDataContainer*>( feature );
0199                 for( int i = 0; i < container->size(); ++i ) {
0200 
0201                     emit removed( container->child( i ) );
0202                     if (auto placemark = geodata_cast<GeoDataPlacemark>(container->child(i)))
0203                     {
0204                         if( placemark->isBalloonVisible() ) {
0205                             emit balloonHidden();
0206                         }
0207                     }
0208                 }
0209             }
0210         }
0211     }
0212 
0213     for( GeoDataFeature* feature: m_deletedObjects ) {
0214         if( feature->targetId().isEmpty() ) {
0215             continue;
0216         }
0217         GeoDataFeature* target = findFeature( m_rootDocument, feature->targetId() );
0218         if ( target ) {
0219             /** @todo Do we have to note the original row position and restore it? */
0220             Q_ASSERT( dynamic_cast<GeoDataContainer*>( target ) );
0221             emit added( static_cast<GeoDataContainer*>( target ), feature, -1 );
0222             if (auto placemark = geodata_cast<GeoDataPlacemark>(feature))
0223             {
0224                 if( placemark->isBalloonVisible() ) {
0225                     emit balloonShown( placemark );
0226                 }
0227             }
0228         } // else the root document was modified in an unfortunate way and we cannot restore it at this point
0229     }
0230     m_deletedObjects.clear();
0231 }
0232 
0233 bool PlaybackAnimatedUpdateItem::isApplied() const
0234 {
0235     return m_playing;
0236 }
0237 
0238 bool PlaybackAnimatedUpdateItem::canDelete(const GeoDataFeature &feature)
0239 {
0240     return  geodata_cast<GeoDataDocument>(&feature) ||
0241             geodata_cast<GeoDataFolder>(&feature) ||
0242             geodata_cast<GeoDataGroundOverlay>(&feature) ||
0243             geodata_cast<GeoDataPlacemark>(&feature) ||
0244             geodata_cast<GeoDataScreenOverlay>(&feature) ||
0245             geodata_cast<GeoDataPhotoOverlay>(&feature);
0246 }
0247 
0248 }
0249 
0250 #include "moc_PlaybackAnimatedUpdateItem.cpp"