QGIS API Documentation  3.20.0-Odense (decaadbb31)
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 {
547  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
548  if ( meta )
549  return meta->createEmptyLayer( uri, fields, wkbType, srs, overwrite, oldToNewAttrIdxMap, errorMessage, options );
550  else
551  {
552  errorMessage = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
553  return Qgis::VectorExportResult::ErrorInvalidProvider;
554  }
555 }
556 
557 QgsRasterDataProvider *QgsProviderRegistry::createRasterDataProvider( const QString &providerKey, const QString &uri, const QString &format,
558  int nBands, Qgis::DataType type, int width, int height,
559  double *geoTransform, const QgsCoordinateReferenceSystem &crs,
560  const QStringList &createOptions )
561 {
562  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
563  if ( meta )
564  return meta->createRasterDataProvider( uri, format, nBands, type, width, height, geoTransform, crs, createOptions );
565  else
566  return nullptr;
567 }
568 
569 QList<QPair<QString, QString> > QgsProviderRegistry::pyramidResamplingMethods( const QString &providerKey )
570 {
571  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
572  if ( meta )
573  return meta->pyramidResamplingMethods();
574  else
575  return QList<QPair<QString, QString> >();
576 }
577 
578 QList<QgsDataItemProvider *> QgsProviderRegistry::dataItemProviders( const QString &providerKey ) const
579 {
580  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
581  if ( meta )
582  return meta->dataItemProviders();
583  else
584  return QList<QgsDataItemProvider *>();
585 }
586 
587 int QgsProviderRegistry::listStyles( const QString &providerKey, const QString &uri, QStringList &ids, QStringList &names, QStringList &descriptions, QString &errCause )
588 {
589  int res = -1;
590  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
591  if ( meta )
592  {
593  res = meta->listStyles( uri, ids, names, descriptions, errCause );
594  }
595  else
596  {
597  errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
598  }
599  return res;
600 }
601 
602 QString QgsProviderRegistry::getStyleById( const QString &providerKey, const QString &uri, QString styleId, QString &errCause )
603 {
604  QString ret;
605  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
606  if ( meta )
607  {
608  ret = meta->getStyleById( uri, styleId, errCause );
609  }
610  else
611  {
612  errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
613  }
614  return ret;
615 }
616 
617 bool QgsProviderRegistry::deleteStyleById( const QString &providerKey, const QString &uri, QString styleId, QString &errCause )
618 {
619  bool ret( false );
620 
621  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
622  if ( meta )
623  return meta->deleteStyleById( uri, styleId, errCause );
624  else
625  {
626  errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
627  }
628  return ret;
629 }
630 
631 bool QgsProviderRegistry::saveStyle( const QString &providerKey, const QString &uri, const QString &qmlStyle,
632  const QString &sldStyle, const QString &styleName, const QString &styleDescription,
633  const QString &uiFileContent, bool useAsDefault, QString &errCause )
634 {
635  bool ret( false );
636  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
637  if ( meta )
638  ret = meta->saveStyle( uri, qmlStyle, sldStyle, styleName, styleDescription,
639  uiFileContent, useAsDefault, errCause );
640  else
641  {
642  errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
643  }
644  return ret;
645 }
646 
647 QString QgsProviderRegistry::loadStyle( const QString &providerKey, const QString &uri, QString &errCause )
648 {
649  QString ret;
650  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
651  if ( meta )
652  ret = meta->loadStyle( uri, errCause );
653  else
654  {
655  errCause = QObject::tr( "Unable to load %1 provider" ).arg( providerKey );
656  }
657  return ret;
658 }
659 
660 bool QgsProviderRegistry::saveLayerMetadata( const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage )
661 {
662  errorMessage.clear();
663  if ( QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey ) )
664  return meta->saveLayerMetadata( uri, metadata, errorMessage );
665  else
666  {
667  throw QgsNotSupportedException( QObject::tr( "Unable to load %1 provider" ).arg( providerKey ) );
668  }
669 }
670 
671 bool QgsProviderRegistry::createDb( const QString &providerKey, const QString &dbPath, QString &errCause )
672 {
673  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
674  if ( meta )
675  return meta->createDb( dbPath, errCause );
676  else
677  {
678  errCause = QStringLiteral( "Resolving createDb(...) failed" );
679  return false;
680  }
681 }
682 
683 QgsTransaction *QgsProviderRegistry::createTransaction( const QString &providerKey, const QString &connString )
684 {
685  QgsProviderMetadata *meta = findMetadata_( mProviders, providerKey );
686  if ( meta )
687  return meta->createTransaction( connString );
688  else
689  return nullptr;
690 }
691 
692 QWidget *QgsProviderRegistry::createSelectionWidget( const QString &providerKey,
693  QWidget *parent, Qt::WindowFlags fl, QgsProviderRegistry::WidgetMode widgetMode )
694 {
695  Q_UNUSED( providerKey );
696  Q_UNUSED( parent );
697  Q_UNUSED( fl );
698  Q_UNUSED( widgetMode );
699  QgsDebugMsg( "deprecated call - use QgsGui::sourceSelectProviderRegistry()->createDataSourceWidget() instead" );
700  return nullptr;
701 }
702 
703 QFunctionPointer QgsProviderRegistry::function( QString const &providerKey,
704  QString const &functionName )
705 {
707  QString lib = library( providerKey );
709  if ( lib.isEmpty() )
710  return nullptr;
711 
712  QLibrary myLib( lib );
713 
714  QgsDebugMsg( "Library name is " + myLib.fileName() );
715 
716  if ( myLib.load() )
717  {
718  return myLib.resolve( functionName.toLatin1().data() );
719  }
720  else
721  {
722  QgsDebugMsg( "Cannot load library: " + myLib.errorString() );
723  return nullptr;
724  }
725 }
726 
727 QLibrary *QgsProviderRegistry::createProviderLibrary( QString const &providerKey ) const
728 {
730  QString lib = library( providerKey );
732  if ( lib.isEmpty() )
733  return nullptr;
734 
735  std::unique_ptr< QLibrary > myLib( new QLibrary( lib ) );
736 
737  QgsDebugMsg( "Library name is " + myLib->fileName() );
738 
739  if ( myLib->load() )
740  return myLib.release();
741 
742  QgsDebugMsg( "Cannot load library: " + myLib->errorString() );
743 
744  return nullptr;
745 }
746 
748 {
749  QgsDebugMsg( "deprecated - use QgsGui::providerGuiRegistry() instead." );
750 }
751 
753 {
754  if ( providerMetadata )
755  {
756  if ( mProviders.find( providerMetadata->key() ) == mProviders.end() )
757  {
758  mProviders[ providerMetadata->key() ] = providerMetadata;
759  return true;
760  }
761  else
762  {
763  QgsDebugMsgLevel( QStringLiteral( "Cannot register provider metadata: a provider with the same key (%1) was already registered!" ).arg( providerMetadata->key() ), 2 );
764  }
765  }
766  else
767  {
768  QgsDebugMsgLevel( QStringLiteral( "Trying to register a null metadata provider!" ), 2 );
769  }
770  return false;
771 }
772 
774 {
775  return mVectorFileFilters;
776 }
777 
779 {
780  return mRasterFileFilters;
781 }
782 
784 {
785  return mMeshFileFilters;
786 }
787 
789 {
790  return mMeshDatasetFileFilters;
791 }
792 
794 {
795  return mPointCloudFileFilters;
796 }
797 
799 {
800  return mDatabaseDrivers;
801 }
802 
804 {
805  return mDirectoryDrivers;
806 }
807 
809 {
810  return mProtocolDrivers;
811 }
812 
814 {
815  QStringList lst;
816  for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); ++it )
817  {
818  lst.append( it->first );
819  }
820  return lst;
821 }
822 
823 QgsProviderMetadata *QgsProviderRegistry::providerMetadata( const QString &providerKey ) const
824 {
825  return findMetadata_( mProviders, providerKey );
826 }
827 
828 QList<QgsProviderRegistry::ProviderCandidateDetails> QgsProviderRegistry::preferredProvidersForUri( const QString &uri ) const
829 {
830  QList< QgsProviderRegistry::ProviderCandidateDetails > res;
831  int maxPriority = 0;
832  for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
833  {
834  if ( !( it->second->capabilities() & QgsProviderMetadata::PriorityForUri ) )
835  continue;
836 
837  const int thisProviderPriority = it->second->priorityForUri( uri );
838  if ( thisProviderPriority == 0 )
839  continue;
840 
841  if ( thisProviderPriority > maxPriority )
842  {
843  res.clear();
844  maxPriority = thisProviderPriority;
845  }
846  if ( thisProviderPriority == maxPriority )
847  {
848  res.append( ProviderCandidateDetails( it->second, it->second->validLayerTypesForUri( uri ) ) );
849  }
850  }
851  return res;
852 }
853 
855 {
856  mUnusableUriHandlers << handler;
857  return true;
858 }
859 
860 bool QgsProviderRegistry::handleUnusableUri( const QString &uri, UnusableUriDetails &details ) const
861 {
862  for ( const QgsProviderRegistry::UnusableUriHandlerInterface *handler : mUnusableUriHandlers )
863  {
864  if ( handler->matchesUri( uri ) )
865  {
866  details = handler->details( uri );
867  return true;
868  }
869  }
870  return false;
871 }
872 
873 bool QgsProviderRegistry::shouldDeferUriForOtherProviders( const QString &uri, const QString &providerKey ) const
874 {
875  const QList< ProviderCandidateDetails > providers = preferredProvidersForUri( uri );
876  if ( providers.empty() )
877  return false;
878 
879  for ( const ProviderCandidateDetails &provider : providers )
880  {
881  if ( provider.metadata()->key() == providerKey )
882  return false;
883  }
884  return true;
885 }
886 
887 bool QgsProviderRegistry::uriIsBlocklisted( const QString &uri ) const
888 {
889  for ( auto it = mProviders.begin(); it != mProviders.end(); ++it )
890  {
891  if ( it->second->uriIsBlocklisted( uri ) )
892  return true;
893  }
894  return false;
895 }
VectorExportResult
Vector layer export result codes.
Definition: qgis.h:316
DataType
Raster data types.
Definition: qgis.h:119
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...
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:467
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 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 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.
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.
@ 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 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.
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.
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 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
@ PointCloudLayer
Added in 3.18.
#define Q_NOWARN_DEPRECATED_POP
Definition: qgis.h:1080
#define Q_NOWARN_DEPRECATED_PUSH
Definition: qgis.h:1079
#define cast_to_fptr(f)
Definition: qgis.h:483
#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.