File indexing completed on 2024-04-21 03:49:50

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 "ParsingRunnerManager.h"
0009 
0010 #include "MarbleDebug.h"
0011 #include "PluginManager.h"
0012 #include "ParseRunnerPlugin.h"
0013 #include "RunnerTask.h"
0014 
0015 #include <QFileInfo>
0016 #include <QList>
0017 #include <QThreadPool>
0018 #include <QTimer>
0019 #include <QMutex>
0020 
0021 namespace Marble
0022 {
0023 
0024 class MarbleModel;
0025 
0026 class Q_DECL_HIDDEN ParsingRunnerManager::Private
0027 {
0028 public:
0029     Private( ParsingRunnerManager *parent, const PluginManager *pluginManager );
0030 
0031     ~Private();
0032 
0033     void cleanupParsingTask();
0034     void addParsingResult(GeoDataDocument *document, const QString &error);
0035 
0036     ParsingRunnerManager *const q;
0037     const PluginManager *const m_pluginManager;
0038     QMutex m_parsingTasksMutex;
0039     int m_parsingTasks;
0040     GeoDataDocument *m_fileResult;
0041 };
0042 
0043 ParsingRunnerManager::Private::Private( ParsingRunnerManager *parent, const PluginManager *pluginManager ) :
0044     q( parent ),
0045     m_pluginManager( pluginManager ),
0046     m_parsingTasks(0),
0047     m_fileResult( nullptr )
0048 {
0049     qRegisterMetaType<GeoDataDocument*>( "GeoDataDocument*" );
0050 }
0051 
0052 ParsingRunnerManager::Private::~Private()
0053 {
0054     // nothing to do
0055 }
0056 
0057 void ParsingRunnerManager::Private::cleanupParsingTask()
0058 {
0059     QMutexLocker locker(&m_parsingTasksMutex);
0060     m_parsingTasks = qMax(0, m_parsingTasks-1);
0061     if (m_parsingTasks == 0) {
0062         emit q->parsingFinished();
0063     }
0064 }
0065 
0066 ParsingRunnerManager::ParsingRunnerManager( const PluginManager *pluginManager, QObject *parent ) :
0067     QObject( parent ),
0068     d( new Private( this, pluginManager ) )
0069 {
0070     if ( QThreadPool::globalInstance()->maxThreadCount() < 4 ) {
0071         QThreadPool::globalInstance()->setMaxThreadCount( 4 );
0072     }
0073 }
0074 
0075 ParsingRunnerManager::~ParsingRunnerManager()
0076 {
0077     delete d;
0078 }
0079 
0080 void ParsingRunnerManager::parseFile( const QString &fileName, DocumentRole role )
0081 {
0082     QList<const ParseRunnerPlugin*> plugins = d->m_pluginManager->parsingRunnerPlugins();
0083     const QFileInfo fileInfo( fileName );
0084     const QString suffix = fileInfo.suffix().toLower();
0085     const QString completeSuffix = fileInfo.completeSuffix().toLower();
0086 
0087     d->m_parsingTasks = 0;
0088     for( const ParseRunnerPlugin *plugin: plugins ) {
0089         QStringList const extensions = plugin->fileExtensions();
0090         if ( extensions.isEmpty() || extensions.contains( suffix ) || extensions.contains( completeSuffix ) ) {
0091             ParsingTask *task = new ParsingTask( plugin->newRunner(), this, fileName, role );
0092             connect( task, SIGNAL(finished()), this, SLOT(cleanupParsingTask()) );
0093             mDebug() << "parse task " << plugin->nameId() << " " << (quintptr)task;
0094             ++d->m_parsingTasks;
0095             QThreadPool::globalInstance()->start( task );
0096         }
0097     }
0098 
0099     if (d->m_parsingTasks == 0) {
0100         emit parsingFinished();
0101     }
0102 }
0103 
0104 GeoDataDocument *ParsingRunnerManager::openFile( const QString &fileName, DocumentRole role, int timeout )
0105 {
0106     d->m_fileResult = nullptr;
0107     QEventLoop localEventLoop;
0108     QTimer watchdog;
0109     watchdog.setSingleShot(true);
0110     connect( &watchdog, SIGNAL(timeout()),
0111              &localEventLoop, SLOT(quit()));
0112     connect(this, SIGNAL(parsingFinished()),
0113             &localEventLoop, SLOT(quit()), Qt::QueuedConnection );
0114 
0115     watchdog.start( timeout );
0116     parseFile( fileName, role);
0117     localEventLoop.exec();
0118     return d->m_fileResult;
0119 }
0120 
0121 void ParsingRunnerManager::Private::addParsingResult(GeoDataDocument *document, const QString &error)
0122 {
0123     if ( document || !error.isEmpty() ) {
0124         if (document) {
0125             m_fileResult = document;
0126         }
0127         emit q->parsingFinished( document, error );
0128     }
0129 }
0130 
0131 }
0132 
0133 #include "moc_ParsingRunnerManager.cpp"