File indexing completed on 2024-03-24 03:52:40
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2008 Henry de Valence <hdevalence@gmail.com> 0004 // SPDX-FileCopyrightText: 2010 Dennis Nienhüser <nienhueser@kde.org> 0005 // SPDX-FileCopyrightText: 2010-2013 Bernhard Beschow <bbeschow@cs.tu-berlin.de> 0006 // SPDX-FileCopyrightText: 2011 Thibaut Gridel <tgridel@free.fr> 0007 0008 #include "ReverseGeocodingRunnerManager.h" 0009 0010 #include "MarbleDebug.h" 0011 #include "MarbleModel.h" 0012 #include "GeoDataCoordinates.h" 0013 #include "GeoDataPlacemark.h" 0014 #include "Planet.h" 0015 #include "PluginManager.h" 0016 #include "ReverseGeocodingRunnerPlugin.h" 0017 #include "RunnerTask.h" 0018 0019 #include <QList> 0020 #include <QThreadPool> 0021 #include <QTimer> 0022 0023 namespace Marble 0024 { 0025 0026 class MarbleModel; 0027 0028 class Q_DECL_HIDDEN ReverseGeocodingRunnerManager::Private 0029 { 0030 public: 0031 Private( ReverseGeocodingRunnerManager *parent, const MarbleModel *marbleModel ); 0032 0033 QList<const ReverseGeocodingRunnerPlugin *> plugins( const QList<const ReverseGeocodingRunnerPlugin *> &plugins ) const; 0034 0035 void addReverseGeocodingResult( const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark ); 0036 void cleanupReverseGeocodingTask( ReverseGeocodingTask *task ); 0037 0038 ReverseGeocodingRunnerManager *const q; 0039 const MarbleModel *const m_marbleModel; 0040 const PluginManager* m_pluginManager; 0041 QList<ReverseGeocodingTask*> m_reverseTasks; 0042 QVector<GeoDataCoordinates> m_reverseGeocodingResults; 0043 QString m_reverseGeocodingResult; 0044 }; 0045 0046 ReverseGeocodingRunnerManager::Private::Private( ReverseGeocodingRunnerManager *parent, const MarbleModel *marbleModel ) : 0047 q( parent ), 0048 m_marbleModel( marbleModel ), 0049 m_pluginManager( marbleModel->pluginManager() ) 0050 { 0051 qRegisterMetaType<GeoDataPlacemark>( "GeoDataPlacemark" ); 0052 qRegisterMetaType<GeoDataCoordinates>( "GeoDataCoordinates" ); 0053 } 0054 0055 QList<const ReverseGeocodingRunnerPlugin *> ReverseGeocodingRunnerManager::Private::plugins( const QList<const ReverseGeocodingRunnerPlugin *> &plugins ) const 0056 { 0057 QList<const ReverseGeocodingRunnerPlugin *> result; 0058 0059 for( const ReverseGeocodingRunnerPlugin *plugin: plugins ) { 0060 if ( ( m_marbleModel && m_marbleModel->workOffline() && !plugin->canWorkOffline() ) ) { 0061 continue; 0062 } 0063 0064 if ( !plugin->canWork() ) { 0065 continue; 0066 } 0067 0068 if ( m_marbleModel && !plugin->supportsCelestialBody( m_marbleModel->planet()->id() ) ) 0069 { 0070 continue; 0071 } 0072 0073 result << plugin; 0074 } 0075 0076 return result; 0077 } 0078 0079 void ReverseGeocodingRunnerManager::Private::addReverseGeocodingResult( const GeoDataCoordinates &coordinates, const GeoDataPlacemark &placemark ) 0080 { 0081 if ( !m_reverseGeocodingResults.contains( coordinates ) && !placemark.address().isEmpty() ) { 0082 m_reverseGeocodingResults.push_back( coordinates ); 0083 m_reverseGeocodingResult = placemark.address(); 0084 emit q->reverseGeocodingFinished( coordinates, placemark ); 0085 } 0086 0087 if ( m_reverseTasks.isEmpty() ) { 0088 emit q->reverseGeocodingFinished(); 0089 } 0090 } 0091 0092 void ReverseGeocodingRunnerManager::Private::cleanupReverseGeocodingTask( ReverseGeocodingTask *task ) 0093 { 0094 m_reverseTasks.removeAll( task ); 0095 mDebug() << "removing task " << m_reverseTasks.size() << " " << (quintptr)task; 0096 if ( m_reverseTasks.isEmpty() ) { 0097 emit q->reverseGeocodingFinished(); 0098 } 0099 } 0100 0101 ReverseGeocodingRunnerManager::ReverseGeocodingRunnerManager( const MarbleModel *marbleModel, QObject *parent ) : 0102 QObject( parent ), 0103 d( new Private( this, marbleModel ) ) 0104 { 0105 if ( QThreadPool::globalInstance()->maxThreadCount() < 4 ) { 0106 QThreadPool::globalInstance()->setMaxThreadCount( 4 ); 0107 } 0108 } 0109 0110 ReverseGeocodingRunnerManager::~ReverseGeocodingRunnerManager() 0111 { 0112 delete d; 0113 } 0114 0115 void ReverseGeocodingRunnerManager::reverseGeocoding( const GeoDataCoordinates &coordinates ) 0116 { 0117 d->m_reverseTasks.clear(); 0118 d->m_reverseGeocodingResult.clear(); 0119 d->m_reverseGeocodingResults.removeAll( coordinates ); 0120 0121 QList<const ReverseGeocodingRunnerPlugin*> plugins = d->plugins( d->m_pluginManager->reverseGeocodingRunnerPlugins() ); 0122 for( const ReverseGeocodingRunnerPlugin* plugin: plugins ) { 0123 ReverseGeocodingTask* task = new ReverseGeocodingTask( plugin->newRunner(), this, d->m_marbleModel, coordinates ); 0124 connect( task, SIGNAL(finished(ReverseGeocodingTask*)), this, SLOT(cleanupReverseGeocodingTask(ReverseGeocodingTask*)) ); 0125 mDebug() << "reverse task " << plugin->nameId() << " " << (quintptr)task; 0126 d->m_reverseTasks << task; 0127 } 0128 0129 for( ReverseGeocodingTask* task: d->m_reverseTasks ) { 0130 QThreadPool::globalInstance()->start( task ); 0131 } 0132 0133 if ( plugins.isEmpty() ) { 0134 GeoDataPlacemark anonymous; 0135 anonymous.setCoordinate( coordinates ); 0136 emit reverseGeocodingFinished( coordinates, anonymous ); 0137 d->cleanupReverseGeocodingTask( nullptr ); 0138 } 0139 } 0140 0141 QString ReverseGeocodingRunnerManager::searchReverseGeocoding( const GeoDataCoordinates &coordinates, int timeout ) { 0142 QEventLoop localEventLoop; 0143 QTimer watchdog; 0144 watchdog.setSingleShot(true); 0145 connect( &watchdog, SIGNAL(timeout()), 0146 &localEventLoop, SLOT(quit())); 0147 connect(this, SIGNAL(reverseGeocodingFinished()), 0148 &localEventLoop, SLOT(quit()), Qt::QueuedConnection ); 0149 0150 watchdog.start( timeout ); 0151 reverseGeocoding( coordinates ); 0152 localEventLoop.exec(); 0153 return d->m_reverseGeocodingResult; 0154 } 0155 0156 } 0157 0158 #include "moc_ReverseGeocodingRunnerManager.cpp"