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