Branch data Line data Source code
1 : : /***************************************************************************
2 : : qgsproviderregistry.cpp - Singleton class for
3 : : registering data providers.
4 : : -------------------
5 : : begin : Sat Jan 10 2004
6 : : copyright : (C) 2004 by Gary E.Sherman
7 : : email : sherman at mrcc.com
8 : : ***************************************************************************/
9 : :
10 : : /***************************************************************************
11 : : * *
12 : : * This program is free software; you can redistribute it and/or modify *
13 : : * it under the terms of the GNU General Public License as published by *
14 : : * the Free Software Foundation; either version 2 of the License, or *
15 : : * (at your option) any later version. *
16 : : * *
17 : : ***************************************************************************/
18 : :
19 : : #include "qgsproviderregistry.h"
20 : :
21 : : #include <QString>
22 : : #include <QDir>
23 : : #include <QLibrary>
24 : :
25 : : #include "qgis.h"
26 : : #include "qgsdataprovider.h"
27 : : #include "qgsdataitemprovider.h"
28 : : #include "qgslogger.h"
29 : : #include "qgsmessageoutput.h"
30 : : #include "qgsmessagelog.h"
31 : : #include "qgsprovidermetadata.h"
32 : : #include "qgsvectorlayer.h"
33 : : #include "qgsvectortileprovidermetadata.h"
34 : : #include "qgsproject.h"
35 : : #include "providers/memory/qgsmemoryprovider.h"
36 : : #include "providers/gdal/qgsgdalprovider.h"
37 : : #include "providers/ogr/qgsogrprovider.h"
38 : : #include "providers/meshmemory/qgsmeshmemorydataprovider.h"
39 : :
40 : : #ifdef HAVE_EPT
41 : : #include "providers/ept/qgseptprovider.h"
42 : : #endif
43 : :
44 : : #include "qgsruntimeprofiler.h"
45 : : #include "qgsfileutils.h"
46 : :
47 : : #ifdef HAVE_STATIC_PROVIDERS
48 : : #include "qgswmsprovider.h"
49 : : #include "qgspostgresprovider.h"
50 : : #endif
51 : :
52 : : static QgsProviderRegistry *sInstance = nullptr;
53 : :
54 : 173 : QgsProviderRegistry *QgsProviderRegistry::instance( const QString &pluginPath )
55 : : {
56 : 173 : if ( !sInstance )
57 : : {
58 : 3 : static QMutex sMutex;
59 : 3 : QMutexLocker locker( &sMutex );
60 : 3 : if ( !sInstance )
61 : : {
62 : 3 : sInstance = new QgsProviderRegistry( pluginPath );
63 : 3 : }
64 : 3 : }
65 : 173 : return sInstance;
66 : 0 : } // QgsProviderRegistry::instance
67 : :
68 : :
69 : : /**
70 : : * Convenience function for finding any existing data providers that match "providerKey"
71 : :
72 : : Necessary because [] map operator will create a QgsProviderMetadata
73 : : instance. Also you cannot use the map [] operator in const members for that
74 : : very reason. So there needs to be a convenient way to find a data provider
75 : : without accidentally adding a null meta data item to the metadata map.
76 : : */
77 : : static
78 : 164 : QgsProviderMetadata *findMetadata_( const QgsProviderRegistry::Providers &metaData,
79 : : const QString &providerKey )
80 : : {
81 : : // first do case-sensitive match
82 : : QgsProviderRegistry::Providers::const_iterator i =
83 : 164 : metaData.find( providerKey );
84 : :
85 : 164 : if ( i != metaData.end() )
86 : : {
87 : 164 : return i->second;
88 : : }
89 : :
90 : : // fallback to case-insensitive match
91 : 0 : for ( auto it = metaData.begin(); it != metaData.end(); ++it )
92 : : {
93 : 0 : if ( providerKey.compare( it->first, Qt::CaseInsensitive ) == 0 )
94 : 0 : return it->second;
95 : 0 : }
96 : :
97 : 0 : return nullptr;
98 : 164 : }
99 : :
100 : 3 : QgsProviderRegistry::QgsProviderRegistry( const QString &pluginPath )
101 : : {
102 : : // At startup, examine the libs in the qgis/lib dir and store those that
103 : : // are a provider shared lib
104 : : // check all libs in the current plugin directory and get name and descriptions
105 : : //TODO figure out how to register and identify data source plugin for a specific
106 : : //TODO layer type
107 : : #if 0
108 : : char **argv = qApp->argv();
109 : : QString appDir = argv[0];
110 : : int bin = appDir.findRev( "/bin", -1, false );
111 : : QString baseDir = appDir.left( bin );
112 : : QString mLibraryDirectory = baseDir + "/lib";
113 : : #endif
114 : :
115 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Initialize data providers" ) );
116 : 3 : mLibraryDirectory.setPath( pluginPath );
117 : 3 : init();
118 : 3 : }
119 : :
120 : : ///@cond PRIVATE
121 : 9 : class PdalUnusableUriHandlerInterface : public QgsProviderRegistry::UnusableUriHandlerInterface
122 : : {
123 : : public:
124 : 0 : bool matchesUri( const QString &uri ) const override
125 : : {
126 : 0 : const QFileInfo fi( uri );
127 : 0 : if ( fi.suffix().compare( QLatin1String( "las" ), Qt::CaseInsensitive ) == 0 || fi.suffix().compare( QLatin1String( "laz" ), Qt::CaseInsensitive ) == 0 )
128 : 0 : return true;
129 : :
130 : 0 : return false;
131 : 0 : }
132 : :
133 : 0 : QgsProviderRegistry::UnusableUriDetails details( const QString &uri ) const override
134 : : {
135 : 0 : QgsProviderRegistry::UnusableUriDetails res = QgsProviderRegistry::UnusableUriDetails( uri,
136 : 0 : QObject::tr( "LAS and LAZ files cannot be opened by this QGIS install." ),
137 : 0 : QList<QgsMapLayerType>() << QgsMapLayerType::PointCloudLayer );
138 : :
139 : : #ifdef Q_OS_WIN
140 : : res.detailedWarning = QObject::tr( "The installer used to install this version of QGIS does "
141 : : "not include the PDAL library required for opening LAS and LAZ point clouds. Please "
142 : : "obtain one of the alternative installers from https://qgis.org which has point "
143 : : "cloud support enabled." );
144 : : #else
145 : 0 : res.detailedWarning = QObject::tr( "This QGIS build does not include the PDAL library dependency required for opening LAS or LAZ point clouds." );
146 : : #endif
147 : 0 : return res;
148 : 0 : }
149 : : };
150 : : ///@endcond
151 : :
152 : 3 : void QgsProviderRegistry::init()
153 : : {
154 : : // add static providers
155 : : Q_NOWARN_DEPRECATED_PUSH
156 : : {
157 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Create memory layer provider" ) );
158 : 3 : mProviders[ QgsMemoryProvider::providerKey() ] = new QgsProviderMetadata( QgsMemoryProvider::providerKey(), QgsMemoryProvider::providerDescription(), &QgsMemoryProvider::createProvider );
159 : 3 : }
160 : : {
161 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Create mesh memory layer provider" ) );
162 : 3 : mProviders[ QgsMeshMemoryDataProvider::providerKey() ] = new QgsProviderMetadata( QgsMeshMemoryDataProvider::providerKey(), QgsMeshMemoryDataProvider::providerDescription(), &QgsMeshMemoryDataProvider::createProvider );
163 : 3 : }
164 : : Q_NOWARN_DEPRECATED_POP
165 : : {
166 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Create GDAL provider" ) );
167 : 3 : mProviders[ QgsGdalProvider::providerKey() ] = new QgsGdalProviderMetadata();
168 : 3 : }
169 : : {
170 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Create OGR provider" ) );
171 : 3 : mProviders[ QgsOgrProvider::providerKey() ] = new QgsOgrProviderMetadata();
172 : 3 : }
173 : : {
174 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Create vector tile provider" ) );
175 : 3 : QgsProviderMetadata *vt = new QgsVectorTileProviderMetadata();
176 : 3 : mProviders[ vt->key() ] = vt;
177 : 3 : }
178 : : #ifdef HAVE_EPT
179 : : {
180 : 3 : QgsScopedRuntimeProfile profile( QObject::tr( "Create EPT point cloud provider" ) );
181 : 3 : QgsProviderMetadata *pc = new QgsEptProviderMetadata();
182 : 3 : mProviders[ pc->key() ] = pc;
183 : 3 : }
184 : : #endif
185 : :
186 : 3 : registerUnusableUriHandler( new PdalUnusableUriHandlerInterface() );
187 : :
188 : : #ifdef HAVE_STATIC_PROVIDERS
189 : : mProviders[ QgsWmsProvider::providerKey() ] = new QgsWmsProviderMetadata();
190 : : mProviders[ QgsPostgresProvider::providerKey() ] = new QgsPostgresProviderMetadata();
191 : : #endif
192 : :
193 : : // add dynamic providers
194 : : #ifdef HAVE_STATIC_PROVIDERS
195 : : QgsDebugMsg( QStringLiteral( "Forced only static providers" ) );
196 : : #else
197 : : typedef QgsProviderMetadata *factory_function( );
198 : :
199 : 3 : mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
200 : 3 : mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
201 : :
202 : : #if defined(Q_OS_WIN) || defined(__CYGWIN__)
203 : : mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
204 : : #elif defined(ANDROID)
205 : : mLibraryDirectory.setNameFilters( QStringList( "*provider*.so" ) );
206 : : #else
207 : 6 : mLibraryDirectory.setNameFilters( QStringList( QStringLiteral( "*.so" ) ) );
208 : : #endif
209 : :
210 : 3 : QgsDebugMsgLevel( QStringLiteral( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ), 2 );
211 : :
212 : 3 : if ( mLibraryDirectory.count() == 0 )
213 : : {
214 : 3 : QgsDebugMsg( QStringLiteral( "No dynamic QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() ) );
215 : 3 : }
216 : :
217 : : // provider file regex pattern, only files matching the pattern are loaded if the variable is defined
218 : 3 : QString filePattern = getenv( "QGIS_PROVIDER_FILE" );
219 : 3 : QRegExp fileRegexp;
220 : 3 : if ( !filePattern.isEmpty() )
221 : : {
222 : 0 : fileRegexp.setPattern( filePattern );
223 : 0 : }
224 : :
225 : : typedef std::vector<QgsProviderMetadata *> *multiple_factory_function();
226 : :
227 : 3 : const auto constEntryInfoList = mLibraryDirectory.entryInfoList();
228 : 3 : for ( const QFileInfo &fi : constEntryInfoList )
229 : : {
230 : 0 : if ( !fileRegexp.isEmpty() )
231 : : {
232 : 0 : if ( fileRegexp.indexIn( fi.fileName() ) == -1 )
233 : : {
234 : 0 : QgsDebugMsg( "provider " + fi.fileName() + " skipped because doesn't match pattern " + filePattern );
235 : 0 : continue;
236 : : }
237 : 0 : }
238 : :
239 : : // Always skip authentication methods
240 : 0 : if ( fi.fileName().contains( QStringLiteral( "authmethod" ), Qt::CaseSensitivity::CaseInsensitive ) )
241 : : {
242 : 0 : continue;
243 : : }
244 : :
245 : 0 : QgsScopedRuntimeProfile profile( QObject::tr( "Load %1" ).arg( fi.fileName() ) );
246 : 0 : QLibrary myLib( fi.filePath() );
247 : 0 : if ( !myLib.load() )
248 : : {
249 : 0 : QgsDebugMsg( QStringLiteral( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName(), myLib.errorString() ) );
250 : 0 : continue;
251 : : }
252 : :
253 : 0 : bool libraryLoaded { false };
254 : 0 : QFunctionPointer func = myLib.resolve( QStringLiteral( "providerMetadataFactory" ).toLatin1().data() );
255 : 0 : factory_function *function = reinterpret_cast< factory_function * >( cast_to_fptr( func ) );
256 : 0 : if ( function )
257 : : {
258 : 0 : QgsProviderMetadata *meta = function();
259 : 0 : if ( meta )
260 : : {
261 : 0 : if ( findMetadata_( mProviders, meta->key() ) )
262 : : {
263 : 0 : QgsDebugMsg( QStringLiteral( "Checking %1: ...invalid (key %2 already registered)" ).arg( myLib.fileName() ).arg( meta->key() ) );
264 : 0 : delete meta;
265 : 0 : continue;
266 : : }
267 : : // add this provider to the provider map
268 : 0 : mProviders[meta->key()] = meta;
269 : 0 : libraryLoaded = true;
270 : 0 : }
271 : 0 : }
272 : : else
273 : : {
274 : 0 : QFunctionPointer multi_func = myLib.resolve( QStringLiteral( "multipleProviderMetadataFactory" ).toLatin1().data() );
275 : 0 : multiple_factory_function *multi_function = reinterpret_cast< multiple_factory_function * >( cast_to_fptr( multi_func ) );
276 : 0 : if ( multi_function )
277 : : {
278 : 0 : std::vector<QgsProviderMetadata *> *metadatas = multi_function();
279 : 0 : for ( const auto meta : *metadatas )
280 : : {
281 : 0 : if ( findMetadata_( mProviders, meta->key() ) )
282 : : {
283 : 0 : QgsDebugMsg( QStringLiteral( "Checking %1: ...invalid (key %2 already registered)" ).arg( myLib.fileName() ).arg( meta->key() ) );
284 : 0 : delete meta;
285 : 0 : continue;
286 : : }
287 : : // add this provider to the provider map
288 : 0 : mProviders[meta->key()] = meta;
289 : 0 : libraryLoaded = true;
290 : : }
291 : 0 : delete metadatas;
292 : 0 : }
293 : : }
294 : :
295 : 0 : if ( ! libraryLoaded )
296 : : {
297 : 0 : QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...invalid (no providerMetadataFactory method)" ).arg( myLib.fileName() ), 2 );
298 : 0 : }
299 : 0 : }
300 : :
301 : : #endif
302 : 3 : QgsDebugMsg( QStringLiteral( "Loaded %1 providers (%2) " ).arg( mProviders.size() ).arg( providerList().join( ';' ) ) );
303 : :
304 : 3 : QStringList pointCloudWildcards;
305 : 3 : QStringList pointCloudFilters;
306 : :
307 : : // now initialize all providers
308 : 21 : for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
309 : : {
310 : 18 : const QString &key = it->first;
311 : :
312 : 18 : QgsScopedRuntimeProfile profile( QObject::tr( "Initialize %1" ).arg( key ) );
313 : :
314 : 18 : QgsProviderMetadata *meta = it->second;
315 : :
316 : : // now get vector file filters, if any
317 : 18 : QString fileVectorFilters = meta->filters( QgsProviderMetadata::FilterType::FilterVector );
318 : 18 : if ( !fileVectorFilters.isEmpty() )
319 : : {
320 : 3 : mVectorFileFilters += fileVectorFilters;
321 : 3 : QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file filters)" ).arg( key ).arg( fileVectorFilters.split( ";;" ).count() ), 2 );
322 : 3 : }
323 : :
324 : : // now get raster file filters, if any
325 : 18 : QString fileRasterFilters = meta->filters( QgsProviderMetadata::FilterType::FilterRaster );
326 : 18 : if ( !fileRasterFilters.isEmpty() )
327 : : {
328 : 3 : QgsDebugMsgLevel( "raster filters: " + fileRasterFilters, 2 );
329 : 3 : mRasterFileFilters += fileRasterFilters;
330 : 3 : QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file filters)" ).arg( key ).arg( fileRasterFilters.split( ";;" ).count() ), 2 );
331 : 3 : }
332 : :
333 : : // now get mesh file filters, if any
334 : 18 : QString fileMeshFilters = meta->filters( QgsProviderMetadata::FilterType::FilterMesh );
335 : 18 : if ( !fileMeshFilters.isEmpty() )
336 : : {
337 : 0 : mMeshFileFilters += fileMeshFilters;
338 : 0 : QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file mesh filters)" ).arg( key ).arg( mMeshFileFilters.split( ";;" ).count() ), 2 );
339 : :
340 : 0 : }
341 : :
342 : 18 : QString fileMeshDatasetFilters = meta->filters( QgsProviderMetadata::FilterType::FilterMeshDataset );
343 : 18 : if ( !fileMeshDatasetFilters.isEmpty() )
344 : : {
345 : 0 : mMeshDatasetFileFilters += fileMeshDatasetFilters;
346 : 0 : QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file dataset filters)" ).arg( key ).arg( mMeshDatasetFileFilters.split( ";;" ).count() ), 2 );
347 : 0 : }
348 : :
349 : : // now get point cloud file filters, if any
350 : 18 : const QString filePointCloudFilters = meta->filters( QgsProviderMetadata::FilterType::FilterPointCloud );
351 : 18 : if ( !filePointCloudFilters.isEmpty() )
352 : : {
353 : 3 : QgsDebugMsgLevel( "point cloud filters: " + filePointCloudFilters, 2 );
354 : :
355 : : #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
356 : : const QStringList filters = filePointCloudFilters.split( QStringLiteral( ";;" ), QString::SkipEmptyParts );
357 : : #else
358 : 6 : const QStringList filters = filePointCloudFilters.split( QStringLiteral( ";;" ), Qt::SkipEmptyParts );
359 : : #endif
360 : 6 : for ( const QString &filter : filters )
361 : : {
362 : 3 : pointCloudFilters.append( filter );
363 : 3 : pointCloudWildcards.append( QgsFileUtils::wildcardsFromFilter( filter ).split( ' ' ) );
364 : : }
365 : 3 : }
366 : :
367 : : // call initProvider() - allows provider to register its services to QGIS
368 : 18 : meta->initProvider();
369 : 18 : }
370 : :
371 : 3 : if ( !pointCloudFilters.empty() )
372 : : {
373 : 6 : pointCloudFilters.insert( 0, QObject::tr( "All Supported Files" ) + QStringLiteral( " (%1)" ).arg( pointCloudWildcards.join( ' ' ) ) );
374 : 6 : pointCloudFilters.insert( 1, QObject::tr( "All Files" ) + QStringLiteral( " (*.*)" ) );
375 : 3 : mPointCloudFileFilters = pointCloudFilters.join( QLatin1String( ";;" ) );
376 : 3 : }
377 : :
378 : : // load database drivers (only OGR)
379 : 3 : mDatabaseDrivers = QgsOgrProviderUtils::databaseDrivers();
380 : :
381 : : // load directory drivers (only OGR)
382 : 3 : mDirectoryDrivers = QgsOgrProviderUtils::directoryDrivers();
383 : :
384 : : // load protocol drivers (only OGR)
385 : 3 : mProtocolDrivers = QgsOgrProviderUtils::protocolDrivers();
386 : 3 : } // QgsProviderRegistry ctor
387 : :
388 : :
389 : : // typedef for the unload dataprovider function
390 : : typedef void cleanupProviderFunction_t();
391 : :
392 : 3 : void QgsProviderRegistry::clean()
393 : : {
394 : : // avoid recreating a new project just to clean it
395 : 3 : if ( QgsProject::sProject )
396 : 0 : QgsProject::instance()->removeAllMapLayers();
397 : :
398 : 3 : Providers::const_iterator it = mProviders.begin();
399 : :
400 : 21 : while ( it != mProviders.end() )
401 : : {
402 : 18 : QgsDebugMsgLevel( QStringLiteral( "cleanup:%1" ).arg( it->first ), 5 );
403 : 18 : it->second->cleanupProvider();
404 : 18 : delete it->second;
405 : 18 : ++it;
406 : : }
407 : 3 : mProviders.clear();
408 : 3 : }
409 : :
410 : 3 : bool QgsProviderRegistry::exists()
411 : : {
412 : 3 : return static_cast< bool >( sInstance );
413 : : }
414 : :
415 : 3 : QgsProviderRegistry::~QgsProviderRegistry()
416 : : {
417 : 3 : qDeleteAll( mUnusableUriHandlers );
418 : :
419 : 3 : clean();
420 : 3 : if ( sInstance == this )
421 : 3 : sInstance = nullptr;
422 : 3 : }
423 : :
424 : 0 : QString QgsProviderRegistry::library( QString const &providerKey ) const
425 : : {
426 : 0 : QgsProviderMetadata *md = findMetadata_( mProviders, providerKey );
427 : :
428 : 0 : if ( md )
429 : : {
430 : : Q_NOWARN_DEPRECATED_PUSH
431 : 0 : return md->library();
432 : : Q_NOWARN_DEPRECATED_POP
433 : : }
434 : :
435 : 0 : return QString();
436 : 0 : }
437 : :
438 : 0 : QString QgsProviderRegistry::pluginList( bool asHTML ) const
439 : : {
440 : 0 : Providers::const_iterator it = mProviders.begin();
441 : :
442 : 0 : if ( mProviders.empty() )
443 : 0 : return QObject::tr( "No data provider plugins are available. No vector layers can be loaded" );
444 : :
445 : 0 : QString list;
446 : :
447 : 0 : if ( asHTML )
448 : 0 : list += QLatin1String( "<ol>" );
449 : :
450 : 0 : while ( it != mProviders.end() )
451 : : {
452 : 0 : if ( asHTML )
453 : 0 : list += QLatin1String( "<li>" );
454 : :
455 : 0 : list += it->second->description();
456 : :
457 : 0 : if ( asHTML )
458 : 0 : list += QLatin1String( "<br></li>" );
459 : : else
460 : 0 : list += '\n';
461 : :
462 : 0 : ++it;
463 : : }
464 : :
465 : 0 : if ( asHTML )
466 : 0 : list += QLatin1String( "</ol>" );
467 : :
468 : 0 : return list;
469 : 0 : }
470 : :
471 : 0 : void QgsProviderRegistry::setLibraryDirectory( QDir const &path )
472 : : {
473 : 0 : mLibraryDirectory = path;
474 : 0 : clean();
475 : 0 : init();
476 : 0 : }
477 : :
478 : 0 : QDir QgsProviderRegistry::libraryDirectory() const
479 : : {
480 : 0 : return mLibraryDirectory;
481 : : }
482 : :
483 : :
484 : : /* Copied from QgsVectorLayer::setDataProvider
485 : : * TODO: Make it work in the generic environment
486 : : *
487 : : * TODO: Is this class really the best place to put a data provider loader?
488 : : * It seems more sensible to provide the code in one place rather than
489 : : * in qgsrasterlayer, qgsvectorlayer, serversourceselect, etc.
490 : : */
491 : 78 : QgsDataProvider *QgsProviderRegistry::createProvider( QString const &providerKey, QString const &dataSource,
492 : : const QgsDataProvider::ProviderOptions &options,
493 : : QgsDataProvider::ReadFlags flags )
494 : : {
495 : : // XXX should I check for and possibly delete any pre-existing providers?
496 : : // XXX How often will that scenario occur?
497 : :
498 : 78 : QgsProviderMetadata *metadata = findMetadata_( mProviders, providerKey );
499 : 78 : if ( !metadata )
500 : : {
501 : 0 : QgsMessageLog::logMessage( QObject::tr( "Invalid data provider %1" ).arg( providerKey ) );
502 : 0 : return nullptr;
503 : : }
504 : :
505 : 78 : return metadata->createProvider( dataSource, options, flags );
506 : 78 : }
507 : :
508 : 0 : int QgsProviderRegistry::providerCapabilities( const QString &providerKey ) const
509 : : {
510 : 0 : const QList< QgsDataItemProvider * > itemProviders = dataItemProviders( providerKey );
511 : 0 : int ret = QgsDataProvider::NoDataCapabilities;
512 : : //concat flags
513 : 0 : for ( const QgsDataItemProvider *itemProvider : itemProviders )
514 : : {
515 : 0 : ret = ret | itemProvider->capabilities();
516 : : }
517 : 0 : return ret;
518 : 0 : }
519 : :
520 : 64 : QVariantMap QgsProviderRegistry::decodeUri( const QString &providerKey, const QString &uri )
521 : : {
522 : 64 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
523 : 64 : if ( meta )
524 : 64 : return meta->decodeUri( uri );
525 : : else
526 : 0 : return QVariantMap();
527 : 64 : }
528 : :
529 : 0 : QString QgsProviderRegistry::encodeUri( const QString &providerKey, const QVariantMap &parts )
530 : : {
531 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
532 : 0 : if ( meta )
533 : 0 : return meta->encodeUri( parts );
534 : : else
535 : 0 : return QString();
536 : 0 : }
537 : :
538 : 0 : QgsVectorLayerExporter::ExportError QgsProviderRegistry::createEmptyLayer( const QString &providerKey,
539 : : const QString &uri,
540 : : const QgsFields &fields,
541 : : QgsWkbTypes::Type wkbType,
542 : : const QgsCoordinateReferenceSystem &srs,
543 : : bool overwrite, QMap<int, int> &oldToNewAttrIdxMap,
544 : : QString &errorMessage,
545 : : const QMap<QString, QVariant> *options )
546 : : {
547 : : QgsVectorLayerExporter::ExportError ret;
548 : :
549 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
550 : 0 : if ( meta )
551 : 0 : return meta->createEmptyLayer( uri, fields, wkbType, srs, overwrite, oldToNewAttrIdxMap, errorMessage, options );
552 : : else
553 : : {
554 : 0 : ret = QgsVectorLayerExporter::ErrInvalidProvider;
555 : 0 : errorMessage = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
556 : : }
557 : :
558 : 0 : return ret;
559 : 0 : }
560 : :
561 : 0 : QgsRasterDataProvider *QgsProviderRegistry::createRasterDataProvider( const QString &providerKey, const QString &uri, const QString &format,
562 : : int nBands, Qgis::DataType type, int width, int height,
563 : : double *geoTransform, const QgsCoordinateReferenceSystem &crs,
564 : : const QStringList &createOptions )
565 : : {
566 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
567 : 0 : if ( meta )
568 : 0 : return meta->createRasterDataProvider( uri, format, nBands, type, width, height, geoTransform, crs, createOptions );
569 : : else
570 : 0 : return nullptr;
571 : 0 : }
572 : :
573 : 0 : QList<QPair<QString, QString> > QgsProviderRegistry::pyramidResamplingMethods( const QString &providerKey )
574 : : {
575 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
576 : 0 : if ( meta )
577 : 0 : return meta->pyramidResamplingMethods();
578 : : else
579 : 0 : return QList<QPair<QString, QString> >();
580 : 0 : }
581 : :
582 : 18 : QList<QgsDataItemProvider *> QgsProviderRegistry::dataItemProviders( const QString &providerKey ) const
583 : : {
584 : 18 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
585 : 18 : if ( meta )
586 : 18 : return meta->dataItemProviders();
587 : : else
588 : 0 : return QList<QgsDataItemProvider *>();
589 : 18 : }
590 : :
591 : 0 : int QgsProviderRegistry::listStyles( const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause )
592 : : {
593 : 0 : int res = -1;
594 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
595 : 0 : if ( meta )
596 : : {
597 : 0 : res = meta->listStyles( uri, ids, names, descriptions, errCause );
598 : 0 : }
599 : : else
600 : : {
601 : 0 : errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
602 : : }
603 : 0 : return res;
604 : 0 : }
605 : :
606 : 0 : QString QgsProviderRegistry::getStyleById( const QString &providerKey, const QString &uri, QString styleId, QString &errCause )
607 : : {
608 : 0 : QString ret;
609 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
610 : 0 : if ( meta )
611 : : {
612 : 0 : ret = meta->getStyleById( uri, styleId, errCause );
613 : 0 : }
614 : : else
615 : : {
616 : 0 : errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
617 : : }
618 : 0 : return ret;
619 : 0 : }
620 : :
621 : 0 : bool QgsProviderRegistry::deleteStyleById( const QString &providerKey, const QString &uri, QString styleId, QString &errCause )
622 : : {
623 : 0 : bool ret( false );
624 : :
625 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
626 : 0 : if ( meta )
627 : 0 : return meta->deleteStyleById( uri, styleId, errCause );
628 : : else
629 : : {
630 : 0 : errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
631 : : }
632 : 0 : return ret;
633 : 0 : }
634 : :
635 : 0 : bool QgsProviderRegistry::saveStyle( const QString &providerKey, const QString &uri, const QString &qmlStyle,
636 : : const QString &sldStyle, const QString &styleName, const QString &styleDescription,
637 : : const QString &uiFileContent, bool useAsDefault, QString &errCause )
638 : : {
639 : 0 : bool ret( false );
640 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
641 : 0 : if ( meta )
642 : 0 : ret = meta->saveStyle( uri, qmlStyle, sldStyle, styleName, styleDescription,
643 : 0 : uiFileContent, useAsDefault, errCause );
644 : : else
645 : : {
646 : 0 : errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
647 : : }
648 : 0 : return ret;
649 : 0 : }
650 : :
651 : 1 : QString QgsProviderRegistry::loadStyle( const QString &providerKey, const QString &uri, QString &errCause )
652 : : {
653 : 1 : QString ret;
654 : 1 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
655 : 1 : if ( meta )
656 : 1 : ret = meta->loadStyle( uri, errCause );
657 : : else
658 : : {
659 : 0 : errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
660 : : }
661 : 1 : return ret;
662 : 1 : }
663 : :
664 : 0 : bool QgsProviderRegistry::createDb( const QString &providerKey, const QString &dbPath, QString &errCause )
665 : : {
666 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
667 : 0 : if ( meta )
668 : 0 : return meta->createDb( dbPath, errCause );
669 : : else
670 : : {
671 : 0 : errCause = QStringLiteral( "Resolving createDb(...) failed" );
672 : 0 : return false;
673 : : }
674 : 0 : }
675 : :
676 : 0 : QgsTransaction *QgsProviderRegistry::createTransaction( const QString &providerKey, const QString &connString )
677 : : {
678 : 0 : QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
679 : 0 : if ( meta )
680 : 0 : return meta->createTransaction( connString );
681 : : else
682 : 0 : return nullptr;
683 : 0 : }
684 : :
685 : 0 : QWidget *QgsProviderRegistry::createSelectionWidget( const QString &providerKey,
686 : : QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
687 : : {
688 : 0 : Q_UNUSED( providerKey );
689 : : Q_UNUSED( parent );
690 : : Q_UNUSED( fl );
691 : : Q_UNUSED( widgetMode );
692 : 0 : QgsDebugMsg( "deprecated call - use QgsGui::sourceSelectProviderRegistry()->createDataSourceWidget() instead" );
693 : 0 : return nullptr;
694 : : }
695 : :
696 : 0 : QFunctionPointer QgsProviderRegistry::function( QString const &providerKey,
697 : : QString const &functionName )
698 : : {
699 : : Q_NOWARN_DEPRECATED_PUSH
700 : 0 : QString lib = library( providerKey );
701 : : Q_NOWARN_DEPRECATED_POP
702 : 0 : if ( lib.isEmpty() )
703 : 0 : return nullptr;
704 : :
705 : 0 : QLibrary myLib( lib );
706 : :
707 : 0 : QgsDebugMsg( "Library name is " + myLib.fileName() );
708 : :
709 : 0 : if ( myLib.load() )
710 : : {
711 : 0 : return myLib.resolve( functionName.toLatin1().data() );
712 : : }
713 : : else
714 : : {
715 : 0 : QgsDebugMsg( "Cannot load library: " + myLib.errorString() );
716 : 0 : return nullptr;
717 : : }
718 : 0 : }
719 : :
720 : 0 : QLibrary *QgsProviderRegistry::createProviderLibrary( QString const &providerKey ) const
721 : : {
722 : : Q_NOWARN_DEPRECATED_PUSH
723 : 0 : QString lib = library( providerKey );
724 : : Q_NOWARN_DEPRECATED_POP
725 : 0 : if ( lib.isEmpty() )
726 : 0 : return nullptr;
727 : :
728 : 0 : std::unique_ptr< QLibrary > myLib( new QLibrary( lib ) );
729 : :
730 : 0 : QgsDebugMsg( "Library name is " + myLib->fileName() );
731 : :
732 : 0 : if ( myLib->load() )
733 : 0 : return myLib.release();
734 : :
735 : 0 : QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
736 : :
737 : 0 : return nullptr;
738 : 0 : }
739 : :
740 : 0 : void QgsProviderRegistry::registerGuis( QWidget * )
741 : : {
742 : 0 : QgsDebugMsg( "deprecated - use QgsGui::providerGuiRegistry() instead." );
743 : 0 : }
744 : :
745 : 0 : bool QgsProviderRegistry::registerProvider( QgsProviderMetadata *providerMetadata )
746 : : {
747 : 0 : if ( providerMetadata )
748 : : {
749 : 0 : if ( mProviders.find( providerMetadata->key() ) == mProviders.end() )
750 : : {
751 : 0 : mProviders[ providerMetadata->key() ] = providerMetadata;
752 : 0 : return true;
753 : : }
754 : : else
755 : : {
756 : 0 : QgsDebugMsgLevel( QStringLiteral( "Cannot register provider metadata: a provider with the same key (%1) was already registered!" ).arg( providerMetadata->key() ), 2 );
757 : : }
758 : 0 : }
759 : : else
760 : : {
761 : 0 : QgsDebugMsgLevel( QStringLiteral( "Trying to register a null metadata provider!" ), 2 );
762 : : }
763 : 0 : return false;
764 : 0 : }
765 : :
766 : 0 : QString QgsProviderRegistry::fileVectorFilters() const
767 : : {
768 : 0 : return mVectorFileFilters;
769 : : }
770 : :
771 : 0 : QString QgsProviderRegistry::fileRasterFilters() const
772 : : {
773 : 0 : return mRasterFileFilters;
774 : : }
775 : :
776 : 0 : QString QgsProviderRegistry::fileMeshFilters() const
777 : : {
778 : 0 : return mMeshFileFilters;
779 : : }
780 : :
781 : 0 : QString QgsProviderRegistry::fileMeshDatasetFilters() const
782 : : {
783 : 0 : return mMeshDatasetFileFilters;
784 : : }
785 : :
786 : 0 : QString QgsProviderRegistry::filePointCloudFilters() const
787 : : {
788 : 0 : return mPointCloudFileFilters;
789 : : }
790 : :
791 : 0 : QString QgsProviderRegistry::databaseDrivers() const
792 : : {
793 : 0 : return mDatabaseDrivers;
794 : : }
795 : :
796 : 0 : QString QgsProviderRegistry::directoryDrivers() const
797 : : {
798 : 0 : return mDirectoryDrivers;
799 : : }
800 : :
801 : 0 : QString QgsProviderRegistry::protocolDrivers() const
802 : : {
803 : 0 : return mProtocolDrivers;
804 : : }
805 : :
806 : 3 : QStringList QgsProviderRegistry::providerList() const
807 : : {
808 : 3 : QStringList lst;
809 : 21 : for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
810 : : {
811 : 18 : lst.append( it->first );
812 : 18 : }
813 : 3 : return lst;
814 : 3 : }
815 : :
816 : 3 : QgsProviderMetadata *QgsProviderRegistry::providerMetadata( const QString &providerKey ) const
817 : : {
818 : 3 : return findMetadata_( mProviders, providerKey );
819 : : }
820 : :
821 : 0 : QList<QgsProviderRegistry::ProviderCandidateDetails> QgsProviderRegistry::preferredProvidersForUri( const QString &uri ) const
822 : : {
823 : 0 : QList< QgsProviderRegistry::ProviderCandidateDetails > res;
824 : 0 : int maxPriority = 0;
825 : 0 : for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
826 : : {
827 : 0 : if ( !( it->second->capabilities() & QgsProviderMetadata::PriorityForUri ) )
828 : 0 : continue;
829 : :
830 : 0 : const int thisProviderPriority = it->second->priorityForUri( uri );
831 : 0 : if ( thisProviderPriority == 0 )
832 : 0 : continue;
833 : :
834 : 0 : if ( thisProviderPriority > maxPriority )
835 : : {
836 : 0 : res.clear();
837 : 0 : maxPriority = thisProviderPriority;
838 : 0 : }
839 : 0 : if ( thisProviderPriority == maxPriority )
840 : : {
841 : 0 : res.append( ProviderCandidateDetails( it->second, it->second->validLayerTypesForUri( uri ) ) );
842 : 0 : }
843 : 0 : }
844 : 0 : return res;
845 : 0 : }
846 : :
847 : 3 : bool QgsProviderRegistry::registerUnusableUriHandler( QgsProviderRegistry::UnusableUriHandlerInterface *handler )
848 : : {
849 : 3 : mUnusableUriHandlers << handler;
850 : 3 : return true;
851 : : }
852 : :
853 : 0 : bool QgsProviderRegistry::handleUnusableUri( const QString &uri, UnusableUriDetails &details ) const
854 : : {
855 : 0 : for ( const QgsProviderRegistry::UnusableUriHandlerInterface *handler : mUnusableUriHandlers )
856 : : {
857 : 0 : if ( handler->matchesUri( uri ) )
858 : : {
859 : 0 : details = handler->details( uri );
860 : 0 : return true;
861 : : }
862 : : }
863 : 0 : return false;
864 : 0 : }
865 : :
866 : 0 : bool QgsProviderRegistry::shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const
867 : : {
868 : 0 : const QList< ProviderCandidateDetails > providers = preferredProvidersForUri( uri );
869 : 0 : if ( providers.empty() )
870 : 0 : return false;
871 : :
872 : 0 : for ( const ProviderCandidateDetails &provider : providers )
873 : : {
874 : 0 : if ( provider.metadata()->key() == providerKey )
875 : 0 : return false;
876 : : }
877 : 0 : return true;
878 : 0 : }
879 : :
880 : 0 : bool QgsProviderRegistry::uriIsBlocklisted( const QString &uri ) const
881 : : {
882 : 0 : for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
883 : : {
884 : 0 : if ( it->second->uriIsBlocklisted( uri ) )
885 : 0 : return true;
886 : 0 : }
887 : 0 : return false;
888 : 0 : }
|