41
38
typedef QString description_t();
42
39
typedef bool isprovider_t();
43
40
typedef QString fileVectorFilters_t();
41
typedef QString databaseDrivers_t();
42
typedef QString directoryDrivers_t();
43
typedef QString protocolDrivers_t();
45
45
QgsProviderRegistry *QgsProviderRegistry::_instance = 0;
47
QgsProviderRegistry *QgsProviderRegistry::instance(QString pluginPath)
47
QgsProviderRegistry *QgsProviderRegistry::instance( QString pluginPath )
51
_instance = new QgsProviderRegistry(pluginPath);
51
_instance = new QgsProviderRegistry( pluginPath );
56
56
} // QgsProviderRegistry::instance
60
QgsProviderRegistry::QgsProviderRegistry(QString pluginPath)
60
QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )
62
62
// At startup, examine the libs in the qgis/lib dir and store those that
63
63
// are a provider shared lib
75
75
mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
78
mLibraryDirectory.setNameFilter( "*.dll" );
78
mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
80
mLibraryDirectory.setNameFilter( "*.so" );
84
QgsLogger::debug("Checking " + mLibraryDirectory.path() + " for provider plugins\n", 1, __FILE__, __FUNCTION__, __LINE__);
87
if (mLibraryDirectory.count() == 0)
80
mLibraryDirectory.setNameFilters( QStringList( "*.so" ) );
83
QgsDebugMsg( QString( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ) );
85
if ( mLibraryDirectory.count() == 0 )
89
QString msg = QObject::tr("No Data Provider Plugins",
90
"No QGIS data provider plugins found in:");
91
msg += "\n" + mLibraryDirectory.path() + "\n\n";
92
msg += QObject::tr("No vector layers can be loaded. Check your QGIS installation");
93
QMessageBox::critical(0, QObject::tr("No Data Providers"), msg);
87
QString msg = QObject::tr( "No QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
88
msg += QObject::tr( "No vector layers can be loaded. Check your QGIS installation" );
90
QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
91
output->setTitle( QObject::tr( "No Data Providers" ) );
92
output->setMessage( msg, QgsMessageOutput::MessageText );
93
output->showMessage();
97
97
const QFileInfoList list = mLibraryDirectory.entryInfoList();
98
98
QListIterator<QFileInfo> it( list );
101
while ( it.hasNext() )
105
105
QLibrary *myLib = new QLibrary( fi.filePath() );
107
107
bool loaded = myLib->load();
108
//we will build up a debug message and print on one line to avoid terminal spam
109
QString myMessage = "Checking " + myLib->fileName() + " : " ;
112
QgsLogger::debug("Checking " + myLib->library(), 1, __FILE__, __FUNCTION__, __LINE__);
114
113
// get the description and the key for the provider plugin
115
isprovider_t *isProvider = (isprovider_t *) myLib->resolve("isProvider");
117
//MH: Added a further test to detect non-provider plugins linked to provider plugins.
118
//Only pure provider plugins have 'type' not defined
119
isprovider_t *hasType = (isprovider_t *) myLib->resolve("type");
121
if (!hasType && isProvider)
114
isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "isProvider" ) );
116
//MH: Added a further test to detect non-provider plugins linked to provider plugins.
117
//Only pure provider plugins have 'type' not defined
118
isprovider_t *hasType = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "type" ) );
120
if ( !hasType && isProvider )
123
122
// check to see if this is a provider plugin
126
125
// looks like a provider. get the key and description
127
description_t *pDesc = (description_t *) myLib->resolve("description");
128
providerkey_t *pKey = (providerkey_t *) myLib->resolve("providerKey");
126
description_t *pDesc = ( description_t * ) cast_to_fptr( myLib->resolve( "description" ) );
127
providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib->resolve( "providerKey" ) );
131
130
// add this provider to the provider map
133
new QgsProviderMetadata(pKey(), pDesc(), myLib->library());
135
QgsDebugMsg("Loaded " + pDesc());
132
new QgsProviderMetadata( pKey(), pDesc(), myLib->fileName() );
133
//myMessage += "Loaded " + QString(pDesc()) + " ok";
138
135
// now get vector file filters, if any
139
fileVectorFilters_t *pFileVectorFilters =
140
(fileVectorFilters_t *) myLib->resolve("fileVectorFilters");
136
fileVectorFilters_t *pFileVectorFilters =
137
( fileVectorFilters_t * ) cast_to_fptr( myLib->resolve( "fileVectorFilters" ) );
138
//load database drivers
139
databaseDrivers_t *pDatabaseDrivers =
140
( databaseDrivers_t * ) cast_to_fptr( myLib->resolve( "databaseDrivers" ) );
141
if ( pDatabaseDrivers )
143
mDatabaseDrivers = pDatabaseDrivers();
145
//load directory drivers
146
directoryDrivers_t *pDirectoryDrivers =
147
( directoryDrivers_t * ) cast_to_fptr( myLib->resolve( "directoryDrivers" ) );
148
if ( pDirectoryDrivers )
150
mDirectoryDrivers = pDirectoryDrivers();
152
//load protocol drivers
153
protocolDrivers_t *pProtocolDrivers =
154
( protocolDrivers_t * ) cast_to_fptr( myLib->resolve( "protocolDrivers" ) );
155
if ( pProtocolDrivers )
157
mProtocolDrivers = pProtocolDrivers();
142
160
if ( pFileVectorFilters )
144
162
QString vectorFileFilters = pFileVectorFilters();
147
164
// now get vector file filters, if any
148
fileVectorFilters_t *pVectorFileFilters =
149
(fileVectorFilters_t *) myLib->resolve("fileVectorFilters");
165
fileVectorFilters_t *pVectorFileFilters =
166
( fileVectorFilters_t * ) cast_to_fptr( myLib->resolve( "fileVectorFilters" ) );
151
168
if ( pVectorFileFilters )
155
172
if ( ! fileVectorFilters.isEmpty() )
157
174
mVectorFileFilters += fileVectorFilters;
175
myMessage += QString( "... loaded ok (and with %1 file filters)" ).
176
arg( fileVectorFilters.split( ";;" ).count() );
161
QgsLogger::debug("No vector file filters for " + pKey(), 1, __FILE__, __FUNCTION__, __LINE__);
180
//myMessage += ", but it has no vector file filters for " + QString(pKey());
181
myMessage += "... loaded ok (0 file filters)";
167
QgsDebugMsg("Unable to invoke fileVectorFilters()");
187
//myMessage += ", but unable to invoke fileVectorFilters()";
188
myMessage += "... loaded ok (null file filters)";
172
QgsLogger::debug("Unable to find one of the required provider functions (providerKey() or description()) in " + myLib->library());
193
//myMessage += ", but unable to find one of the required provider functions (providerKey() or description()) in ";
194
myMessage += "...not usable";
177
QgsDebugMsg("Unable to invoke fileVectorFilters()");
200
//myMessage += ", but this is not a valid provider, skipping.";
201
myMessage += "..invalid";
183
QgsDebugMsg(myLib->library() + " is not a provider");
206
//myMessage += ", but this is not a valid provider or has no type, skipping.";
207
myMessage += "..invalid (no type)";
212
myMessage += "...invalid (lib not loadable)";
215
QgsDebugMsg( myMessage );
275
void QgsProviderRegistry::setLibraryDirectory(QDir const & path)
306
void QgsProviderRegistry::setLibraryDirectory( QDir const & path )
277
mLibraryDirectory = path;
308
mLibraryDirectory = path;
281
312
QDir const & QgsProviderRegistry::libraryDirectory() const
283
return mLibraryDirectory;
314
return mLibraryDirectory;
288
319
// typedef for the QgsDataProvider class factory
289
320
typedef QgsDataProvider * classFactoryFunction_t( const QString * );
293
/** Copied from QgsVectorLayer::setDataProvider
324
/** Copied from QgsVectorLayer::setDataProvider
294
325
* TODO: Make it work in the generic environment
296
327
* TODO: Is this class really the best place to put a data provider loader?
297
328
* It seems more sensible to provide the code in one place rather than
298
329
* in qgsrasterlayer, qgsvectorlayer, serversourceselect, etc.
300
QgsDataProvider* QgsProviderRegistry::getProvider( QString const & providerKey,
301
QString const & dataSource )
331
QgsDataProvider* QgsProviderRegistry::getProvider( QString const & providerKey,
332
QString const & dataSource )
303
334
// XXX should I check for and possibly delete any pre-existing providers?
304
335
// XXX How often will that scenario occur?
307
const char * providerStr = providerKey.ascii(); // debugger probe
308
const char * dataSourceStr = dataSource.ascii(); // ditto
311
337
// load the plugin
312
QString lib = library(providerKey);
338
QString lib = library( providerKey );
314
340
#ifdef TESTPROVIDERLIB
315
const char *cLib = (const char *) lib;
341
const char *cLib = lib.toUtf8();
317
343
// test code to help debug provider loading problems
318
344
// void *handle = dlopen(cLib, RTLD_LAZY);
319
void *handle = dlopen(cOgrLib, RTLD_LAZY | RTLD_GLOBAL);
345
void *handle = dlopen( cOgrLib, RTLD_LAZY | RTLD_GLOBAL );
322
QgsLogger::warning("Error in dlopen");
348
QgsLogger::warning( "Error in dlopen" );
326
QgsDebugMsg("dlopen suceeded");
352
QgsDebugMsg( "dlopen suceeded" );
332
358
// load the data provider
333
QLibrary* myLib = new QLibrary((const char *) lib);
359
QLibrary* myLib = new QLibrary( lib );
336
QgsDebugMsg("QgsProviderRegistry::getRasterProvider: Library name is " + myLib->library());
361
QgsDebugMsg( "Library name is " + myLib->fileName() );
339
363
bool loaded = myLib->load();
343
QgsDebugMsg( "Loaded data provider library" );
344
QgsDebugMsg( "Attempting to resolve the classFactory function" );
346
classFactoryFunction_t * classFactory =
347
(classFactoryFunction_t *) myLib->resolve("classFactory");
367
QgsDebugMsg( "Loaded data provider library" );
368
QgsDebugMsg( "Attempting to resolve the classFactory function" );
370
classFactoryFunction_t * classFactory =
371
( classFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "classFactory" ) );
351
375
QgsDebugMsg( "Getting pointer to a dataProvider object from the library" );
353
377
//XXX - This was a dynamic cast but that kills the Windows
354
378
// version big-time with an abnormal termination error
355
// QgsDataProvider* dataProvider = (QgsDataProvider*)
356
// (classFactory((const char*)(dataSource.utf8())));
358
QgsDataProvider * dataProvider = (*classFactory)(&dataSource);
379
// QgsDataProvider* dataProvider = (QgsDataProvider*)
380
// (classFactory((const char*)(dataSource.utf8())));
382
QgsDataProvider * dataProvider = ( *classFactory )( &dataSource );
363
386
QgsDebugMsg( "Instantiated the data provider plugin" );
364
QgsDebugMsg("provider name: " + dataProvider->name());
366
if (dataProvider->isValid())
387
QgsDebugMsg( "provider name: " + dataProvider->name() );
389
if ( dataProvider->isValid() )
369
392
return dataProvider;
372
395
{ // this is likely because the dataSource is invalid, and isn't
373
// necessarily a reflection on the data provider itself
374
QgsDebugMsg( "Invalid data provider" );
396
// necessarily a reflection on the data provider itself
397
QgsDebugMsg( "Invalid data provider" );
383
406
QgsLogger::warning( "Unable to instantiate the data provider plugin" );
393
QgsLogger::warning( "Failed to load ../providers/libproviders.so" );
416
QgsLogger::warning( "Failed to load " + lib );
398
421
QgsDebugMsg( "exiting" );
400
423
return 0; // factory didn't exist
402
425
} // QgsProviderRegistry::setDataProvider
408
427
QString QgsProviderRegistry::fileVectorFilters() const
410
return mVectorFileFilters;
411
} // QgsProviderRegistry::fileVectorFilters
429
return mVectorFileFilters;
432
QString QgsProviderRegistry::databaseDrivers() const
434
return mDatabaseDrivers;
437
QString QgsProviderRegistry::directoryDrivers() const
439
return mDirectoryDrivers;
442
QString QgsProviderRegistry::protocolDrivers() const
444
return mProtocolDrivers;
448
QStringList QgsProviderRegistry::providerList() const
451
for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); it++ )
453
lst.append( it->first );
459
const QgsProviderMetadata* QgsProviderRegistry::providerMetadata( const QString& providerKey ) const
461
return findMetadata_( mProviders, providerKey );
417
467
QgsProviderRegistry::openVector( QString const & dataSource, QString const & providerKey )
419
469
return getProvider( providerKey, dataSource );
420
470
} // QgsProviderRegistry::openVector