File indexing completed on 2024-05-05 03:49:20

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2011 Dennis Nienhüser <nienhueser@kde.org>
0004 //
0005 
0006 #include "Tracking.h"
0007 
0008 #include "MarbleQuickItem.h"
0009 #include "MarbleModel.h"
0010 #include "PositionTracking.h"
0011 #include "RenderPlugin.h"
0012 #include "ViewportParams.h"
0013 #include "AutoNavigation.h"
0014 
0015 namespace Marble {
0016 
0017 Tracking::Tracking( QObject* parent) : QObject( parent ),
0018     m_showTrack( true ),
0019     m_positionSource( nullptr ),
0020     m_positionMarker( nullptr ),
0021     m_marbleQuickItem( nullptr ),
0022     m_hasLastKnownPosition( false ),
0023     m_autoNavigation( nullptr ),
0024     m_positionMarkerType( None )
0025 {
0026     connect( &m_lastKnownPosition, SIGNAL(longitudeChanged()), this, SLOT(setHasLastKnownPosition()) );
0027     connect( &m_lastKnownPosition, SIGNAL(latitudeChanged()), this, SLOT(setHasLastKnownPosition()) );
0028 }
0029 
0030 bool Tracking::showTrack() const
0031 {
0032     return m_showTrack;
0033 }
0034 
0035 void Tracking::setShowTrack( bool show )
0036 {
0037     if ( show != m_showTrack ) {
0038         if ( m_marbleQuickItem ) {
0039             m_marbleQuickItem->model()->positionTracking()->setTrackVisible( show );
0040             m_marbleQuickItem->update();
0041         }
0042 
0043         m_showTrack = show;
0044         emit showTrackChanged();
0045     }
0046 }
0047 
0048 PositionSource* Tracking::positionSource()
0049 {
0050     return m_positionSource;
0051 }
0052 
0053 void Tracking::setPositionSource( PositionSource* source )
0054 {
0055     if ( source != m_positionSource ) {
0056         m_positionSource = source;
0057         if ( source ) {
0058             connect( source, SIGNAL(positionChanged()),
0059                     this, SLOT(updatePositionMarker()) );
0060             connect( source, SIGNAL(positionChanged()),
0061                     this, SLOT(updateLastKnownPosition()) );
0062             connect( source, SIGNAL(hasPositionChanged()),
0063                     this, SLOT(updatePositionMarker()) );
0064             connect( source, SIGNAL(positionChanged()),
0065                      this, SIGNAL(distanceChanged()) );
0066         }
0067         emit positionSourceChanged();
0068     }
0069 }
0070 
0071 MarbleQuickItem* Tracking::map()
0072 {
0073     return m_marbleQuickItem;
0074 }
0075 
0076 void Tracking::setMap( MarbleQuickItem* item )
0077 {
0078     if ( item != m_marbleQuickItem ) {
0079         m_marbleQuickItem = item;
0080 
0081         if ( m_marbleQuickItem ) {
0082             m_marbleQuickItem->model()->positionTracking()->setTrackVisible( showTrack() );
0083             setShowPositionMarkerPlugin( m_positionMarkerType == Arrow );
0084 
0085             connect( m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()), this, SLOT(updatePositionMarker()) );
0086             connect( m_marbleQuickItem, SIGNAL(mapThemeChanged()), this, SLOT(updatePositionMarker()) );
0087         }
0088 
0089         emit mapChanged();
0090     }
0091 }
0092 
0093 void Tracking::setPositionMarker( QObject* marker )
0094 {
0095     if ( marker != m_positionMarker ) {
0096         m_positionMarker = marker;
0097         emit positionMarkerChanged();
0098     }
0099 }
0100 
0101 QObject* Tracking::positionMarker()
0102 {
0103     return m_positionMarker;
0104 }
0105 
0106 void Tracking::updatePositionMarker()
0107 {
0108     if ( m_marbleQuickItem && m_positionMarker && m_positionMarkerType == Circle ) {
0109         Coordinate* position = nullptr;
0110         bool visible = (m_marbleQuickItem->model()->planetId() == QLatin1String("earth"));
0111         if ( m_positionSource && m_positionSource->hasPosition() ) {
0112             position = m_positionSource->position();
0113         } else if ( hasLastKnownPosition() ) {
0114             position = lastKnownPosition();
0115         } else {
0116             visible = false;
0117         }
0118 
0119         qreal x(0), y(0);
0120         if ( position ) {
0121             Marble::GeoDataCoordinates const pos( position->longitude(), position->latitude(), 0.0, GeoDataCoordinates::Degree );
0122             visible = visible && m_marbleQuickItem->map()->viewport()->screenCoordinates( pos.longitude(), pos.latitude(), x, y );
0123             QQuickItem* item = qobject_cast<QQuickItem*>( m_positionMarker );
0124             if ( item ) {
0125                 item->setVisible( visible );
0126                 if ( visible ) {
0127                     item->setX( x - item->width() / 2.0 );
0128                     item->setY( y - item->height() / 2.0 );
0129                 }
0130             }
0131         }
0132     } else if ( m_positionMarkerType != Circle ) {
0133         QQuickItem* item = qobject_cast<QQuickItem*>( m_positionMarker );
0134         if ( item ) {
0135             item->setVisible( false );
0136         }
0137     }
0138 }
0139 
0140 void Tracking::updateLastKnownPosition()
0141 {
0142     if ( m_positionSource && m_positionSource->hasPosition() ) {
0143         setLastKnownPosition( m_positionSource->position() );
0144     }
0145 }
0146 
0147 void Tracking::setHasLastKnownPosition()
0148 {
0149     if ( !m_hasLastKnownPosition ) {
0150         m_hasLastKnownPosition = true;
0151         emit hasLastKnownPositionChanged();
0152     }
0153 }
0154 
0155 void Tracking::setShowPositionMarkerPlugin( bool visible )
0156 {
0157     if ( m_marbleQuickItem ) {
0158         QList<RenderPlugin*> const renderPlugins = m_marbleQuickItem->map()->renderPlugins();
0159         for( RenderPlugin* renderPlugin: renderPlugins ) {
0160             Q_ASSERT( renderPlugin );
0161             if (renderPlugin->nameId() == QLatin1String("positionMarker")) {
0162                 renderPlugin->setEnabled( true );
0163                 renderPlugin->setVisible( visible );
0164             }
0165         }
0166    }
0167 }
0168 
0169 bool Tracking::hasLastKnownPosition() const
0170 {
0171     return m_hasLastKnownPosition;
0172 }
0173 
0174 Coordinate * Tracking::lastKnownPosition()
0175 {
0176     return &m_lastKnownPosition;
0177 }
0178 
0179 void Tracking::setLastKnownPosition( Coordinate* lastKnownPosition )
0180 {
0181     if ( lastKnownPosition && *lastKnownPosition != m_lastKnownPosition ) {
0182         m_lastKnownPosition.setCoordinates( lastKnownPosition->coordinates() );
0183         emit lastKnownPositionChanged();
0184     }
0185 }
0186 
0187 bool Tracking::autoCenter() const
0188 {
0189     if ( m_autoNavigation ) {
0190         return m_autoNavigation->recenterMode() != Marble::AutoNavigation::DontRecenter;
0191     }
0192 
0193     return false;
0194 }
0195 
0196 void Tracking::setAutoCenter( bool enabled )
0197 {
0198     if ( autoCenter() != enabled ) {
0199         if ( enabled && !m_autoNavigation && m_marbleQuickItem ) {
0200             m_autoNavigation = new Marble::AutoNavigation( m_marbleQuickItem->model(), m_marbleQuickItem->map()->viewport(), this );
0201             connect( m_autoNavigation, SIGNAL(zoomIn(FlyToMode)),
0202                      m_marbleQuickItem, SLOT(zoomIn()) );
0203             connect( m_autoNavigation, SIGNAL(zoomOut(FlyToMode)),
0204                      m_marbleQuickItem, SLOT(zoomOut()) );
0205             connect( m_autoNavigation, SIGNAL(centerOn(GeoDataCoordinates,bool)),
0206                      m_marbleQuickItem, SLOT(centerOn(GeoDataCoordinates)) );
0207 
0208             connect( m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()),
0209                      m_autoNavigation, SLOT(inhibitAutoAdjustments()) );
0210         }
0211 
0212         if ( m_autoNavigation ) {
0213             m_autoNavigation->setRecenter( Marble::AutoNavigation::RecenterOnBorder );
0214         }
0215 
0216         emit autoCenterChanged();
0217     }
0218 }
0219 
0220 bool Tracking::autoZoom() const
0221 {
0222     if ( m_autoNavigation ) {
0223         return m_autoNavigation->autoZoom();
0224     }
0225 
0226     return false;
0227 }
0228 
0229 void Tracking::setAutoZoom( bool enabled )
0230 {
0231     if ( autoZoom() != enabled ) {
0232         if ( enabled && !m_autoNavigation && m_marbleQuickItem ) {
0233             m_autoNavigation = new Marble::AutoNavigation( m_marbleQuickItem->model(), m_marbleQuickItem->map()->viewport(), this );
0234             connect( m_autoNavigation, SIGNAL(zoomIn(FlyToMode)),
0235                      m_marbleQuickItem, SLOT(zoomIn()) );
0236             connect( m_autoNavigation, SIGNAL(zoomOut(FlyToMode)),
0237                      m_marbleQuickItem, SLOT(zoomOut()) );
0238             connect( m_autoNavigation, SIGNAL(centerOn(GeoDataCoordinates,bool)),
0239                      m_marbleQuickItem, SLOT(centerOn(GeoDataCoordinates)) );
0240 
0241             connect( m_marbleQuickItem, SIGNAL(visibleLatLonAltBoxChanged()),
0242                      m_autoNavigation, SLOT(inhibitAutoAdjustments()) );
0243         }
0244 
0245         if ( m_autoNavigation ) {
0246             m_autoNavigation->setAutoZoom( enabled );
0247         }
0248 
0249         emit autoZoomChanged();
0250     }
0251 }
0252 
0253 Tracking::PositionMarkerType Tracking::positionMarkerType() const
0254 {
0255     return m_positionMarkerType;
0256 }
0257 
0258 void Tracking::setPositionMarkerType( Tracking::PositionMarkerType type )
0259 {
0260     setShowPositionMarkerPlugin( type == Arrow );
0261     if ( type != m_positionMarkerType ) {
0262         m_positionMarkerType = type;
0263         emit positionMarkerTypeChanged();
0264     }
0265 }
0266 
0267 double Tracking::distance() const
0268 {
0269     return m_marbleQuickItem ? m_marbleQuickItem->model()->positionTracking()->length( m_marbleQuickItem->model()->planetRadius() ) : 0.0;
0270 }
0271 
0272 void Tracking::saveTrack( const QString &fileName )
0273 {
0274     if ( m_marbleQuickItem ) {
0275         /** @todo FIXME: replace the file:// prefix on QML side */
0276         QString target = fileName.startsWith( QLatin1String( "file://" ) ) ? fileName.mid( 7 ) : fileName;
0277         m_marbleQuickItem->model()->positionTracking()->saveTrack( target );
0278     }
0279 }
0280 
0281 void Tracking::openTrack(const QString &fileName)
0282 {
0283     if ( m_marbleQuickItem ) {
0284         /** @todo FIXME: replace the file:// prefix on QML side */
0285         QString target = fileName.startsWith( QLatin1String( "file://" ) ) ? fileName.mid( 7 ) : fileName;
0286         m_marbleQuickItem->model()->addGeoDataFile( target );
0287     }
0288 }
0289 
0290 void Tracking::clearTrack()
0291 {
0292     if ( m_marbleQuickItem ) {
0293         m_marbleQuickItem->model()->positionTracking()->clearTrack();
0294     }
0295 }
0296 
0297 }
0298 
0299 #include "moc_Tracking.cpp"