File indexing completed on 2024-03-24 03:52:41
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 "RoutingRunnerManager.h" 0009 0010 #include "MarblePlacemarkModel.h" 0011 #include "MarbleDebug.h" 0012 #include "MarbleModel.h" 0013 #include "Planet.h" 0014 #include "GeoDataDocument.h" 0015 #include "PluginManager.h" 0016 #include "RoutingRunnerPlugin.h" 0017 #include "RunnerTask.h" 0018 #include "routing/RouteRequest.h" 0019 #include "routing/RoutingProfilesModel.h" 0020 0021 #include <QThreadPool> 0022 #include <QTimer> 0023 0024 namespace Marble 0025 { 0026 0027 class MarbleModel; 0028 0029 class Q_DECL_HIDDEN RoutingRunnerManager::Private 0030 { 0031 public: 0032 Private( RoutingRunnerManager *parent, const MarbleModel *marbleModel ); 0033 0034 ~Private(); 0035 0036 template<typename T> 0037 QList<T*> plugins( const QList<T*> &plugins ) const; 0038 0039 void addRoutingResult( GeoDataDocument *route ); 0040 void cleanupRoutingTask( RoutingTask *task ); 0041 0042 RoutingRunnerManager *const q; 0043 const MarbleModel *const m_marbleModel; 0044 const PluginManager *const m_pluginManager; 0045 QList<RoutingTask*> m_routingTasks; 0046 QVector<GeoDataDocument*> m_routingResult; 0047 }; 0048 0049 RoutingRunnerManager::Private::Private( RoutingRunnerManager *parent, const MarbleModel *marbleModel ) : 0050 q( parent ), 0051 m_marbleModel( marbleModel ), 0052 m_pluginManager( marbleModel->pluginManager() ) 0053 { 0054 qRegisterMetaType<GeoDataDocument*>( "GeoDataDocument*" ); 0055 } 0056 0057 RoutingRunnerManager::Private::~Private() 0058 { 0059 // nothing to do 0060 } 0061 0062 template<typename T> 0063 QList<T*> RoutingRunnerManager::Private::plugins( const QList<T*> &plugins ) const 0064 { 0065 QList<T*> result; 0066 for( T* plugin: plugins ) { 0067 if ( ( m_marbleModel && m_marbleModel->workOffline() && !plugin->canWorkOffline() ) ) { 0068 continue; 0069 } 0070 0071 if ( !plugin->canWork() ) { 0072 continue; 0073 } 0074 0075 if ( m_marbleModel && !plugin->supportsCelestialBody( m_marbleModel->planet()->id() ) ) 0076 { 0077 continue; 0078 } 0079 0080 result << plugin; 0081 } 0082 0083 return result; 0084 } 0085 0086 void RoutingRunnerManager::Private::addRoutingResult( GeoDataDocument *route ) 0087 { 0088 if ( route ) { 0089 mDebug() << "route retrieved"; 0090 m_routingResult.push_back( route ); 0091 emit q->routeRetrieved( route ); 0092 } 0093 } 0094 0095 void RoutingRunnerManager::Private::cleanupRoutingTask( RoutingTask *task ) 0096 { 0097 m_routingTasks.removeAll( task ); 0098 mDebug() << "removing task" << m_routingTasks.size() << " " << (quintptr)task; 0099 if ( m_routingTasks.isEmpty() ) { 0100 if ( m_routingResult.isEmpty() ) { 0101 emit q->routeRetrieved( nullptr ); 0102 } 0103 0104 emit q->routingFinished(); 0105 } 0106 } 0107 0108 RoutingRunnerManager::RoutingRunnerManager( const MarbleModel *marbleModel, QObject *parent ) 0109 : QObject( parent ), 0110 d( new Private( this, marbleModel ) ) 0111 { 0112 if ( QThreadPool::globalInstance()->maxThreadCount() < 4 ) { 0113 QThreadPool::globalInstance()->setMaxThreadCount( 4 ); 0114 } 0115 } 0116 0117 RoutingRunnerManager::~RoutingRunnerManager() 0118 { 0119 delete d; 0120 } 0121 0122 void RoutingRunnerManager::retrieveRoute( const RouteRequest *request ) 0123 { 0124 RoutingProfile profile = request->routingProfile(); 0125 0126 d->m_routingTasks.clear(); 0127 d->m_routingResult.clear(); 0128 0129 QList<RoutingRunnerPlugin*> plugins = d->plugins( d->m_pluginManager->routingRunnerPlugins() ); 0130 for( RoutingRunnerPlugin* plugin: plugins ) { 0131 if ( !profile.name().isEmpty() && !profile.pluginSettings().contains( plugin->nameId() ) ) { 0132 continue; 0133 } 0134 0135 RoutingTask* task = new RoutingTask( plugin->newRunner(), this, request ); 0136 connect( task, SIGNAL(finished(RoutingTask*)), this, SLOT(cleanupRoutingTask(RoutingTask*)) ); 0137 mDebug() << "route task" << plugin->nameId() << " " << (quintptr)task; 0138 d->m_routingTasks << task; 0139 } 0140 0141 for( RoutingTask* task: d->m_routingTasks ) { 0142 QThreadPool::globalInstance()->start( task ); 0143 } 0144 0145 if ( d->m_routingTasks.isEmpty() ) { 0146 mDebug() << "No suitable routing plugins found, cannot retrieve a route"; 0147 d->cleanupRoutingTask( nullptr ); 0148 } 0149 } 0150 0151 QVector<GeoDataDocument*> RoutingRunnerManager::searchRoute( const RouteRequest *request, int timeout ) { 0152 QEventLoop localEventLoop; 0153 QTimer watchdog; 0154 watchdog.setSingleShot(true); 0155 connect( &watchdog, SIGNAL(timeout()), 0156 &localEventLoop, SLOT(quit())); 0157 connect(this, SIGNAL(routingFinished()), 0158 &localEventLoop, SLOT(quit()), Qt::QueuedConnection ); 0159 0160 watchdog.start( timeout ); 0161 retrieveRoute( request ); 0162 localEventLoop.exec(); 0163 return d->m_routingResult; 0164 } 0165 0166 } 0167 0168 #include "moc_RoutingRunnerManager.cpp"