00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "qgsproviderregistry.h"
00020
00021 #include <QString>
00022 #include <QDir>
00023 #include <QLibrary>
00024
00025
00026 #include "qgis.h"
00027 #include "qgsdataprovider.h"
00028 #include "qgslogger.h"
00029 #include "qgsmessageoutput.h"
00030 #include "qgsmessagelog.h"
00031 #include "qgsprovidermetadata.h"
00032 #include "qgsvectorlayer.h"
00033
00034
00035
00036 typedef QString providerkey_t();
00037 typedef QString description_t();
00038 typedef bool isprovider_t();
00039 typedef QString fileVectorFilters_t();
00040 typedef QString databaseDrivers_t();
00041 typedef QString directoryDrivers_t();
00042 typedef QString protocolDrivers_t();
00043
00044
00045
00046 QgsProviderRegistry *QgsProviderRegistry::_instance = 0;
00047
00048 QgsProviderRegistry *QgsProviderRegistry::instance( QString pluginPath )
00049 {
00050 if ( _instance == 0 )
00051 {
00052 _instance = new QgsProviderRegistry( pluginPath );
00053 }
00054
00055 return _instance;
00056
00057 }
00058
00059
00060
00061 QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )
00062 {
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 mLibraryDirectory = pluginPath;
00074
00075 mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
00076 mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );
00077
00078 #ifdef WIN32
00079 mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
00080 #elif ANDROID
00081 mLibraryDirectory.setNameFilters( QStringList( "*provider.so" ) );
00082 #else
00083 mLibraryDirectory.setNameFilters( QStringList( "*.so" ) );
00084 #endif
00085
00086 QgsDebugMsg( QString( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ) );
00087
00088 if ( mLibraryDirectory.count() == 0 )
00089 {
00090 QString msg = QObject::tr( "No QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
00091 msg += QObject::tr( "No vector layers can be loaded. Check your QGIS installation" );
00092
00093 QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
00094 output->setTitle( QObject::tr( "No Data Providers" ) );
00095 output->setMessage( msg, QgsMessageOutput::MessageText );
00096 output->showMessage();
00097 }
00098 else
00099 {
00100 const QFileInfoList list = mLibraryDirectory.entryInfoList();
00101 QListIterator<QFileInfo> it( list );
00102 QFileInfo fi;
00103
00104 while ( it.hasNext() )
00105 {
00106 fi = it.next();
00107
00108 QLibrary *myLib = new QLibrary( fi.filePath() );
00109
00110 bool loaded = myLib->load();
00111
00112 QString myMessage = "Checking " + myLib->fileName() + " : " ;
00113
00114 if ( loaded )
00115 {
00116
00117 isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "isProvider" ) );
00118
00119
00120
00121 isprovider_t *hasType = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "type" ) );
00122
00123 if ( !hasType && isProvider )
00124 {
00125
00126 if ( isProvider() )
00127 {
00128
00129 description_t *pDesc = ( description_t * ) cast_to_fptr( myLib->resolve( "description" ) );
00130 providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib->resolve( "providerKey" ) );
00131 if ( pDesc && pKey )
00132 {
00133
00134 mProviders[pKey()] =
00135 new QgsProviderMetadata( pKey(), pDesc(), myLib->fileName() );
00136
00137
00138
00139 fileVectorFilters_t *pFileVectorFilters =
00140 ( fileVectorFilters_t * ) cast_to_fptr( myLib->resolve( "fileVectorFilters" ) );
00141
00142 databaseDrivers_t *pDatabaseDrivers =
00143 ( databaseDrivers_t * ) cast_to_fptr( myLib->resolve( "databaseDrivers" ) );
00144 if ( pDatabaseDrivers )
00145 {
00146 mDatabaseDrivers = pDatabaseDrivers();
00147 }
00148
00149 directoryDrivers_t *pDirectoryDrivers =
00150 ( directoryDrivers_t * ) cast_to_fptr( myLib->resolve( "directoryDrivers" ) );
00151 if ( pDirectoryDrivers )
00152 {
00153 mDirectoryDrivers = pDirectoryDrivers();
00154 }
00155
00156 protocolDrivers_t *pProtocolDrivers =
00157 ( protocolDrivers_t * ) cast_to_fptr( myLib->resolve( "protocolDrivers" ) );
00158 if ( pProtocolDrivers )
00159 {
00160 mProtocolDrivers = pProtocolDrivers();
00161 }
00162
00163 if ( pFileVectorFilters )
00164 {
00165 QString vectorFileFilters = pFileVectorFilters();
00166
00167
00168 fileVectorFilters_t *pVectorFileFilters =
00169 ( fileVectorFilters_t * ) cast_to_fptr( myLib->resolve( "fileVectorFilters" ) );
00170
00171 if ( pVectorFileFilters )
00172 {
00173 QString fileVectorFilters = pVectorFileFilters();
00174
00175 if ( ! fileVectorFilters.isEmpty() )
00176 {
00177 mVectorFileFilters += fileVectorFilters;
00178 myMessage += QString( "... loaded ok (and with %1 file filters)" ).
00179 arg( fileVectorFilters.split( ";;" ).count() );
00180 }
00181 else
00182 {
00183
00184 myMessage += "... loaded ok (0 file filters)";
00185 }
00186 }
00187 }
00188 else
00189 {
00190
00191 myMessage += "... loaded ok (null file filters)";
00192 }
00193 }
00194 else
00195 {
00196
00197 myMessage += "...not usable";
00198
00199 }
00200 }
00201 else
00202 {
00203
00204 myMessage += "..invalid";
00205 }
00206 }
00207 else
00208 {
00209
00210 myMessage += "..invalid (no type)";
00211 }
00212 }
00213 else
00214 {
00215 myMessage += "...invalid (lib not loadable): ";
00216 myMessage += myLib->errorString();
00217 }
00218
00219 QgsDebugMsg( myMessage );
00220
00221 delete myLib;
00222 }
00223 }
00224
00225 }
00226
00227
00228 QgsProviderRegistry::~QgsProviderRegistry()
00229 {
00230 }
00231
00232
00240 static
00241 QgsProviderMetadata * findMetadata_( QgsProviderRegistry::Providers const & metaData,
00242 QString const & providerKey )
00243 {
00244 QgsProviderRegistry::Providers::const_iterator i =
00245 metaData.find( providerKey );
00246
00247 if ( i != metaData.end() )
00248 {
00249 return i->second;
00250 }
00251
00252 return 0x0;
00253 }
00254
00255
00256
00257 QString QgsProviderRegistry::library( QString const & providerKey ) const
00258 {
00259 QgsProviderMetadata * md = findMetadata_( mProviders, providerKey );
00260
00261 if ( md )
00262 {
00263 return md->library();
00264 }
00265
00266 return QString();
00267 }
00268
00269
00270 QString QgsProviderRegistry::pluginList( bool asHTML ) const
00271 {
00272 Providers::const_iterator it = mProviders.begin();
00273 QString list;
00274
00275 if ( mProviders.empty() )
00276 {
00277 list = QObject::tr( "No data provider plugins are available. No vector layers can be loaded" );
00278 }
00279 else
00280 {
00281 if ( asHTML )
00282 {
00283 list += "<ol>";
00284 }
00285 while ( it != mProviders.end() )
00286 {
00287 QgsProviderMetadata *mp = ( *it ).second;
00288
00289 if ( asHTML )
00290 {
00291 list += "<li>" + mp->description() + "<br>";
00292 }
00293 else
00294 {
00295 list += mp->description() + "\n";
00296 }
00297
00298 it++;
00299 }
00300 if ( asHTML )
00301 {
00302 list += "</ol>";
00303 }
00304 }
00305
00306 return list;
00307 }
00308
00309
00310 void QgsProviderRegistry::setLibraryDirectory( QDir const & path )
00311 {
00312 mLibraryDirectory = path;
00313 }
00314
00315
00316 QDir const & QgsProviderRegistry::libraryDirectory() const
00317 {
00318 return mLibraryDirectory;
00319 }
00320
00321
00322
00323
00324 typedef QgsDataProvider * classFactoryFunction_t( const QString * );
00325
00326
00327
00335 QgsDataProvider *QgsProviderRegistry::provider( QString const & providerKey, QString const & dataSource )
00336 {
00337
00338
00339
00340
00341 QString lib = library( providerKey );
00342
00343 #ifdef TESTPROVIDERLIB
00344 const char *cLib = lib.toUtf8();
00345
00346
00347
00348 void *handle = dlopen( cOgrLib, RTLD_LAZY | RTLD_GLOBAL );
00349 if ( !handle )
00350 {
00351 QgsLogger::warning( "Error in dlopen" );
00352 }
00353 else
00354 {
00355 QgsDebugMsg( "dlopen suceeded" );
00356 dlclose( handle );
00357 }
00358
00359 #endif
00360
00361
00362 QLibrary* myLib = new QLibrary( lib );
00363
00364 QgsDebugMsg( "Library name is " + myLib->fileName() );
00365
00366 bool loaded = myLib->load();
00367
00368 if ( loaded )
00369 {
00370 QgsDebugMsg( "Loaded data provider library" );
00371 QgsDebugMsg( "Attempting to resolve the classFactory function" );
00372
00373 classFactoryFunction_t * classFactory =
00374 ( classFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "classFactory" ) );
00375
00376 if ( classFactory )
00377 {
00378 QgsDebugMsg( "Getting pointer to a dataProvider object from the library" );
00379
00380
00381
00382
00383
00384
00385 QgsDataProvider * dataProvider = ( *classFactory )( &dataSource );
00386
00387 if ( dataProvider )
00388 {
00389 QgsDebugMsg( "Instantiated the data provider plugin" );
00390 QgsDebugMsg( "provider name: " + dataProvider->name() );
00391
00392 if ( dataProvider->isValid() )
00393 {
00394 delete myLib;
00395 return dataProvider;
00396 }
00397 else
00398 {
00399
00400
00401 QgsDebugMsg( "Invalid data provider" );
00402
00403 myLib->unload();
00404 delete myLib;
00405 return 0;
00406 }
00407 }
00408 else
00409 {
00410 QgsMessageLog::logMessage( QObject::tr( "Unable to instantiate the data provider plugin %1" ).arg( lib ) );
00411
00412 delete dataProvider;
00413
00414 myLib->unload();
00415 delete myLib;
00416 return 0;
00417 }
00418 }
00419 }
00420 else
00421 {
00422 QgsMessageLog::logMessage( QObject::tr( "Failed to load %1: %2" ).arg( lib ).arg( myLib->errorString() ) );
00423 delete myLib;
00424 return 0;
00425 }
00426
00427 QgsDebugMsg( "exiting" );
00428
00429 return 0;
00430
00431 }
00432
00433
00434 typedef QWidget * selectFactoryFunction_t( QWidget * parent, Qt::WFlags fl );
00435
00436 QWidget* QgsProviderRegistry::selectWidget( const QString & providerKey,
00437 QWidget * parent, Qt::WFlags fl )
00438 {
00439 QLibrary *myLib = providerLibrary( providerKey );
00440 if ( !myLib )
00441 return 0;
00442
00443 selectFactoryFunction_t * selectFactory =
00444 ( selectFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "selectWidget" ) );
00445
00446 if ( !selectFactory )
00447 return 0;
00448
00449 return selectFactory( parent, fl );
00450 }
00451
00452
00453 void * QgsProviderRegistry::function( QString const & providerKey,
00454 QString const & functionName )
00455 {
00456 QString lib = library( providerKey );
00457
00458 QLibrary* myLib = new QLibrary( lib );
00459
00460 QgsDebugMsg( "Library name is " + myLib->fileName() );
00461
00462 bool loaded = myLib->load();
00463
00464 if ( loaded )
00465 {
00466 void * ptr = myLib->resolve( functionName.toAscii().data() );
00467 delete myLib;
00468 return ptr;
00469 }
00470 delete myLib;
00471 return 0;
00472 }
00473
00474 QLibrary *QgsProviderRegistry::providerLibrary( QString const & providerKey ) const
00475 {
00476 QString lib = library( providerKey );
00477
00478 QLibrary *myLib = new QLibrary( lib );
00479
00480 QgsDebugMsg( "Library name is " + myLib->fileName() );
00481
00482 bool loaded = myLib->load();
00483
00484 if ( loaded )
00485 {
00486 return myLib;
00487 }
00488 delete myLib;
00489 return 0;
00490 }
00491
00492 QString QgsProviderRegistry::fileVectorFilters() const
00493 {
00494 return mVectorFileFilters;
00495 }
00496
00497 QString QgsProviderRegistry::databaseDrivers() const
00498 {
00499 return mDatabaseDrivers;
00500 }
00501
00502 QString QgsProviderRegistry::directoryDrivers() const
00503 {
00504 return mDirectoryDrivers;
00505 }
00506
00507 QString QgsProviderRegistry::protocolDrivers() const
00508 {
00509 return mProtocolDrivers;
00510 }
00511
00512
00513 QStringList QgsProviderRegistry::providerList() const
00514 {
00515 QStringList lst;
00516 for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); it++ )
00517 {
00518 lst.append( it->first );
00519 }
00520 return lst;
00521 }
00522
00523
00524 const QgsProviderMetadata* QgsProviderRegistry::providerMetadata( const QString& providerKey ) const
00525 {
00526 return findMetadata_( mProviders, providerKey );
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536