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