QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )
{
  // At startup, examine the libs in the qgis/lib dir and store those that
  // are a provider shared lib
  // check all libs in the current plugin directory and get name and descriptions
  //TODO figure out how to register and identify data source plugin for a specific
  //TODO layer type
#if 0
  char **argv = qApp->argv();
  QString appDir = argv[0];
  int bin = appDir.findRev( "/bin", -1, false );
  QString baseDir = appDir.left( bin );
  QString mLibraryDirectory = baseDir + "/lib";
#endif
  mLibraryDirectory = pluginPath;
  mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
  mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );

#if defined(WIN32) || defined(__CYGWIN__)
  mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
#elif ANDROID
  mLibraryDirectory.setNameFilters( QStringList( "*provider.so" ) );
#else
  mLibraryDirectory.setNameFilters( QStringList( "*.so" ) );
#endif

  QgsDebugMsg( QString( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ) );

  if ( mLibraryDirectory.count() == 0 )
  {
    QString msg = QObject::tr( "No QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
    msg += QObject::tr( "No vector layers can be loaded. Check your QGIS installation" );

    QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
    output->setTitle( QObject::tr( "No Data Providers" ) );
    output->setMessage( msg, QgsMessageOutput::MessageText );
    output->showMessage();
    return;
  }

  QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );
  while ( it.hasNext() )
  {
    QFileInfo fi( it.next() );

    QLibrary myLib( fi.filePath() );
    if ( !myLib.load() )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName() ).arg( myLib.errorString() ) );
      continue;
    }

    //MH: Added a further test to detect non-provider plugins linked to provider plugins.
    //Only pure provider plugins have 'type' not defined
    isprovider_t *hasType = ( isprovider_t * ) cast_to_fptr( myLib.resolve( "type" ) );
    if ( hasType )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (has type method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // get the description and the key for the provider plugin
    isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib.resolve( "isProvider" ) );
    if ( !isProvider )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no isProvider method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // check to see if this is a provider plugin
    if ( !isProvider() )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (not a provider)" ).arg( myLib.fileName() ) );
      continue;
    }

    // looks like a provider. get the key and description
    description_t *pDesc = ( description_t * ) cast_to_fptr( myLib.resolve( "description" ) );
    if ( !pDesc )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no description method)" ).arg( myLib.fileName() ) );
      continue;
    }

    providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib.resolve( "providerKey" ) );
    if ( !pKey )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no providerKey method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // add this provider to the provider map
    mProviders[pKey()] = new QgsProviderMetadata( pKey(), pDesc(), myLib.fileName() );

    // load database drivers
    databaseDrivers_t *pDatabaseDrivers = ( databaseDrivers_t * ) cast_to_fptr( myLib.resolve( "databaseDrivers" ) );
    if ( pDatabaseDrivers )
    {
      mDatabaseDrivers = pDatabaseDrivers();
    }

    // load directory drivers
    directoryDrivers_t *pDirectoryDrivers = ( directoryDrivers_t * ) cast_to_fptr( myLib.resolve( "directoryDrivers" ) );
    if ( pDirectoryDrivers )
    {
      mDirectoryDrivers = pDirectoryDrivers();
    }

    // load protocol drivers
    protocolDrivers_t *pProtocolDrivers = ( protocolDrivers_t * ) cast_to_fptr( myLib.resolve( "protocolDrivers" ) );
    if ( pProtocolDrivers )
    {
      mProtocolDrivers = pProtocolDrivers();
    }

    // now get vector file filters, if any
    fileVectorFilters_t *pFileVectorFilters = ( fileVectorFilters_t * ) cast_to_fptr( myLib.resolve( "fileVectorFilters" ) );
    if ( pFileVectorFilters )
    {
      QString fileVectorFilters = pFileVectorFilters();

      if ( !fileVectorFilters.isEmpty() )
        mVectorFileFilters += fileVectorFilters;

      QgsDebugMsg( QString( "Checking %1: ...loaded ok (%2 file filters)" ).arg( myLib.fileName() ).arg( fileVectorFilters.split( ";;" ).count() ) );
    }

    // now get raster file filters, if any
    // this replaces deprecated QgsRasterLayer::buildSupportedRasterFileFilter
    buildsupportedrasterfilefilter_t *pBuild =
      ( buildsupportedrasterfilefilter_t * ) cast_to_fptr( myLib.resolve( "buildSupportedRasterFileFilter" ) );
    if ( pBuild )
    {
      QString fileRasterFilters;
      pBuild( fileRasterFilters );

      QgsDebugMsg( "raster filters: " + fileRasterFilters );
      if ( !fileRasterFilters.isEmpty() )
        mRasterFileFilters += fileRasterFilters;

      QgsDebugMsg( QString( "Checking %1: ...loaded ok (%2 file filters)" ).arg( myLib.fileName() ).arg( fileRasterFilters.split( ";;" ).count() ) );
    }
  }
} // QgsProviderRegistry ctor
Exemple #2
0
void QgsProviderRegistry::init()
{
  // add standard providers
  mProviders[ QgsMemoryProvider::providerKey() ] = new QgsProviderMetadata( QgsMemoryProvider::providerKey(), QgsMemoryProvider::providerDescription(), &QgsMemoryProvider::createProvider );

  mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
  mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );

#if defined(Q_OS_WIN) || defined(__CYGWIN__)
  mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
#elif defined(ANDROID)
  mLibraryDirectory.setNameFilters( QStringList( "*provider.so" ) );
#else
  mLibraryDirectory.setNameFilters( QStringList( QStringLiteral( "*.so" ) ) );
#endif

  QgsDebugMsg( QString( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ) );

  if ( mLibraryDirectory.count() == 0 )
  {
    QString msg = QObject::tr( "No QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
    msg += QObject::tr( "No vector layers can be loaded. Check your QGIS installation" );

    QgsMessageOutput *output = QgsMessageOutput::createMessageOutput();
    output->setTitle( QObject::tr( "No Data Providers" ) );
    output->setMessage( msg, QgsMessageOutput::MessageText );
    output->showMessage();
    return;
  }

  // provider file regex pattern, only files matching the pattern are loaded if the variable is defined
  QString filePattern = getenv( "QGIS_PROVIDER_FILE" );
  QRegExp fileRegexp;
  if ( !filePattern.isEmpty() )
  {
    fileRegexp.setPattern( filePattern );
  }

  Q_FOREACH ( const QFileInfo &fi, mLibraryDirectory.entryInfoList() )
  {
    if ( !fileRegexp.isEmpty() )
    {
      if ( fileRegexp.indexIn( fi.fileName() ) == -1 )
      {
        QgsDebugMsg( "provider " + fi.fileName() + " skipped because doesn't match pattern " + filePattern );
        continue;
      }
    }

    QLibrary myLib( fi.filePath() );
    if ( !myLib.load() )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName(), myLib.errorString() ) );
      continue;
    }

    //MH: Added a further test to detect non-provider plugins linked to provider plugins.
    //Only pure provider plugins have 'type' not defined
    isprovider_t *hasType = reinterpret_cast< isprovider_t * >( cast_to_fptr( myLib.resolve( "type" ) ) );
    if ( hasType )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (has type method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // get the description and the key for the provider plugin
    isprovider_t *isProvider = reinterpret_cast< isprovider_t * >( cast_to_fptr( myLib.resolve( "isProvider" ) ) );
    if ( !isProvider )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no isProvider method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // check to see if this is a provider plugin
    if ( !isProvider() )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (not a provider)" ).arg( myLib.fileName() ) );
      continue;
    }

    // looks like a provider. get the key and description
    description_t *pDesc = reinterpret_cast< description_t * >( cast_to_fptr( myLib.resolve( "description" ) ) );
    if ( !pDesc )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no description method)" ).arg( myLib.fileName() ) );
      continue;
    }

    providerkey_t *pKey = reinterpret_cast< providerkey_t * >( cast_to_fptr( myLib.resolve( "providerKey" ) ) );
    if ( !pKey )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no providerKey method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // add this provider to the provider map
    mProviders[pKey()] = new QgsProviderMetadata( pKey(), pDesc(), myLib.fileName() );

    // load database drivers
    databaseDrivers_t *pDatabaseDrivers = reinterpret_cast< databaseDrivers_t * >( cast_to_fptr( myLib.resolve( "databaseDrivers" ) ) );
    if ( pDatabaseDrivers )
    {
      mDatabaseDrivers = pDatabaseDrivers();
    }

    // load directory drivers
    directoryDrivers_t *pDirectoryDrivers = reinterpret_cast< directoryDrivers_t * >( cast_to_fptr( myLib.resolve( "directoryDrivers" ) ) );
    if ( pDirectoryDrivers )
    {
      mDirectoryDrivers = pDirectoryDrivers();
    }

    // load protocol drivers
    protocolDrivers_t *pProtocolDrivers = reinterpret_cast< protocolDrivers_t * >( cast_to_fptr( myLib.resolve( "protocolDrivers" ) ) );
    if ( pProtocolDrivers )
    {
      mProtocolDrivers = pProtocolDrivers();
    }

    // now get vector file filters, if any
    fileVectorFilters_t *pFileVectorFilters = reinterpret_cast< fileVectorFilters_t * >( cast_to_fptr( myLib.resolve( "fileVectorFilters" ) ) );
    if ( pFileVectorFilters )
    {
      QString fileVectorFilters = pFileVectorFilters();

      if ( !fileVectorFilters.isEmpty() )
        mVectorFileFilters += fileVectorFilters;

      QgsDebugMsg( QString( "Checking %1: ...loaded OK (%2 file filters)" ).arg( myLib.fileName() ).arg( fileVectorFilters.split( ";;" ).count() ) );
    }

    // now get raster file filters, if any
    // this replaces deprecated QgsRasterLayer::buildSupportedRasterFileFilter
    buildsupportedrasterfilefilter_t *pBuild =
      reinterpret_cast< buildsupportedrasterfilefilter_t * >( cast_to_fptr( myLib.resolve( "buildSupportedRasterFileFilter" ) ) );
    if ( pBuild )
    {
      QString fileRasterFilters;
      pBuild( fileRasterFilters );

      QgsDebugMsg( "raster filters: " + fileRasterFilters );
      if ( !fileRasterFilters.isEmpty() )
        mRasterFileFilters += fileRasterFilters;

      QgsDebugMsg( QString( "Checking %1: ...loaded OK (%2 file filters)" ).arg( myLib.fileName() ).arg( fileRasterFilters.split( ";;" ).count() ) );
    }
  }
} // QgsProviderRegistry ctor
QgsAuthMethodRegistry::QgsAuthMethodRegistry( const QString& pluginPath )
{
  // At startup, examine the libs in the qgis/lib dir and store those that
  // are an auth method shared lib
  // check all libs in the current plugin directory and get name and descriptions
#if 0
  char **argv = qApp->argv();
  QString appDir = argv[0];
  int bin = appDir.findRev( "/bin", -1, false );
  QString baseDir = appDir.left( bin );
  QString mLibraryDirectory = baseDir + "/lib";
#endif
  mLibraryDirectory = pluginPath;
  mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
  mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );

#if defined(Q_OS_WIN) || defined(__CYGWIN__)
  mLibraryDirectory.setNameFilters( QStringList( "*authmethod.dll" ) );
#else
  mLibraryDirectory.setNameFilters( QStringList( "*authmethod.so" ) );
#endif

  QgsDebugMsg( QString( "Checking for auth method plugins in: %1" ).arg( mLibraryDirectory.path() ) );

  if ( mLibraryDirectory.count() == 0 )
  {
    QString msg = QObject::tr( "No QGIS auth method plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
    msg += QObject::tr( "No authentication methods can be used. Check your QGIS installation" );

    QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
    output->setTitle( QObject::tr( "No Authentication Methods" ) );
    output->setMessage( msg, QgsMessageOutput::MessageText );
    output->showMessage();
    return;
  }

  // auth method file regex pattern, only files matching the pattern are loaded if the variable is defined
  QString filePattern = getenv( "QGIS_AUTHMETHOD_FILE" );
  QRegExp fileRegexp;
  if ( !filePattern.isEmpty() )
  {
    fileRegexp.setPattern( filePattern );
  }

  QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );
  while ( it.hasNext() )
  {
    QFileInfo fi( it.next() );

    if ( !fileRegexp.isEmpty() )
    {
      if ( fileRegexp.indexIn( fi.fileName() ) == -1 )
      {
        QgsDebugMsg( "auth method " + fi.fileName() + " skipped because doesn't match pattern " + filePattern );
        continue;
      }
    }

    QLibrary myLib( fi.filePath() );
    if ( !myLib.load() )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName(), myLib.errorString() ) );
      continue;
    }

    // get the description and the key for the auth method plugin
    isauthmethod_t *isAuthMethod = ( isauthmethod_t * ) cast_to_fptr( myLib.resolve( "isAuthMethod" ) );
    if ( !isAuthMethod )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no isAuthMethod method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // check to see if this is an auth method plugin
    if ( !isAuthMethod() )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (not an auth method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // looks like an auth method plugin. get the key and description
    description_t *pDesc = ( description_t * ) cast_to_fptr( myLib.resolve( "description" ) );
    if ( !pDesc )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no description method)" ).arg( myLib.fileName() ) );
      continue;
    }

    methodkey_t *pKey = ( methodkey_t * ) cast_to_fptr( myLib.resolve( "authMethodKey" ) );
    if ( !pKey )
    {
      QgsDebugMsg( QString( "Checking %1: ...invalid (no authMethodKey method)" ).arg( myLib.fileName() ) );
      continue;
    }

    // add this auth method to the method map
    mAuthMethods[pKey()] = new QgsAuthMethodMetadata( pKey(), pDesc(), myLib.fileName() );

  }
}
void QgsPluginManager::getPluginDescriptions()
{
  QString sharedLibExtension;
#ifdef WIN32
  sharedLibExtension = "*.dll";
#else
  sharedLibExtension = "*.so*";
#endif

  // check all libs in the current ans user plugins directories, and get name and descriptions
  QSettings settings;
  QStringList myPathList( lblPluginDir->text() );
  QString myPaths = settings.value( "plugins/searchPathsForPlugins", "" ).toString();
  if ( !myPaths.isEmpty() )
  {
    myPathList.append( myPaths.split( "|" ) );
  }

  for ( int j = 0; j < myPathList.size(); ++j )
  {
    QString myPluginDir = myPathList.at( j );
    QDir pluginDir( myPluginDir, sharedLibExtension, QDir::Name | QDir::IgnoreCase, QDir::Files | QDir::NoSymLinks );

    if ( pluginDir.count() == 0 )
    {
      QMessageBox::information( this, tr( "No Plugins" ), tr( "No QGIS plugins found in %1" ).arg( myPluginDir ) );
      return;
    }

    QgsDebugMsg( "PLUGIN MANAGER:" );
    for ( uint i = 0; i < pluginDir.count(); i++ )
    {
      QString lib = QString( "%1/%2" ).arg( myPluginDir ).arg( pluginDir[i] );

#ifdef TESTLIB
      // This doesn't work on WIN32 and causes problems with plugins
      // on OS X (the code doesn't cause a problem but including dlfcn.h
      // renders plugins unloadable)
#if !defined(WIN32) && !defined(Q_OS_MACX)
      // test code to help debug loading problems
      // This doesn't work on WIN32 and causes problems with plugins
      // on OS X (the code doesn't cause a problem but including dlfcn.h
      // renders plugins unloadable)

      //void *handle = dlopen((const char *) lib, RTLD_LAZY);
      void *handle = dlopen( lib.toLocal8Bit().data(), RTLD_LAZY | RTLD_GLOBAL );
      if ( !handle )
      {
        QgsDebugMsg( "Error in dlopen: " );
        QgsDebugMsg( dlerror() );
      }
      else
      {
        QgsDebugMsg( "dlopen suceeded for " + lib );
        dlclose( handle );
      }
#endif //#ifndef WIN32 && Q_OS_MACX
#endif //#ifdef TESTLIB

      QgsDebugMsg( "Examining: " + lib );
      QLibrary *myLib = new QLibrary( lib );
      bool loaded = myLib->load();
      if ( !loaded )
      {
        QgsDebugMsg( QString( "Failed to load: %1 (%2)" ).arg( myLib->fileName() ).arg( myLib->errorString() ) );
        delete myLib;
        continue;
      }

      QgsDebugMsg( "Loaded library: " + myLib->fileName() );

      // Don't bother with libraries that are providers
      //if(!myLib->resolve("isProvider"))

      //MH: Replaced to allow for plugins that are linked to providers
      //type is only used in non-provider plugins
      if ( !myLib->resolve( "type" ) )
      {
        delete myLib;
        continue;
      }

      // resolve the metadata from plugin
      name_t *pName = ( name_t * ) cast_to_fptr( myLib->resolve( "name" ) );
      description_t *pDesc = ( description_t * ) cast_to_fptr( myLib->resolve( "description" ) );
      category_t *pCat = ( category_t * ) cast_to_fptr( myLib->resolve( "category" ) );
      version_t *pVersion = ( version_t * ) cast_to_fptr( myLib->resolve( "version" ) );
      icon_t* pIcon = ( icon_t * ) cast_to_fptr( myLib->resolve( "icon" ) );

      // show the values (or lack of) for each function
      if ( pName )
      {
        QgsDebugMsg( "Plugin name: " + pName() );
      }
      else
      {
        QgsDebugMsg( "Plugin name not returned when queried" );
      }
      if ( pDesc )
      {
        QgsDebugMsg( "Plugin description: " + pDesc() );
      }
      else
      {
        QgsDebugMsg( "Plugin description not returned when queried" );
      }
      if ( pCat )
      {
        QgsDebugMsg( "Plugin category: " + pCat() );
      }
      else
      {
        QgsDebugMsg( "Plugin category not returned when queried" );
      }
      if ( pVersion )
      {
        QgsDebugMsg( "Plugin version: " + pVersion() );
      }
      else
      {
        QgsDebugMsg( "Plugin version not returned when queried" );
      }
      if ( pIcon )
      {
        QgsDebugMsg( "Plugin icon: " + pIcon() );
      }

      if ( !pName || !pDesc || !pVersion )
      {
        QgsDebugMsg( "Failed to get name, description, or type for " + myLib->fileName() );
        delete myLib;
        continue;
      }

      QString pluginName = pName();
      QString pluginDesc = pDesc();
      // if no category defined - use default value
      QString pluginCat = ( pCat ? pCat() : tr( "Plugins" ) );
      QString pluginVersion = pVersion();
      QString pluginIconFileName = ( pIcon ? pIcon() : QString() );
      QString baseName = QFileInfo( lib ).baseName();

      QString myLibraryName = pluginDir[i];
      // filtering will be done on the display role so give it name and desription
      // user wont see this text since we are using a custome delegate
      QStandardItem * mypDetailItem = new QStandardItem( pluginName + " - " + pluginDesc );
      mypDetailItem->setData( myLibraryName, PLUGIN_LIBRARY_ROLE );
      mypDetailItem->setData( myPluginDir, PLUGIN_DIRECTORY_ROLE );
      mypDetailItem->setData( baseName, PLUGIN_BASE_NAME_ROLE ); //for matching in registry later
      QgsDetailedItemData myData;
      myData.setTitle( pluginName );
      myData.setDetail( pluginDesc );
      myData.setCategory( tr( "Installed in %1 menu/toolbar" ).arg( pluginCat ) );
      myData.setRenderAsWidget( false );
      myData.setCheckable( true );
      myData.setChecked( false ); //start unchecked - we will check it later if needed
      if ( pluginIconFileName.isEmpty() )
        myData.setIcon( QPixmap( QgsApplication::defaultThemePath() + "/plugin.png" ) );
      else
        myData.setIcon( QPixmap( pluginIconFileName ) );

      QgsDebugMsg( "Getting an instance of the QgsPluginRegistry" );

      // check to see if the plugin is loaded and set the checkbox accordingly
      QgsPluginRegistry *pRegistry = QgsPluginRegistry::instance();

      // get the library using the plugin description
      if ( !pRegistry->isLoaded( baseName ) )
      {
        QgsDebugMsg( "Couldn't find plugin in the registry" );
      }
      else
      {
        QgsDebugMsg( "Found plugin in the registry" );
        // TODO: this check shouldn't be necessary, plugin base names must be unique
        if ( pRegistry->library( baseName ) == myLib->fileName() )
        {
          // set the checkbox
          myData.setChecked( true );
        }
      }
      QVariant myVariant = qVariantFromValue( myData );
      mypDetailItem->setData( myVariant, PLUGIN_DATA_ROLE );
      // Add items to model
      mModelPlugins->appendRow( mypDetailItem );

      delete myLib;
    }
  }
}