~ubuntu-branches/ubuntu/wily/qgis/wily

« back to all changes in this revision

Viewing changes to src/core/qgsproviderregistry.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 *   (at your option) any later version.                                   *
16
16
 *                                                                         *
17
17
 ***************************************************************************/
18
 
 /* $Id: qgsproviderregistry.cpp 5757 2006-09-03 16:35:41Z mhugent $ */
 
18
/* $Id$ */
19
19
 
20
20
#include "qgsproviderregistry.h"
21
21
 
22
22
#include <iostream>
23
23
 
24
 
using namespace std;
25
 
 
26
 
#include <QMessageBox>
27
24
#include <QString>
28
25
#include <QDir>
29
26
#include <QLibrary>
30
 
#include <QApplication>
31
27
 
32
28
 
33
29
#include "qgis.h"
34
30
#include "qgsdataprovider.h"
35
31
#include "qgslogger.h"
 
32
#include "qgsmessageoutput.h"
36
33
#include "qgsprovidermetadata.h"
37
34
 
38
35
 
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();
44
44
 
45
45
QgsProviderRegistry *QgsProviderRegistry::_instance = 0;
46
46
 
47
 
QgsProviderRegistry *QgsProviderRegistry::instance(QString pluginPath)
 
47
QgsProviderRegistry *QgsProviderRegistry::instance( QString pluginPath )
48
48
{
49
 
    if (_instance == 0)
50
 
    {
51
 
        _instance = new QgsProviderRegistry(pluginPath);
52
 
    }
 
49
  if ( _instance == 0 )
 
50
  {
 
51
    _instance = new QgsProviderRegistry( pluginPath );
 
52
  }
53
53
 
54
 
    return _instance;
 
54
  return _instance;
55
55
 
56
56
} // QgsProviderRegistry::instance
57
57
 
58
58
 
59
59
 
60
 
QgsProviderRegistry::QgsProviderRegistry(QString pluginPath)
 
60
QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )
61
61
{
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 );
76
76
 
77
77
#ifdef WIN32
78
 
  mLibraryDirectory.setNameFilter( "*.dll" );
 
78
  mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
79
79
#else
80
 
  mLibraryDirectory.setNameFilter( "*.so" );
81
 
#endif
82
 
 
83
 
#ifdef QGISDEBUG
84
 
  QgsLogger::debug("Checking " + mLibraryDirectory.path() + " for provider plugins\n", 1, __FILE__, __FUNCTION__, __LINE__);
85
 
#endif
86
 
 
87
 
  if (mLibraryDirectory.count() == 0)
 
80
  mLibraryDirectory.setNameFilters( QStringList( "*.so" ) );
 
81
#endif
 
82
 
 
83
  QgsDebugMsg( QString( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ) );
 
84
 
 
85
  if ( mLibraryDirectory.count() == 0 )
88
86
  {
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);
94
 
  } 
 
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" );
 
89
 
 
90
    QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
 
91
    output->setTitle( QObject::tr( "No Data Providers" ) );
 
92
    output->setMessage( msg, QgsMessageOutput::MessageText );
 
93
    output->showMessage();
 
94
  }
95
95
  else
96
96
  {
97
97
    const QFileInfoList list = mLibraryDirectory.entryInfoList();
98
98
    QListIterator<QFileInfo> it( list );
99
99
    QFileInfo fi;
100
100
 
101
 
    while (it.hasNext())
 
101
    while ( it.hasNext() )
102
102
    {
103
103
      fi = it.next();
104
 
        
 
104
 
105
105
      QLibrary *myLib = new QLibrary( fi.filePath() );
106
106
 
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() + " : " ;
108
110
 
109
 
      if (loaded)
 
111
      if ( loaded )
110
112
      {
111
 
#ifdef QGISDEBUG
112
 
        QgsLogger::debug("Checking  " + myLib->library(), 1, __FILE__, __FUNCTION__, __LINE__);
113
 
#endif
114
113
        // get the description and the key for the provider plugin
115
 
        isprovider_t *isProvider = (isprovider_t *) myLib->resolve("isProvider");
116
 
 
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");
120
 
 
121
 
        if (!hasType && isProvider)
 
114
        isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib->resolve( "isProvider" ) );
 
115
 
 
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" ) );
 
119
 
 
120
        if ( !hasType && isProvider )
122
121
        {
123
122
          // check to see if this is a provider plugin
124
 
          if (isProvider())
125
 
            {
 
123
          if ( isProvider() )
 
124
          {
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");
129
 
            if (pDesc && pKey)
 
126
            description_t *pDesc = ( description_t * ) cast_to_fptr( myLib->resolve( "description" ) );
 
127
            providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib->resolve( "providerKey" ) );
 
128
            if ( pDesc && pKey )
130
129
            {
131
130
              // add this provider to the provider map
132
 
              mProviders[pKey()] = 
133
 
                new QgsProviderMetadata(pKey(), pDesc(), myLib->library());
134
 
#ifdef QGISDEBUG
135
 
              QgsDebugMsg("Loaded " + pDesc());
136
 
#endif
 
131
              mProviders[pKey()] =
 
132
                new QgsProviderMetadata( pKey(), pDesc(), myLib->fileName() );
 
133
              //myMessage += "Loaded " + QString(pDesc()) + " ok";
137
134
 
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 )
 
142
              {
 
143
                mDatabaseDrivers = pDatabaseDrivers();
 
144
              }
 
145
              //load directory drivers
 
146
              directoryDrivers_t *pDirectoryDrivers =
 
147
                ( directoryDrivers_t * ) cast_to_fptr( myLib->resolve( "directoryDrivers" ) );
 
148
              if ( pDirectoryDrivers )
 
149
              {
 
150
                mDirectoryDrivers = pDirectoryDrivers();
 
151
              }
 
152
              //load protocol drivers
 
153
              protocolDrivers_t *pProtocolDrivers =
 
154
                ( protocolDrivers_t * ) cast_to_fptr( myLib->resolve( "protocolDrivers" ) );
 
155
              if ( pProtocolDrivers )
 
156
              {
 
157
                mProtocolDrivers = pProtocolDrivers();
 
158
              }
141
159
 
142
160
              if ( pFileVectorFilters )
143
161
              {
144
162
                QString vectorFileFilters = pFileVectorFilters();
145
163
 
146
 
 
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" ) );
150
167
 
151
168
                if ( pVectorFileFilters )
152
169
                {
155
172
                  if ( ! fileVectorFilters.isEmpty() )
156
173
                  {
157
174
                    mVectorFileFilters += fileVectorFilters;
 
175
                    myMessage += QString( "... loaded ok (and with %1 file filters)" ).
 
176
                                 arg( fileVectorFilters.split( ";;" ).count() );
158
177
                  }
159
178
                  else
160
179
                  {
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)";
162
182
                  }
163
183
                }
164
 
              } 
 
184
              }
165
185
              else
166
186
              {
167
 
                QgsDebugMsg("Unable to invoke fileVectorFilters()");
 
187
                //myMessage += ", but unable to invoke fileVectorFilters()";
 
188
                myMessage += "... loaded ok (null file filters)";
168
189
              }
169
190
            }
170
191
            else
171
192
            {
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";
 
195
 
173
196
            }
174
197
          }
175
198
          else
176
199
          {
177
 
            QgsDebugMsg("Unable to invoke fileVectorFilters()");
 
200
            //myMessage += ", but this is not a valid provider, skipping.";
 
201
            myMessage += "..invalid";
178
202
          }
179
 
        } 
 
203
        }
180
204
        else
181
205
        {
182
 
#ifdef QGISDEBUG
183
 
          QgsDebugMsg(myLib->library() + " is not a provider");
184
 
#endif
 
206
          //myMessage += ", but this is not a valid provider or has no type, skipping.";
 
207
          myMessage += "..invalid (no type)";
185
208
        }
186
209
      }
 
210
      else
 
211
      {
 
212
        myMessage += "...invalid (lib not loadable)";
 
213
      }
187
214
 
188
 
      //++it;
 
215
      QgsDebugMsg( myMessage );
189
216
 
190
217
      delete myLib;
191
218
    }
194
221
} // QgsProviderRegistry ctor
195
222
 
196
223
 
 
224
QgsProviderRegistry::~QgsProviderRegistry()
 
225
{
 
226
}
 
227
 
197
228
 
198
229
/** convenience function for finding any existing data providers that match "providerKey"
199
230
 
206
237
QgsProviderMetadata * findMetadata_( QgsProviderRegistry::Providers const & metaData,
207
238
                                     QString const & providerKey )
208
239
{
209
 
  QgsProviderRegistry::Providers::const_iterator i = 
 
240
  QgsProviderRegistry::Providers::const_iterator i =
210
241
    metaData.find( providerKey );
211
242
 
212
243
  if ( i != metaData.end() )
219
250
 
220
251
 
221
252
 
222
 
QString QgsProviderRegistry::library(QString const & providerKey) const
 
253
QString QgsProviderRegistry::library( QString const & providerKey ) const
223
254
{
224
255
  QgsProviderMetadata * md = findMetadata_( mProviders, providerKey );
225
256
 
226
 
  if (md)
 
257
  if ( md )
227
258
  {
228
259
    return md->library();
229
260
  }
232
263
}
233
264
 
234
265
 
235
 
QString QgsProviderRegistry::pluginList(bool asHTML) const
 
266
QString QgsProviderRegistry::pluginList( bool asHTML ) const
236
267
{
237
268
  Providers::const_iterator it = mProviders.begin();
238
269
  QString list;
239
270
 
240
271
  if ( mProviders.empty() )
241
272
  {
242
 
    list = QObject::tr("No data provider plugins are available. No vector layers can be loaded");
243
 
  } 
 
273
    list = QObject::tr( "No data provider plugins are available. No vector layers can be loaded" );
 
274
  }
244
275
  else
245
276
  {
246
 
    if (asHTML)
 
277
    if ( asHTML )
247
278
    {
248
279
      list += "<ol>";
249
280
    }
250
 
    while (it != mProviders.end())
 
281
    while ( it != mProviders.end() )
251
282
    {
252
 
      QgsProviderMetadata *mp = (*it).second;
 
283
      QgsProviderMetadata *mp = ( *it ).second;
253
284
 
254
 
      if (asHTML)
 
285
      if ( asHTML )
255
286
      {
256
287
        list += "<li>" + mp->description() + "<br>";
257
 
      } 
 
288
      }
258
289
      else
259
290
      {
260
291
        list += mp->description() + "\n";
262
293
 
263
294
      it++;
264
295
    }
265
 
    if (asHTML)
 
296
    if ( asHTML )
266
297
    {
267
298
      list += "</ol>";
268
299
    }
272
303
}
273
304
 
274
305
 
275
 
void QgsProviderRegistry::setLibraryDirectory(QDir const & path)
 
306
void QgsProviderRegistry::setLibraryDirectory( QDir const & path )
276
307
{
277
 
    mLibraryDirectory = path;
 
308
  mLibraryDirectory = path;
278
309
}
279
310
 
280
311
 
281
312
QDir const & QgsProviderRegistry::libraryDirectory() const
282
313
{
283
 
    return mLibraryDirectory;
 
314
  return mLibraryDirectory;
284
315
}
285
316
 
286
317
 
287
318
 
288
319
// typedef for the QgsDataProvider class factory
289
320
typedef QgsDataProvider * classFactoryFunction_t( const QString * );
290
 
 
291
 
 
292
 
 
293
 
/** Copied from QgsVectorLayer::setDataProvider 
 
321
 
 
322
 
 
323
 
 
324
/** Copied from QgsVectorLayer::setDataProvider
294
325
 *  TODO: Make it work in the generic environment
295
326
 *
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.
299
330
 */
300
 
QgsDataProvider* QgsProviderRegistry::getProvider( QString const & providerKey, 
301
 
                                                   QString const & dataSource )
 
331
QgsDataProvider* QgsProviderRegistry::getProvider( QString const & providerKey,
 
332
    QString const & dataSource )
302
333
{
303
334
  // XXX should I check for and possibly delete any pre-existing providers?
304
335
  // XXX How often will that scenario occur?
305
336
 
306
 
#ifdef QGISDEBUG
307
 
    const char * providerStr = providerKey.ascii(); // debugger probe
308
 
    const char * dataSourceStr = dataSource.ascii(); // ditto
309
 
#endif
310
 
 
311
337
  // load the plugin
312
 
  QString lib = library(providerKey);
 
338
  QString lib = library( providerKey );
313
339
 
314
340
#ifdef TESTPROVIDERLIB
315
 
  const char *cLib = (const char *) lib;
 
341
  const char *cLib = lib.toUtf8();
316
342
 
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);
320
 
  if (!handle)
 
345
  void *handle = dlopen( cOgrLib, RTLD_LAZY | RTLD_GLOBAL );
 
346
  if ( !handle )
321
347
  {
322
 
    QgsLogger::warning("Error in dlopen");
 
348
    QgsLogger::warning( "Error in dlopen" );
323
349
  }
324
350
  else
325
351
  {
326
 
    QgsDebugMsg("dlopen suceeded");
327
 
    dlclose(handle);
 
352
    QgsDebugMsg( "dlopen suceeded" );
 
353
    dlclose( handle );
328
354
  }
329
355
 
330
356
#endif
331
357
 
332
358
  // load the data provider
333
 
  QLibrary* myLib = new QLibrary((const char *) lib);
 
359
  QLibrary* myLib = new QLibrary( lib );
334
360
 
335
 
#ifdef QGISDEBUG
336
 
  QgsDebugMsg("QgsProviderRegistry::getRasterProvider: Library name is " + myLib->library());
337
 
#endif
 
361
  QgsDebugMsg( "Library name is " + myLib->fileName() );
338
362
 
339
363
  bool loaded = myLib->load();
340
364
 
341
 
  if (loaded)
 
365
  if ( loaded )
342
366
  {
343
 
      QgsDebugMsg( "Loaded data provider library" );
344
 
      QgsDebugMsg( "Attempting to resolve the classFactory function" );
345
 
 
346
 
      classFactoryFunction_t * classFactory = 
347
 
          (classFactoryFunction_t *) myLib->resolve("classFactory");
348
 
 
349
 
    if (classFactory)
 
367
    QgsDebugMsg( "Loaded data provider library" );
 
368
    QgsDebugMsg( "Attempting to resolve the classFactory function" );
 
369
 
 
370
    classFactoryFunction_t * classFactory =
 
371
      ( classFactoryFunction_t * ) cast_to_fptr( myLib->resolve( "classFactory" ) );
 
372
 
 
373
    if ( classFactory )
350
374
    {
351
375
      QgsDebugMsg( "Getting pointer to a dataProvider object from the library" );
352
376
 
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())));
357
 
 
358
 
      QgsDataProvider * dataProvider = (*classFactory)(&dataSource);
359
 
 
360
 
      if (dataProvider)
 
379
      //      QgsDataProvider* dataProvider = (QgsDataProvider*)
 
380
      //      (classFactory((const char*)(dataSource.utf8())));
 
381
 
 
382
      QgsDataProvider * dataProvider = ( *classFactory )( &dataSource );
 
383
 
 
384
      if ( dataProvider )
361
385
      {
362
 
#ifdef QGISDEBUG
363
386
        QgsDebugMsg( "Instantiated the data provider plugin" );
364
 
        QgsDebugMsg("provider name: " + dataProvider->name());
365
 
#endif
366
 
        if (dataProvider->isValid())
 
387
        QgsDebugMsg( "provider name: " + dataProvider->name() );
 
388
 
 
389
        if ( dataProvider->isValid() )
367
390
        {
368
 
          delete myLib;
 
391
          delete myLib;
369
392
          return dataProvider;
370
393
        }
371
394
        else
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" );
375
398
 
376
 
            myLib->unload();
377
 
            delete myLib;
378
 
            return 0;
 
399
          myLib->unload();
 
400
          delete myLib;
 
401
          return 0;
379
402
        }
380
403
      }
381
404
      else
383
406
        QgsLogger::warning( "Unable to instantiate the data provider plugin" );
384
407
 
385
408
        myLib->unload();
386
 
        delete myLib;
 
409
        delete myLib;
387
410
        return 0;
388
411
      }
389
412
    }
390
413
  }
391
414
  else
392
415
  {
393
 
    QgsLogger::warning( "Failed to load ../providers/libproviders.so" );
 
416
    QgsLogger::warning( "Failed to load " + lib );
394
417
    delete myLib;
395
418
    return 0;
396
419
  }
397
 
  
 
420
 
398
421
  QgsDebugMsg( "exiting" );
399
422
 
400
423
  return 0;  // factory didn't exist
401
 
  
 
424
 
402
425
} // QgsProviderRegistry::setDataProvider
403
426
 
404
 
 
405
 
 
406
 
 
407
 
 
408
427
QString QgsProviderRegistry::fileVectorFilters() const
409
428
{
410
 
    return mVectorFileFilters;
411
 
} //  QgsProviderRegistry::fileVectorFilters
412
 
 
413
 
 
414
 
 
415
 
 
416
 
QgsDataProvider * 
 
429
  return mVectorFileFilters;
 
430
}
 
431
 
 
432
QString QgsProviderRegistry::databaseDrivers() const
 
433
{
 
434
  return mDatabaseDrivers;
 
435
}
 
436
 
 
437
QString QgsProviderRegistry::directoryDrivers() const
 
438
{
 
439
  return mDirectoryDrivers;
 
440
}
 
441
 
 
442
QString QgsProviderRegistry::protocolDrivers() const
 
443
{
 
444
  return mProtocolDrivers;
 
445
}
 
446
 
 
447
 
 
448
QStringList QgsProviderRegistry::providerList() const
 
449
{
 
450
  QStringList lst;
 
451
  for ( Providers::const_iterator it = mProviders.begin(); it != mProviders.end(); it++ )
 
452
  {
 
453
    lst.append( it->first );
 
454
  }
 
455
  return lst;
 
456
}
 
457
 
 
458
 
 
459
const QgsProviderMetadata* QgsProviderRegistry::providerMetadata( const QString& providerKey ) const
 
460
{
 
461
  return findMetadata_( mProviders, providerKey );
 
462
}
 
463
 
 
464
 
 
465
/*
 
466
QgsDataProvider *
417
467
QgsProviderRegistry::openVector( QString const & dataSource, QString const & providerKey )
418
468
{
419
469
    return getProvider( providerKey, dataSource );
420
470
} // QgsProviderRegistry::openVector
 
471
*/