QGIS API Documentation 3.30.0-'s-Hertogenbosch (f186b8efe0)
qgsproviderregistry.cpp
Go to the documentation of this file.
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 "qgis.h"
22#include "qgsdataprovider.h"
23#include "qgsdataitemprovider.h"
24#include "qgslogger.h"
25#include "qgsmessagelog.h"
26#include "qgsprovidermetadata.h"
28#include "qgsproject.h"
31#include "providers/gdal/qgsgdalprovider.h"
32#include "providers/ogr/qgsogrprovidermetadata.h"
33#include "providers/ogr/qgsogrprovider.h"
34#include "providers/meshmemory/qgsmeshmemorydataprovider.h"
35
36#ifdef HAVE_EPT
37#include "providers/ept/qgseptprovider.h"
38#endif
39
40#ifdef HAVE_COPC
41#include "providers/copc/qgscopcprovider.h"
42#endif
43
44#include "qgsruntimeprofiler.h"
45#include "qgsfileutils.h"
46
47#ifdef HAVE_STATIC_PROVIDERS
48#include "qgswmsprovider.h"
49#include "qgswcsprovider.h"
50#include "qgsdelimitedtextprovider.h"
51#include "qgsafsprovider.h"
52#include "qgsamsprovider.h"
53#ifdef HAVE_SPATIALITE
54#include "qgsspatialiteprovider.h"
55#include "qgswfsprovider.h"
56#include "qgswfsprovidermetadata.h"
57#include "qgsoapifprovider.h"
58#include "qgsvirtuallayerprovider.h"
59#endif
60#ifdef HAVE_POSTGRESQL
61#include "qgspostgresprovider.h"
62#endif
63#endif
64
65#include <QString>
66#include <QDir>
67#include <QLibrary>
68#include <QRegularExpression>
69
70static QgsProviderRegistry *sInstance = nullptr;
71
73{
74 if ( !sInstance )
75 {
76 static QMutex sMutex;
77 const QMutexLocker locker( &sMutex );
78 if ( !sInstance )
79 {
80 sInstance = new QgsProviderRegistry( pluginPath );
81 }
82 }
83 return sInstance;
84} // QgsProviderRegistry::instance
85
86
95static
96QgsProviderMetadata *findMetadata_( const QgsProviderRegistry::Providers &metaData,
97 const QString &providerKey )
98{
99 // first do case-sensitive match
100 const QgsProviderRegistry::Providers::const_iterator i =
101 metaData.find( providerKey );
102
103 if ( i != metaData.end() )
104 {
105 return i->second;
106 }
107
108 // fallback to case-insensitive match
109 for ( auto it = metaData.begin(); it != metaData.end(); ++it )
110 {
111 if ( providerKey.compare( it->first, Qt::CaseInsensitive ) == 0 )
112 return it->second;
113 }
114
115 return nullptr;
116}
117
118QgsProviderRegistry::QgsProviderRegistry( const QString &pluginPath )
119{
120 // At startup, examine the libs in the qgis/lib dir and store those that
121 // are a provider shared lib
122 // check all libs in the current plugin directory and get name and descriptions
123 //TODO figure out how to register and identify data source plugin for a specific
124 //TODO layer type
125#if 0
126 char **argv = qApp->argv();
127 QString appDir = argv[0];
128 int bin = appDir.findRev( "/bin", -1, false );
129 QString baseDir = appDir.left( bin );
130 QString mLibraryDirectory = baseDir + "/lib";
131#endif
132
133 const QgsScopedRuntimeProfile profile( QObject::tr( "Initialize data providers" ) );
134 mLibraryDirectory.setPath( pluginPath );
135 init();
136}
137
139class PdalUnusableUriHandlerInterface : public QgsProviderRegistry::UnusableUriHandlerInterface
140{
141 public:
142 bool matchesUri( const QString &uri ) const override
143 {
144 const QFileInfo fi( uri );
145 if ( fi.suffix().compare( QLatin1String( "las" ), Qt::CaseInsensitive ) == 0 || fi.suffix().compare( QLatin1String( "laz" ), Qt::CaseInsensitive ) == 0 )
146 return true;
147
148 return false;
149 }
150
151 QgsProviderRegistry::UnusableUriDetails details( const QString &uri ) const override
152 {
154 QObject::tr( "LAS and LAZ files cannot be opened by this QGIS install." ),
155 QList<Qgis::LayerType>() << Qgis::LayerType::PointCloud );
156
157#ifdef Q_OS_WIN
158 res.detailedWarning = QObject::tr( "The installer used to install this version of QGIS does "
159 "not include the PDAL library required for opening LAS and LAZ point clouds. Please "
160 "obtain one of the alternative installers from https://qgis.org which has point "
161 "cloud support enabled." );
162#else
163 res.detailedWarning = QObject::tr( "This QGIS build does not include the PDAL library dependency required for opening LAS or LAZ point clouds." );
164#endif
165 return res;
166 }
167};
169
170void QgsProviderRegistry::init()
171{
172 // add static providers
173 {
174 const QgsScopedRuntimeProfile profile( QObject::tr( "Create memory layer provider" ) );
175 mProviders[ QgsMemoryProvider::providerKey() ] = new QgsMemoryProviderMetadata();
176 }
177 {
178 const QgsScopedRuntimeProfile profile( QObject::tr( "Create mesh memory layer provider" ) );
179 mProviders[ QgsMeshMemoryDataProvider::providerKey() ] = new QgsMeshMemoryProviderMetadata();
180 }
181 {
182 const QgsScopedRuntimeProfile profile( QObject::tr( "Create GDAL provider" ) );
183 mProviders[ QgsGdalProvider::providerKey() ] = new QgsGdalProviderMetadata();
184 }
185 {
186 const QgsScopedRuntimeProfile profile( QObject::tr( "Create OGR provider" ) );
187 mProviders[ QgsOgrProvider::providerKey() ] = new QgsOgrProviderMetadata();
188 }
189 {
190 const QgsScopedRuntimeProfile profile( QObject::tr( "Create vector tile provider" ) );
191 QgsProviderMetadata *vt = new QgsVectorTileProviderMetadata();
192 mProviders[ vt->key() ] = vt;
193 }
194#ifdef HAVE_EPT
195 {
196 const QgsScopedRuntimeProfile profile( QObject::tr( "Create EPT point cloud provider" ) );
197 QgsProviderMetadata *pc = new QgsEptProviderMetadata();
198 mProviders[ pc->key() ] = pc;
199 }
200#endif
201#ifdef HAVE_COPC
202 {
203 const QgsScopedRuntimeProfile profile( QObject::tr( "Create COPC point cloud provider" ) );
204 QgsProviderMetadata *pc = new QgsCopcProviderMetadata();
205 mProviders[ pc->key() ] = pc;
206 }
207#endif
208 registerUnusableUriHandler( new PdalUnusableUriHandlerInterface() );
209
210#ifdef HAVE_STATIC_PROVIDERS
211 mProviders[ QgsWmsProvider::providerKey() ] = new QgsWmsProviderMetadata();
212 mProviders[ QgsWcsProvider::providerKey() ] = new QgsWcsProviderMetadata();
213 mProviders[ QgsDelimitedTextProvider::providerKey() ] = new QgsDelimitedTextProviderMetadata();
214 mProviders[ QgsAfsProvider::providerKey() ] = new QgsAfsProviderMetadata();
215 mProviders[ QgsAmsProvider::providerKey() ] = new QgsAmsProviderMetadata();
216#ifdef HAVE_SPATIALITE
217 mProviders[ QgsSpatiaLiteProvider::providerKey() ] = new QgsSpatiaLiteProviderMetadata();
218 mProviders[ QgsWFSProvider::providerKey() ] = new QgsWfsProviderMetadata();
219 mProviders[ QgsOapifProvider::providerKey() ] = new QgsOapifProviderMetadata();
220 mProviders[ QgsVirtualLayerProvider::providerKey() ] = new QgsVirtualLayerProviderMetadata();
221#endif
222#ifdef HAVE_POSTGRESQL
223 mProviders[ QgsPostgresProvider::providerKey() ] = new QgsPostgresProviderMetadata();
224#endif
225#endif
226
227 // add dynamic providers
228#ifdef HAVE_STATIC_PROVIDERS
229 QgsDebugMsg( QStringLiteral( "Forced only static providers" ) );
230#else
231 typedef QgsProviderMetadata *factory_function( );
232
233 mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
234 mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
235
236#if defined(Q_OS_WIN) || defined(__CYGWIN__)
237 mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
238#elif defined(ANDROID)
239 mLibraryDirectory.setNameFilters( QStringList( "*provider_*.so" ) );
240#else
241 mLibraryDirectory.setNameFilters( QStringList( QStringLiteral( "*.so" ) ) );
242#endif
243
244 QgsDebugMsgLevel( QStringLiteral( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ), 2 );
245
246 if ( mLibraryDirectory.count() == 0 )
247 {
248 QgsDebugMsg( QStringLiteral( "No dynamic QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() ) );
249 }
250
251 // provider file regex pattern, only files matching the pattern are loaded if the variable is defined
252 const QString filePattern = getenv( "QGIS_PROVIDER_FILE" );
253 QRegularExpression fileRegexp;
254 if ( !filePattern.isEmpty() )
255 {
256 fileRegexp.setPattern( filePattern );
257 }
258
259 typedef std::vector<QgsProviderMetadata *> *multiple_factory_function();
260
261 const auto constEntryInfoList = mLibraryDirectory.entryInfoList();
262 for ( const QFileInfo &fi : constEntryInfoList )
263 {
264 if ( !filePattern.isEmpty() )
265 {
266 if ( fi.fileName().indexOf( fileRegexp ) == -1 )
267 {
268 QgsDebugMsg( "provider " + fi.fileName() + " skipped because doesn't match pattern " + filePattern );
269 continue;
270 }
271 }
272
273 // Always skip authentication methods
274 if ( fi.fileName().contains( QStringLiteral( "authmethod" ), Qt::CaseSensitivity::CaseInsensitive ) )
275 {
276 continue;
277 }
278
279 const QgsScopedRuntimeProfile profile( QObject::tr( "Load %1" ).arg( fi.fileName() ) );
280 QLibrary myLib( fi.filePath() );
281 if ( !myLib.load() )
282 {
283 QgsDebugMsg( QStringLiteral( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName(), myLib.errorString() ) );
284 continue;
285 }
286
287 bool libraryLoaded { false };
288 QFunctionPointer func = myLib.resolve( QStringLiteral( "providerMetadataFactory" ).toLatin1().data() );
289 factory_function *function = reinterpret_cast< factory_function * >( cast_to_fptr( func ) );
290 if ( function )
291 {
293 if ( meta )
294 {
295 if ( findMetadata_( mProviders, meta->key() ) )
296 {
297 QgsDebugMsg( QStringLiteral( "Checking %1: ...invalid (key %2 already registered)" ).arg( myLib.fileName() ).arg( meta->key() ) );
298 delete meta;
299 continue;
300 }
301 // add this provider to the provider map
302 mProviders[meta->key()] = meta;
303 libraryLoaded = true;
304 }
305 }
306 else
307 {
308 QFunctionPointer multi_func = myLib.resolve( QStringLiteral( "multipleProviderMetadataFactory" ).toLatin1().data() );
309 multiple_factory_function *multi_function = reinterpret_cast< multiple_factory_function * >( cast_to_fptr( multi_func ) );
310 if ( multi_function )
311 {
312 std::vector<QgsProviderMetadata *> *metadatas = multi_function();
313 for ( const auto meta : *metadatas )
314 {
315 if ( findMetadata_( mProviders, meta->key() ) )
316 {
317 QgsDebugMsg( QStringLiteral( "Checking %1: ...invalid (key %2 already registered)" ).arg( myLib.fileName() ).arg( meta->key() ) );
318 delete meta;
319 continue;
320 }
321 // add this provider to the provider map
322 mProviders[meta->key()] = meta;
323 libraryLoaded = true;
324 }
325 delete metadatas;
326 }
327 }
328
329 if ( ! libraryLoaded )
330 {
331 QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...invalid (no providerMetadataFactory method)" ).arg( myLib.fileName() ), 2 );
332 }
333 }
334
335#endif
336 QgsDebugMsg( QStringLiteral( "Loaded %1 providers (%2) " ).arg( mProviders.size() ).arg( providerList().join( ';' ) ) );
337
338 QStringList pointCloudWildcards;
339 QStringList pointCloudFilters;
340
341 // now initialize all providers
342 for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
343 {
344 const QString &key = it->first;
345
346 const QgsScopedRuntimeProfile profile( QObject::tr( "Initialize %1" ).arg( key ) );
347
348 QgsProviderMetadata *meta = it->second;
349
350 // now get vector file filters, if any
352 if ( !fileVectorFilters.isEmpty() )
353 {
354 mVectorFileFilters += fileVectorFilters;
355 QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file filters)" ).arg( key ).arg( fileVectorFilters.split( ";;" ).count() ), 2 );
356 }
357
358 // now get raster file filters, if any
360 if ( !fileRasterFilters.isEmpty() )
361 {
362 QgsDebugMsgLevel( "raster filters: " + fileRasterFilters, 2 );
363 mRasterFileFilters += fileRasterFilters;
364 QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file filters)" ).arg( key ).arg( fileRasterFilters.split( ";;" ).count() ), 2 );
365 }
366
367 // now get mesh file filters, if any
369 if ( !fileMeshFilters.isEmpty() )
370 {
371 mMeshFileFilters += fileMeshFilters;
372 QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file mesh filters)" ).arg( key ).arg( mMeshFileFilters.split( ";;" ).count() ), 2 );
373
374 }
375
377 if ( !fileMeshDatasetFilters.isEmpty() )
378 {
379 mMeshDatasetFileFilters += fileMeshDatasetFilters;
380 QgsDebugMsgLevel( QStringLiteral( "Checking %1: ...loaded OK (%2 file dataset filters)" ).arg( key ).arg( mMeshDatasetFileFilters.split( ";;" ).count() ), 2 );
381 }
382
383 // now get point cloud file filters, if any
385 if ( !filePointCloudFilters.isEmpty() )
386 {
387 QgsDebugMsgLevel( "point cloud filters: " + filePointCloudFilters, 2 );
388
389#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
390 const QStringList filters = filePointCloudFilters.split( QStringLiteral( ";;" ), QString::SkipEmptyParts );
391#else
392 const QStringList filters = filePointCloudFilters.split( QStringLiteral( ";;" ), Qt::SkipEmptyParts );
393#endif
394 for ( const QString &filter : filters )
395 {
396 pointCloudFilters.append( filter );
397 pointCloudWildcards.append( QgsFileUtils::wildcardsFromFilter( filter ).split( ' ' ) );
398 }
399 }
400
401 // call initProvider() - allows provider to register its services to QGIS
402 meta->initProvider();
403 }
404
405 if ( !pointCloudFilters.empty() )
406 {
407 pointCloudFilters.insert( 0, QObject::tr( "All Supported Files" ) + QStringLiteral( " (%1)" ).arg( pointCloudWildcards.join( ' ' ) ) );
408 pointCloudFilters.insert( 1, QObject::tr( "All Files" ) + QStringLiteral( " (*.*)" ) );
409 mPointCloudFileFilters = pointCloudFilters.join( QLatin1String( ";;" ) );
410 }
411
412 // load database drivers (only OGR)
413 mDatabaseDrivers = QgsOgrProviderUtils::databaseDrivers();
414
415 // load directory drivers (only OGR)
416 mDirectoryDrivers = QgsOgrProviderUtils::directoryDrivers();
417
418 // load protocol drivers (only OGR)
419 mProtocolDrivers = QgsOgrProviderUtils::protocolDrivers();
420} // QgsProviderRegistry ctor
421
422
423// typedef for the unload dataprovider function
425
426void QgsProviderRegistry::clean()
427{
428 // avoid recreating a new project just to clean it
429 if ( QgsProject::sProject )
431
432 Providers::const_iterator it = mProviders.begin();
433
434 while ( it != mProviders.end() )
435 {
436 QgsDebugMsgLevel( QStringLiteral( "cleanup:%1" ).arg( it->first ), 5 );
437 it->second->cleanupProvider();
438 delete it->second;
439 ++it;
440 }
441 mProviders.clear();
442}
443
444bool QgsProviderRegistry::exists()
445{
446 return static_cast< bool >( sInstance );
447}
448
450{
451 qDeleteAll( mUnusableUriHandlers );
452
453 clean();
454 if ( sInstance == this )
455 sInstance = nullptr;
456}
457
458QString QgsProviderRegistry::library( QString const &providerKey ) const
459{
460 QgsProviderMetadata *md = findMetadata_( mProviders, providerKey );
461
462 if ( md )
463 {
465 return md->library();
467 }
468
469 return QString();
470}
471
472QString QgsProviderRegistry::pluginList( bool asHTML ) const
473{
474 Providers::const_iterator it = mProviders.begin();
475
476 if ( mProviders.empty() )
477 return QObject::tr( "No data provider plugins are available. No vector layers can be loaded" );
478
479 QString list;
480
481 if ( asHTML )
482 list += QLatin1String( "<ol>" );
483
484 while ( it != mProviders.end() )
485 {
486 if ( asHTML )
487 list += QLatin1String( "<li>" );
488
489 list += it->second->description();
490
491 if ( asHTML )
492 list += QLatin1String( "<br></li>" );
493 else
494 list += '\n';
495
496 ++it;
497 }
498
499 if ( asHTML )
500 list += QLatin1String( "</ol>" );
501
502 return list;
503}
504
506{
507 mLibraryDirectory = path;
508 clean();
509 init();
510}
511
513{
514 return mLibraryDirectory;
515}
516
517
518/* Copied from QgsVectorLayer::setDataProvider
519 * TODO: Make it work in the generic environment
520 *
521 * TODO: Is this class really the best place to put a data provider loader?
522 * It seems more sensible to provide the code in one place rather than
523 * in qgsrasterlayer, qgsvectorlayer, serversourceselect, etc.
524 */
525QgsDataProvider *QgsProviderRegistry::createProvider( QString const &providerKey, QString const &dataSource,
527 QgsDataProvider::ReadFlags flags )
528{
529 // XXX should I check for and possibly delete any pre-existing providers?
530 // XXX How often will that scenario occur?
531
532 QgsProviderMetadata *metadata = findMetadata_( mProviders, providerKey );
533 if ( !metadata )
534 {
535 QgsMessageLog::logMessage( QObject::tr( "Invalid data provider %1" ).arg( providerKey ) );
536 return nullptr;
537 }
538
539 return metadata->createProvider( dataSource, options, flags );
540}
541
542int QgsProviderRegistry::providerCapabilities( const QString &providerKey ) const
543{
544 const QList< QgsDataItemProvider * > itemProviders = dataItemProviders( providerKey );
546 //concat flags
547 for ( const QgsDataItemProvider *itemProvider : itemProviders )
548 {
549 ret = ret | itemProvider->capabilities();
550 }
551 return ret;
552}
553
554QVariantMap QgsProviderRegistry::decodeUri( const QString &providerKey, const QString &uri )
555{
556 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
557 if ( meta )
558 return meta->decodeUri( uri );
559 else
560 return QVariantMap();
561}
562
563QString QgsProviderRegistry::encodeUri( const QString &providerKey, const QVariantMap &parts )
564{
565 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
566 if ( meta )
567 return meta->encodeUri( parts );
568 else
569 return QString();
570}
571
572QString QgsProviderRegistry::absoluteToRelativeUri( const QString &providerKey, const QString &uri, const QgsReadWriteContext &context ) const
573{
574 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
575 if ( meta )
576 return meta->absoluteToRelativeUri( uri, context );
577 else
578 return uri;
579}
580
581QString QgsProviderRegistry::relativeToAbsoluteUri( const QString &providerKey, const QString &uri, const QgsReadWriteContext &context ) const
582{
583 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
584 if ( meta )
585 return meta->relativeToAbsoluteUri( uri, context );
586 else
587 return uri;
588}
589
591 const QString &uri,
592 const QgsFields &fields,
593 Qgis::WkbType wkbType,
595 bool overwrite, QMap<int, int> &oldToNewAttrIdxMap,
596 QString &errorMessage,
597 const QMap<QString, QVariant> *options )
598{
599 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
600 if ( meta )
601 return meta->createEmptyLayer( uri, fields, wkbType, srs, overwrite, oldToNewAttrIdxMap, errorMessage, options );
602 else
603 {
604 errorMessage = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
605 return Qgis::VectorExportResult::ErrorInvalidProvider;
606 }
607}
608
609QgsRasterDataProvider *QgsProviderRegistry::createRasterDataProvider( const QString &providerKey, const QString &uri, const QString &format,
610 int nBands, Qgis::DataType type, int width, int height,
611 double *geoTransform, const QgsCoordinateReferenceSystem &crs,
612 const QStringList &createOptions )
613{
614 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
615 if ( meta )
616 return meta->createRasterDataProvider( uri, format, nBands, type, width, height, geoTransform, crs, createOptions );
617 else
618 return nullptr;
619}
620
621QList<QPair<QString, QString> > QgsProviderRegistry::pyramidResamplingMethods( const QString &providerKey )
622{
623 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
624 if ( meta )
625 return meta->pyramidResamplingMethods();
626 else
627 return QList<QPair<QString, QString> >();
628}
629
630QList<QgsDataItemProvider *> QgsProviderRegistry::dataItemProviders( const QString &providerKey ) const
631{
632 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
633 if ( meta )
634 return meta->dataItemProviders();
635 else
636 return QList<QgsDataItemProvider *>();
637}
638
639int QgsProviderRegistry::listStyles( const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause )
640{
641 int res = -1;
642 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
643 if ( meta )
644 {
645 res = meta->listStyles( uri, ids, names, descriptions, errCause );
646 }
647 else
648 {
649 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
650 }
651 return res;
652}
653
654bool QgsProviderRegistry::styleExists( const QString &providerKey, const QString &uri, const QString &styleId, QString &errorCause )
655{
656 errorCause.clear();
657
658 if ( QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey ) )
659 {
660 return meta->styleExists( uri, styleId, errorCause );
661 }
662 else
663 {
664 errorCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
665 return false;
666 }
667}
668
669QString QgsProviderRegistry::getStyleById( const QString &providerKey, const QString &uri, const QString &styleId, QString &errCause )
670{
671 QString ret;
672 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
673 if ( meta )
674 {
675 ret = meta->getStyleById( uri, styleId, errCause );
676 }
677 else
678 {
679 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
680 }
681 return ret;
682}
683
684bool QgsProviderRegistry::deleteStyleById( const QString &providerKey, const QString &uri, const QString &styleId, QString &errCause )
685{
686 const bool ret( false );
687
688 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
689 if ( meta )
690 return meta->deleteStyleById( uri, styleId, errCause );
691 else
692 {
693 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
694 }
695 return ret;
696}
697
698bool QgsProviderRegistry::saveStyle( const QString &providerKey, const QString &uri, const QString &qmlStyle,
699 const QString &sldStyle, const QString &styleName, const QString &styleDescription,
700 const QString &uiFileContent, bool useAsDefault, QString &errCause )
701{
702 bool ret( false );
703 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
704 if ( meta )
705 ret = meta->saveStyle( uri, qmlStyle, sldStyle, styleName, styleDescription,
706 uiFileContent, useAsDefault, errCause );
707 else
708 {
709 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
710 }
711 return ret;
712}
713
714QString QgsProviderRegistry::loadStyle( const QString &providerKey, const QString &uri, QString &errCause )
715{
716 QString ret;
717 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
718 if ( meta )
719 ret = meta->loadStyle( uri, errCause );
720 else
721 {
722 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
723 }
724 return ret;
725}
726
727QString QgsProviderRegistry::loadStoredStyle( const QString &providerKey, const QString &uri, QString &styleName, QString &errCause )
728{
729 QString ret;
730 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
731 if ( meta )
732 ret = meta->loadStoredStyle( uri, styleName, errCause );
733 else
734 {
735 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
736 }
737 return ret;
738}
739
740bool QgsProviderRegistry::saveLayerMetadata( const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage )
741{
742 errorMessage.clear();
743 if ( QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey ) )
744 return meta->saveLayerMetadata( uri, metadata, errorMessage );
745 else
746 {
747 throw QgsNotSupportedException( QObject::tr( "Unable to load %1 provider" ).arg( providerKey ) );
748 }
749}
750
751bool QgsProviderRegistry::createDb( const QString &providerKey, const QString &dbPath, QString &errCause )
752{
753 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
754 if ( meta )
755 return meta->createDb( dbPath, errCause );
756 else
757 {
758 errCause = QStringLiteral( "Resolving createDb(...) failed" );
759 return false;
760 }
761}
762
763QgsTransaction *QgsProviderRegistry::createTransaction( const QString &providerKey, const QString &connString )
764{
765 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
766 if ( meta )
767 return meta->createTransaction( connString );
768 else
769 return nullptr;
770}
771
772QWidget *QgsProviderRegistry::createSelectionWidget( const QString &providerKey,
773 QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
774{
775 Q_UNUSED( providerKey );
776 Q_UNUSED( parent );
777 Q_UNUSED( fl );
778 Q_UNUSED( widgetMode );
779 QgsDebugMsg( "deprecated call - use QgsGui::sourceSelectProviderRegistry()->createDataSourceWidget() instead" );
780 return nullptr;
781}
782
783QFunctionPointer QgsProviderRegistry::function( QString const &providerKey,
784 QString const &functionName ) const
785{
787 const QString lib = library( providerKey );
789 if ( lib.isEmpty() )
790 return nullptr;
791
792 QLibrary myLib( lib );
793
794 QgsDebugMsg( "Library name is " + myLib.fileName() );
795
796 if ( myLib.load() )
797 {
798 return myLib.resolve( functionName.toLatin1().data() );
799 }
800 else
801 {
802 QgsDebugMsg( "Cannot load library: " + myLib.errorString() );
803 return nullptr;
804 }
805}
806
807QLibrary *QgsProviderRegistry::createProviderLibrary( QString const &providerKey ) const
808{
810 const QString lib = library( providerKey );
812 if ( lib.isEmpty() )
813 return nullptr;
814
815 std::unique_ptr< QLibrary > myLib( new QLibrary( lib ) );
816
817 QgsDebugMsg( "Library name is " + myLib->fileName() );
818
819 if ( myLib->load() )
820 return myLib.release();
821
822 QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
823
824 return nullptr;
825}
826
828{
829 QgsDebugMsg( "deprecated - use QgsGui::providerGuiRegistry() instead." );
830}
831
833{
834 if ( providerMetadata )
835 {
836 if ( mProviders.find( providerMetadata->key() ) == mProviders.end() )
837 {
838 mProviders[ providerMetadata->key() ] = providerMetadata;
839 return true;
840 }
841 else
842 {
843 QgsDebugMsgLevel( QStringLiteral( "Cannot register provider metadata: a provider with the same key (%1) was already registered!" ).arg( providerMetadata->key() ), 2 );
844 }
845 }
846 else
847 {
848 QgsDebugMsgLevel( QStringLiteral( "Trying to register a null metadata provider!" ), 2 );
849 }
850 return false;
851}
852
854{
855 return mVectorFileFilters;
856}
857
859{
860 return mRasterFileFilters;
861}
862
864{
865 return mMeshFileFilters;
866}
867
869{
870 return mMeshDatasetFileFilters;
871}
872
874{
875 return mPointCloudFileFilters;
876}
877
879{
880 return mDatabaseDrivers;
881}
882
884{
885 return mDirectoryDrivers;
886}
887
889{
890 return mProtocolDrivers;
891}
892
894{
895 QStringList lst;
896 for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
897 {
898 lst.append( it->first );
899 }
900 return lst;
901}
902
904{
905 return findMetadata_( mProviders, providerKey );
906}
907
909{
910 QSet<QString> lst;
911 for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
912 {
913 if ( it->second->supportedLayerTypes().contains( type ) )
914 lst.insert( it->first );
915 }
916 return lst;
917}
918
919QList<QgsProviderRegistry::ProviderCandidateDetails> QgsProviderRegistry::preferredProvidersForUri( const QString &uri ) const
920{
921 QList< QgsProviderRegistry::ProviderCandidateDetails > res;
922 int maxPriority = 0;
923 for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
924 {
925 if ( !( it->second->capabilities() & QgsProviderMetadata::PriorityForUri ) )
926 continue;
927
928 const int thisProviderPriority = it->second->priorityForUri( uri );
929 if ( thisProviderPriority == 0 )
930 continue;
931
932 if ( thisProviderPriority > maxPriority )
933 {
934 res.clear();
935 maxPriority = thisProviderPriority;
936 }
937 if ( thisProviderPriority == maxPriority )
938 {
939 res.append( ProviderCandidateDetails( it->second, it->second->validLayerTypesForUri( uri ) ) );
940 }
941 }
942 return res;
943}
944
946{
947 mUnusableUriHandlers << handler;
948 return true;
949}
950
951bool QgsProviderRegistry::handleUnusableUri( const QString &uri, UnusableUriDetails &details ) const
952{
953 for ( const QgsProviderRegistry::UnusableUriHandlerInterface *handler : mUnusableUriHandlers )
954 {
955 if ( handler->matchesUri( uri ) )
956 {
957 details = handler->details( uri );
958 return true;
959 }
960 }
961 return false;
962}
963
964bool QgsProviderRegistry::shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const
965{
966 const QList< ProviderCandidateDetails > providers = preferredProvidersForUri( uri );
967 if ( providers.empty() )
968 return false;
969
970 for ( const ProviderCandidateDetails &provider : providers )
971 {
972 if ( provider.metadata()->key() == providerKey )
973 return false;
974 }
975 return true;
976}
977
978bool QgsProviderRegistry::uriIsBlocklisted( const QString &uri ) const
979{
980 for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
981 {
982 if ( it->second->uriIsBlocklisted( uri ) )
983 return true;
984 }
985 return false;
986}
987
988QList<QgsProviderSublayerDetails> QgsProviderRegistry::querySublayers( const QString &uri, Qgis::SublayerQueryFlags flags, QgsFeedback *feedback ) const
989{
990 // never query sublayers for blocklisted uris
991 if ( uriIsBlocklisted( uri ) )
992 return {};
993
994 QList<QgsProviderSublayerDetails> res;
995 for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
996 {
997 // if we should defer this uri for other providers, do so
998 if ( shouldDeferUriForOtherProviders( uri, it->first ) )
999 continue;
1000
1001 res.append( it->second->querySublayers( uri, flags, feedback ) );
1002 if ( feedback && feedback->isCanceled() )
1003 break;
1004 }
1005 return res;
1006}
VectorExportResult
Vector layer export result codes.
Definition: qgis.h:620
DataType
Raster data types.
Definition: qgis.h:242
LayerType
Types of layers that can be added to a map.
Definition: qgis.h:115
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:155
This class represents a coordinate reference system (CRS).
This is the interface for those who want to add custom data items to the browser tree.
Abstract base class for spatial data provider implementations.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
bool isCanceled() const SIP_HOLDGIL
Tells whether the operation has been canceled already.
Definition: qgsfeedback.h:54
Container of fields for a vector layer.
Definition: qgsfields.h:45
static QString wildcardsFromFilter(const QString &filter)
Given a filter string like "GeoTIFF Files (*.tiff *.tif)", extracts the wildcard portion of this filt...
A structured metadata store for a map layer.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
Definition: qgsexception.h:118
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:477
void removeAllMapLayers()
Removes all registered layers.
Holds data provider key, description, and associated shared library file or function pointer informat...
virtual QgsRasterDataProvider * createRasterDataProvider(const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates a new instance of the raster data provider.
@ FilterPointCloud
Point clouds (since QGIS 3.18)
virtual bool deleteStyleById(const QString &uri, const QString &styleId, QString &errCause)
Deletes a layer style defined by styleId.
virtual bool saveStyle(const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Saves a layer style to provider.
virtual QgsDataProvider * createProvider(const QString &uri, const QgsDataProvider::ProviderOptions &options, QgsDataProvider::ReadFlags flags=QgsDataProvider::ReadFlags())
Class factory to return a pointer to a newly created QgsDataProvider object.
virtual QString filters(FilterType type)
Builds the list of file filter strings (supported formats)
virtual bool saveLayerMetadata(const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage) SIP_THROW(QgsNotSupportedException)
Saves metadata to the layer corresponding to the specified uri.
virtual QString encodeUri(const QVariantMap &parts) const
Reassembles a provider data source URI from its component paths (e.g.
virtual QString absoluteToRelativeUri(const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
virtual Qgis::VectorExportResult createEmptyLayer(const QString &uri, const QgsFields &fields, Qgis::WkbType wkbType, const QgsCoordinateReferenceSystem &srs, bool overwrite, QMap< int, int > &oldToNewAttrIdxMap, QString &errorMessage, const QMap< QString, QVariant > *options)
Creates new empty vector layer.
virtual bool styleExists(const QString &uri, const QString &styleId, QString &errorCause)
Returns true if a layer style with the specified styleId exists in the provider defined by uri.
QString key() const
This returns the unique key associated with the provider.
virtual QgsTransaction * createTransaction(const QString &connString)
Returns new instance of transaction.
virtual void initProvider()
Initialize the provider.
virtual QString getStyleById(const QString &uri, const QString &styleId, QString &errCause)
Gets a layer style defined by uri.
virtual QString loadStoredStyle(const QString &uri, QString &styleName, QString &errCause)
Loads a layer style from the provider storage, reporting its name.
@ PriorityForUri
Indicates that the metadata can calculate a priority for a URI.
virtual QString relativeToAbsoluteUri(const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
virtual QString loadStyle(const QString &uri, QString &errCause)
Loads a layer style defined by uri.
virtual int listStyles(const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Lists stored layer styles in the provider defined by uri.
virtual QList< QPair< QString, QString > > pyramidResamplingMethods()
Returns pyramid resampling methods available for provider.
virtual QList< QgsDataItemProvider * > dataItemProviders() const
Returns data item providers.
virtual QVariantMap decodeUri(const QString &uri) const
Breaks a provider data source URI into its component paths (e.g.
Q_DECL_DEPRECATED QString library() const
This returns the library file name.
virtual bool createDb(const QString &dbPath, QString &errCause)
Creates database by the provider on the path.
Contains information pertaining to a candidate provider.
Contains information about unusable URIs which aren't handled by any registered providers.
QString detailedWarning
Contains a longer, user-friendly, translated message advising why the URI is not usable.
An interface used to handle unusable URIs which aren't handled by any registered providers,...
virtual UnusableUriDetails details(const QString &uri) const =0
Returns the details for advising the user why the uri is not usable.
virtual bool matchesUri(const QString &uri) const =0
Returns true if the handle is an unusable URI handler for the specified uri.
A registry / canonical manager of data providers.
QString absoluteToRelativeUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts absolute path(s) to relative path(s) in the given provider-specific URI.
QgsDataProvider * createProvider(const QString &providerKey, const QString &dataSource, const QgsDataProvider::ProviderOptions &options=QgsDataProvider::ProviderOptions(), QgsDataProvider::ReadFlags flags=QgsDataProvider::ReadFlags())
Creates a new instance of a provider.
std::map< QString, QgsProviderMetadata * > Providers
Type for data provider metadata associative container.
bool styleExists(const QString &providerKey, const QString &uri, const QString &styleId, QString &errorCause)
Returns true if a layer style with the specified styleId exists in the provider defined by providerKe...
QString loadStyle(const QString &providerKey, const QString &uri, QString &errCause)
Loads a layer style defined by uri.
QString getStyleById(const QString &providerKey, const QString &uri, const QString &styleId, QString &errCause)
Gets a layer style defined by styleId.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
void setLibraryDirectory(const QDir &path)
Sets library directory where to search for plugins.
QgsTransaction * createTransaction(const QString &providerKey, const QString &connString)
Returns new instance of transaction.
QList< QgsProviderSublayerDetails > querySublayers(const QString &uri, Qgis::SublayerQueryFlags flags=Qgis::SublayerQueryFlags(), QgsFeedback *feedback=nullptr) const
Queries the specified uri and returns a list of any valid sublayers found in the dataset which can be...
Q_DECL_DEPRECATED void registerGuis(QWidget *widget)
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
WidgetMode
Different ways a source select dialog can be used.
QString protocolDrivers() const
Returns a string containing the available protocol drivers.
QList< QgsProviderRegistry::ProviderCandidateDetails > preferredProvidersForUri(const QString &uri) const
Returns the details for the preferred provider(s) for opening the specified uri.
Q_DECL_DEPRECATED QString library(const QString &providerKey) const
Returns path for the library of the provider.
QString databaseDrivers() const
Returns a string containing the available database drivers.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
QList< QgsDataItemProvider * > dataItemProviders(const QString &providerKey) const
Returns list of data item providers of the provider.
QgsRasterDataProvider * createRasterDataProvider(const QString &providerKey, const QString &uri, const QString &format, int nBands, Qgis::DataType type, int width, int height, double *geoTransform, const QgsCoordinateReferenceSystem &crs, const QStringList &createOptions=QStringList())
Creates new instance of raster data provider.
QList< QPair< QString, QString > > pyramidResamplingMethods(const QString &providerKey)
Returns list of raster pyramid resampling methods.
bool uriIsBlocklisted(const QString &uri) const
Returns true if the specified uri is known by any registered provider to be something which should be...
Q_DECL_DEPRECATED QLibrary * createProviderLibrary(const QString &providerKey) const
Returns a new QLibrary for the specified providerKey.
Qgis::VectorExportResult createEmptyLayer(const QString &providerKey, const QString &uri, const QgsFields &fields, Qgis::WkbType wkbType, const QgsCoordinateReferenceSystem &srs, bool overwrite, QMap< int, int > &oldToNewAttrIdxMap, QString &errorMessage, const QMap< QString, QVariant > *options)
Creates new empty vector layer.
bool handleUnusableUri(const QString &uri, UnusableUriDetails &details) const
Returns true if the specified uri can potentially be handled by QGIS, if additional dependencies or b...
QString fileVectorFilters() const
Returns a file filter string for supported vector files.
QString fileRasterFilters() const
Returns a file filter string for supported raster files.
QString fileMeshFilters() const
Returns a file filter string for supported mesh files.
QString pluginList(bool asHtml=false) const
Returns list of provider plugins found.
Q_DECL_DEPRECATED int providerCapabilities(const QString &providerKey) const
Returns the provider capabilities.
bool shouldDeferUriForOtherProviders(const QString &uri, const QString &providerKey) const
Returns true if the provider with matching providerKey should defer handling of the specified uri to ...
bool deleteStyleById(const QString &providerKey, const QString &uri, const QString &styleId, QString &errCause)
Deletes a layer style defined by styleId.
QStringList providerList() const
Returns list of available providers by their keys.
QString fileMeshDatasetFilters() const
Returns a file filter string for supported mesh dataset files.
QString loadStoredStyle(const QString &providerKey, const QString &uri, QString &styleName, QString &errCause)
Loads a layer style from the provider storage, reporting its name.
QDir libraryDirectory() const
Returns the library directory where plugins are found.
QString relativeToAbsoluteUri(const QString &providerKey, const QString &uri, const QgsReadWriteContext &context) const
Converts relative path(s) to absolute path(s) in the given provider-specific URI.
QgsProviderMetadata * providerMetadata(const QString &providerKey) const
Returns metadata of the provider or nullptr if not found.
int listStyles(const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause)
Lists stored layer styles in the provider defined by providerKey and uri.
bool createDb(const QString &providerKey, const QString &dbPath, QString &errCause)
Creates database by the provider on the path.
bool saveStyle(const QString &providerKey, const QString &uri, const QString &qmlStyle, const QString &sldStyle, const QString &styleName, const QString &styleDescription, const QString &uiFileContent, bool useAsDefault, QString &errCause)
Saves a layer style to provider.
QSet< QString > providersForLayerType(Qgis::LayerType type) const
Returns a list of the provider keys for available providers which handle the specified layer type.
bool registerProvider(QgsProviderMetadata *providerMetadata)
register a new vector data provider from its providerMetadata
Q_DECL_DEPRECATED QFunctionPointer function(const QString &providerKey, const QString &functionName) const
Gets pointer to provider function.
QString directoryDrivers() const
Returns a string containing the available directory drivers.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage) SIP_THROW(QgsNotSupportedException)
Saves metadata to the layer corresponding to the specified uri.
bool registerUnusableUriHandler(UnusableUriHandlerInterface *handler)
Registers an unusable URI handler, used to handle unusable URIs which aren't handled by any registere...
Q_DECL_DEPRECATED QWidget * createSelectionWidget(const QString &providerKey, QWidget *parent=nullptr, Qt::WindowFlags fl=Qt::WindowFlags(), QgsProviderRegistry::WidgetMode widgetMode=QgsProviderRegistry::WidgetMode::None)
Returns a new widget for selecting layers from a provider.
QString filePointCloudFilters() const
Returns a file filter string for supported point clouds.
Base class for raster data providers.
The class is used as a container of context for various read/write operations on other objects.
Scoped object for logging of the runtime for a single operation or group of operations.
This class allows including a set of layers in a database-side transaction, provided the layer data p...
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:4093
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:4092
#define cast_to_fptr(f)
Definition: qgis.h:3381
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
void cleanupProviderFunction_t()
const QgsCoordinateReferenceSystem & crs
Setting options for creating vector data providers.