QGIS API Documentation 3.29.0-Master (8c80f25a4f)
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
710QString QgsProviderRegistry::loadStoredStyle( const QString &providerKey, const QString &uri, QString &styleName, QString &errCause )
711{
712 QString ret;
713 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
714 if ( meta )
715 ret = meta->loadStoredStyle( uri, styleName, errCause );
716 else
717 {
718 errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
719 }
720 return ret;
721}
722
723bool QgsProviderRegistry::saveLayerMetadata( const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage )
724{
725 errorMessage.clear();
726 if ( QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey ) )
727 return meta->saveLayerMetadata( uri, metadata, errorMessage );
728 else
729 {
730 throw QgsNotSupportedException( QObject::tr( "Unable to load %1 provider" ).arg( providerKey ) );
731 }
732}
733
734bool QgsProviderRegistry::createDb( const QString &providerKey, const QString &dbPath, QString &errCause )
735{
736 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
737 if ( meta )
738 return meta->createDb( dbPath, errCause );
739 else
740 {
741 errCause = QStringLiteral( "Resolving createDb(...) failed" );
742 return false;
743 }
744}
745
746QgsTransaction *QgsProviderRegistry::createTransaction( const QString &providerKey, const QString &connString )
747{
748 QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
749 if ( meta )
750 return meta->createTransaction( connString );
751 else
752 return nullptr;
753}
754
755QWidget *QgsProviderRegistry::createSelectionWidget( const QString &providerKey,
756 QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
757{
758 Q_UNUSED( providerKey );
759 Q_UNUSED( parent );
760 Q_UNUSED( fl );
761 Q_UNUSED( widgetMode );
762 QgsDebugMsg( "deprecated call - use QgsGui::sourceSelectProviderRegistry()->createDataSourceWidget() instead" );
763 return nullptr;
764}
765
766QFunctionPointer QgsProviderRegistry::function( QString const &providerKey,
767 QString const &functionName ) const
768{
770 const QString lib = library( providerKey );
772 if ( lib.isEmpty() )
773 return nullptr;
774
775 QLibrary myLib( lib );
776
777 QgsDebugMsg( "Library name is " + myLib.fileName() );
778
779 if ( myLib.load() )
780 {
781 return myLib.resolve( functionName.toLatin1().data() );
782 }
783 else
784 {
785 QgsDebugMsg( "Cannot load library: " + myLib.errorString() );
786 return nullptr;
787 }
788}
789
790QLibrary *QgsProviderRegistry::createProviderLibrary( QString const &providerKey ) const
791{
793 const QString lib = library( providerKey );
795 if ( lib.isEmpty() )
796 return nullptr;
797
798 std::unique_ptr< QLibrary > myLib( new QLibrary( lib ) );
799
800 QgsDebugMsg( "Library name is " + myLib->fileName() );
801
802 if ( myLib->load() )
803 return myLib.release();
804
805 QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
806
807 return nullptr;
808}
809
811{
812 QgsDebugMsg( "deprecated - use QgsGui::providerGuiRegistry() instead." );
813}
814
816{
817 if ( providerMetadata )
818 {
819 if ( mProviders.find( providerMetadata->key() ) == mProviders.end() )
820 {
821 mProviders[ providerMetadata->key() ] = providerMetadata;
822 return true;
823 }
824 else
825 {
826 QgsDebugMsgLevel( QStringLiteral( "Cannot register provider metadata: a provider with the same key (%1) was already registered!" ).arg( providerMetadata->key() ), 2 );
827 }
828 }
829 else
830 {
831 QgsDebugMsgLevel( QStringLiteral( "Trying to register a null metadata provider!" ), 2 );
832 }
833 return false;
834}
835
837{
838 return mVectorFileFilters;
839}
840
842{
843 return mRasterFileFilters;
844}
845
847{
848 return mMeshFileFilters;
849}
850
852{
853 return mMeshDatasetFileFilters;
854}
855
857{
858 return mPointCloudFileFilters;
859}
860
862{
863 return mDatabaseDrivers;
864}
865
867{
868 return mDirectoryDrivers;
869}
870
872{
873 return mProtocolDrivers;
874}
875
877{
878 QStringList lst;
879 for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
880 {
881 lst.append( it->first );
882 }
883 return lst;
884}
885
887{
888 return findMetadata_( mProviders, providerKey );
889}
890
892{
893 QSet<QString> lst;
894 for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
895 {
896 if ( it->second->supportedLayerTypes().contains( type ) )
897 lst.insert( it->first );
898 }
899 return lst;
900}
901
902QList<QgsProviderRegistry::ProviderCandidateDetails> QgsProviderRegistry::preferredProvidersForUri( const QString &uri ) const
903{
904 QList< QgsProviderRegistry::ProviderCandidateDetails > res;
905 int maxPriority = 0;
906 for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
907 {
908 if ( !( it->second->capabilities() & QgsProviderMetadata::PriorityForUri ) )
909 continue;
910
911 const int thisProviderPriority = it->second->priorityForUri( uri );
912 if ( thisProviderPriority == 0 )
913 continue;
914
915 if ( thisProviderPriority > maxPriority )
916 {
917 res.clear();
918 maxPriority = thisProviderPriority;
919 }
920 if ( thisProviderPriority == maxPriority )
921 {
922 res.append( ProviderCandidateDetails( it->second, it->second->validLayerTypesForUri( uri ) ) );
923 }
924 }
925 return res;
926}
927
929{
930 mUnusableUriHandlers << handler;
931 return true;
932}
933
934bool QgsProviderRegistry::handleUnusableUri( const QString &uri, UnusableUriDetails &details ) const
935{
936 for ( const QgsProviderRegistry::UnusableUriHandlerInterface *handler : mUnusableUriHandlers )
937 {
938 if ( handler->matchesUri( uri ) )
939 {
940 details = handler->details( uri );
941 return true;
942 }
943 }
944 return false;
945}
946
947bool QgsProviderRegistry::shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const
948{
949 const QList< ProviderCandidateDetails > providers = preferredProvidersForUri( uri );
950 if ( providers.empty() )
951 return false;
952
953 for ( const ProviderCandidateDetails &provider : providers )
954 {
955 if ( provider.metadata()->key() == providerKey )
956 return false;
957 }
958 return true;
959}
960
961bool QgsProviderRegistry::uriIsBlocklisted( const QString &uri ) const
962{
963 for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
964 {
965 if ( it->second->uriIsBlocklisted( uri ) )
966 return true;
967 }
968 return false;
969}
970
971QList<QgsProviderSublayerDetails> QgsProviderRegistry::querySublayers( const QString &uri, Qgis::SublayerQueryFlags flags, QgsFeedback *feedback ) const
972{
973 // never query sublayers for blocklisted uris
974 if ( uriIsBlocklisted( uri ) )
975 return {};
976
977 QList<QgsProviderSublayerDetails> res;
978 for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
979 {
980 // if we should defer this uri for other providers, do so
981 if ( shouldDeferUriForOtherProviders( uri, it->first ) )
982 continue;
983
984 res.append( it->second->querySublayers( uri, flags, feedback ) );
985 if ( feedback && feedback->isCanceled() )
986 break;
987 }
988 return res;
989}
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:476
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.
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 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.
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.
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:3499
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:3498
#define cast_to_fptr(f)
Definition: qgis.h:2787
#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.