From c58576e2040e026261758482821554bdb0f16171 Mon Sep 17 00:00:00 2001 From: Tim Sutton Date: Mon, 12 Sep 2011 17:28:45 +0200 Subject: [PATCH] [FEATURE] implement ability to skip specific drivers (fixes #182) --- python/core/qgsapplication.sip | 28 +++++++ src/app/CMakeLists.txt | 1 + src/app/qgisapp.cpp | 3 + src/app/qgsoptions.cpp | 63 ++++++++++++++++ src/app/qgsoptions.h | 10 +++ src/core/qgsapplication.cpp | 42 +++++++++++ src/core/qgsapplication.h | 32 ++++++++ src/providers/gdal/qgsgdalprovider.cpp | 4 + src/ui/qgsoptionsbase.ui | 100 +++++++++++++++++++++---- 9 files changed, 267 insertions(+), 16 deletions(-) diff --git a/python/core/qgsapplication.sip b/python/core/qgsapplication.sip index 4bb950390f6..e0ac2c5f0c2 100644 --- a/python/core/qgsapplication.sip +++ b/python/core/qgsapplication.sip @@ -260,5 +260,33 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv) @note added in 2.0 */ static QString buildOutputPath(); + /** Sets the GDAL_SKIP environment variable to include the specified driver + * and then calls GDALDriverManager::AutoSkipDrivers() to unregister it. The + * driver name should be the short format of the Gdal driver name e.g. GTiff. + * @note added in 2.0 + */ + static void skipGdalDriver( QString theDriver ); + + /** Sets the GDAL_SKIP environment variable to exclude the specified driver + * and then calls GDALDriverManager::AutoSkipDrivers() to unregister it. The + * driver name should be the short format of the Gdal driver name e.g. GTiff. + * @note added in 2.0 + */ + static void restoreGdalDriver( QString theDriver ); + + + /** Returns the list of gdal drivers that should be skipped (based on + * GDAL_SKIP environment variable) + * @note added in 2.0 + */ + static QStringList skippedGdalDrivers( ) const ; + + /** Apply the skipped drivers list to gdal + * @see skipGdalDriver + * @see restoreGdalDriver + * @see skippedGdalDrivers + * @note added in 2.0 */ + static void applyGdalSkippedDrivers(); + }; diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index a9a850a3c83..80aac2e88c0 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -422,6 +422,7 @@ TARGET_LINK_LIBRARIES(${QGIS_APP_NAME} #should only be needed for win ${QT_QTMAIN_LIBRARY} ${QWTPOLAR_LIBRARY} + ${GDAL_LIBRARY} qgis_core qgis_gui qgis_analysis diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 3b82740657f..1ef2ac0f1a5 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -4822,6 +4822,9 @@ void QgisApp::options() //do we need this? TS mMapCanvas->refresh(); + + mRasterFileFilter.clear(); + QgsRasterLayer::buildSupportedRasterFileFilter( mRasterFileFilter ); } delete optionsDialog; diff --git a/src/app/qgsoptions.cpp b/src/app/qgsoptions.cpp index 0dd9c4b8a71..155aee25d01 100644 --- a/src/app/qgsoptions.cpp +++ b/src/app/qgsoptions.cpp @@ -41,6 +41,8 @@ #define ELLIPS_FLAT "NONE" #define ELLIPS_FLAT_DESC "None / Planimetric" +#define CPL_SUPRESS_CPLUSPLUS +#include /** * \class QgsOptions - Set user options and preferences * Constructor @@ -431,6 +433,9 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) : restoreGeometry( settings.value( "/Windows/Options/geometry" ).toByteArray() ); tabWidget->setCurrentIndex( settings.value( "/Windows/Options/row" ).toInt() ); + + loadGdalDriverList(); + } //! Destructor @@ -744,6 +749,10 @@ void QgsOptions::saveOptions() // settings.setValue( "locale/userLocale", cboLocale->currentText() ); settings.setValue( "locale/overrideFlag", grpLocale->isChecked() ); + + + // Gdal skip driver list + saveGdalDriverList(); } @@ -1010,3 +1019,57 @@ void QgsOptions::on_mClearCache_clicked() QgsNetworkAccessManager::instance()->cache()->clear(); #endif } + +void QgsOptions::loadGdalDriverList() +{ + QStringList mySkippedDrivers = QgsApplication::skippedGdalDrivers(); + GDALDriverH myGdalDriver; // current driver + QString myGdalDriverDescription; + QStringList myDrivers; + for ( int i = 0; i < GDALGetDriverCount(); ++i ) + { + myGdalDriver = GDALGetDriver( i ); + + Q_CHECK_PTR( myGdalDriver ); + + if ( !myGdalDriver ) + { + QgsLogger::warning( "unable to get driver " + QString::number( i ) ); + continue; + } + myGdalDriverDescription = GDALGetDescription( myGdalDriver ); + myDrivers << myGdalDriverDescription; + } + QStringListIterator myIterator( myDrivers ); + myDrivers.sort(); + while (myIterator.hasNext()) + { + QString myName = myIterator.next(); + QListWidgetItem * mypItem = new QListWidgetItem( myName ); + if ( mySkippedDrivers.contains( myName ) ) + { + mypItem->setCheckState( Qt::Unchecked ); + } + else + { + mypItem->setCheckState( Qt::Checked ); + } + lstGdalDrivers->addItem( mypItem ); + } +} + +void QgsOptions::saveGdalDriverList() +{ + for ( int i=0; i < lstGdalDrivers->count(); i++ ) + { + QListWidgetItem * mypItem = lstGdalDrivers->item( i ); + if ( mypItem->checkState() == Qt::Unchecked ) + { + QgsApplication::skipGdalDriver( mypItem->text() ); + } + else + { + QgsApplication::restoreGdalDriver( mypItem->text() ); + } + } +} diff --git a/src/app/qgsoptions.h b/src/app/qgsoptions.h index 6761b62846e..1d76f4102c9 100644 --- a/src/app/qgsoptions.h +++ b/src/app/qgsoptions.h @@ -120,6 +120,16 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase void on_mBrowseCacheDirectory_clicked(); void on_mClearCache_clicked(); + /* Load the list of drivers available in GDAL + * @note added in 2.0 + */ + void loadGdalDriverList(); + + /* Save the list of which gdal drivers should be used. + * @note added in 2.0 + */ + void saveGdalDriverList(); + protected: //! Populates combo box with ellipsoids void getEllipsoidList(); diff --git a/src/core/qgsapplication.cpp b/src/core/qgsapplication.cpp index cb6e47e1b1f..2772e85a2d9 100644 --- a/src/core/qgsapplication.cpp +++ b/src/core/qgsapplication.cpp @@ -34,6 +34,7 @@ #include "qgsconfig.h" #include +#include #include // for setting gdal options QObject * QgsApplication::mFileOpenEventReceiver; @@ -49,6 +50,7 @@ QString QgsApplication::mConfigPath = QDir::homePath() + QString( "/.qgis/" ); bool QgsApplication::mRunningFromBuildDir = false; QString QgsApplication::mBuildSourcePath; QString QgsApplication::mBuildOutputPath; +QStringList QgsApplication::mGdalSkipList; /*! \class QgsApplication @@ -711,3 +713,43 @@ QString QgsApplication::relativePathToAbsolutePath( QString rpath, QString targe return targetElems.join( "/" ); } + +void QgsApplication::skipGdalDriver( QString theDriver ) +{ + if ( mGdalSkipList.contains( theDriver ) || theDriver.isEmpty() ) + { + return; + } + mGdalSkipList << theDriver; + applyGdalSkippedDrivers(); +} + +void QgsApplication::restoreGdalDriver( QString theDriver ) +{ + if ( !mGdalSkipList.contains( theDriver ) ) + { + return; + } + int myPos = mGdalSkipList.indexOf( theDriver ); + if ( myPos >= 0 ) + { + mGdalSkipList.removeAt( myPos ); + } + applyGdalSkippedDrivers(); +} + +void QgsApplication::applyGdalSkippedDrivers() +{ + mGdalSkipList.removeDuplicates(); + QString myDriverList = mGdalSkipList.join(" "); + QgsDebugMsg( "Gdal Skipped driver list set to:" ); + QgsDebugMsg( myDriverList ); +#if defined(Q_WS_WIN32) || defined(WIN32) + CPLSetConfigOption("GDAL_SKIP", myDriverList.toUtf8()); +#else + int myChangeFlag = 1; //whether we want to force the env var to change + setenv( "GDAL_SKIP", myDriverList.toUtf8(), myChangeFlag ); +#endif + GDALDriverManager myDriverManager; + myDriverManager.AutoLoadDrivers(); +} diff --git a/src/core/qgsapplication.h b/src/core/qgsapplication.h index 86967004474..fa551ac9ecd 100644 --- a/src/core/qgsapplication.h +++ b/src/core/qgsapplication.h @@ -17,6 +17,7 @@ #include #include +#include #include @@ -223,6 +224,33 @@ class CORE_EXPORT QgsApplication: public QApplication @note added in 2.0 */ static QString buildOutputPath() { return mBuildOutputPath; } + /** Sets the GDAL_SKIP environment variable to include the specified driver + * and then calls GDALDriverManager::AutoSkipDrivers() to unregister it. The + * driver name should be the short format of the Gdal driver name e.g. GTIFF. + * @note added in 2.0 + */ + static void skipGdalDriver( QString theDriver ); + + /** Sets the GDAL_SKIP environment variable to exclude the specified driver + * and then calls GDALDriverManager::AutoSkipDrivers() to unregister it. The + * driver name should be the short format of the Gdal driver name e.g. GTIFF. + * @note added in 2.0 + */ + static void restoreGdalDriver( QString theDriver ); + + /** Returns the list of gdal drivers that should be skipped (based on + * GDAL_SKIP environment variable) + * @note added in 2.0 + */ + static QStringList skippedGdalDrivers( ){ return mGdalSkipList; }; + + /** Apply the skipped drivers list to gdal + * @see skipGdalDriver + * @see restoreGdalDriver + * @see skippedGdalDrivers + * @note added in 2.0 */ + static void applyGdalSkippedDrivers(); + signals: void preNotify( QObject * receiver, QEvent * event, bool * done ); @@ -246,6 +274,10 @@ class CORE_EXPORT QgsApplication: public QApplication static QString mBuildSourcePath; /** path to the output directory of the build. valid only when running from build directory */ static QString mBuildOutputPath; + /** List of gdal drivers to be skipped. Uses GDAL_SKIP to exclude them. + * @see skipGdalDriver, restoreGdalDriver + * @note added in 2.0 */ + static QStringList mGdalSkipList; }; #endif diff --git a/src/providers/gdal/qgsgdalprovider.cpp b/src/providers/gdal/qgsgdalprovider.cpp index 2c19bd46de6..7cb4a261cbf 100644 --- a/src/providers/gdal/qgsgdalprovider.cpp +++ b/src/providers/gdal/qgsgdalprovider.cpp @@ -1182,7 +1182,11 @@ int QgsGdalProvider::colorInterpretation( int theBandNo ) const void QgsGdalProvider::registerGdalDrivers() { if ( GDALGetDriverCount() == 0 ) + { GDALAllRegister(); + } + //call regardless of above + QgsApplication::applyGdalSkippedDrivers(); } diff --git a/src/ui/qgsoptionsbase.ui b/src/ui/qgsoptionsbase.ui index 41b786578d5..dc69c365632 100644 --- a/src/ui/qgsoptionsbase.ui +++ b/src/ui/qgsoptionsbase.ui @@ -50,8 +50,14 @@ General + + 0 + + + QFrame::NoFrame + true @@ -60,8 +66,8 @@ 0 0 - 780 - 755 + 979 + 1135 @@ -425,6 +431,32 @@ + + + + GDAL Drivers + + + + + + + 0 + 141 + + + + + + + + In some cases more than one GDAL driver can be used to load the same raster format. Use the list below to specify which to use. + + + + + + @@ -489,8 +521,14 @@ Rendering + + 0 + + + QFrame::NoFrame + true @@ -499,8 +537,8 @@ 0 0 - 780 - 433 + 641 + 512 @@ -657,8 +695,14 @@ Map tools + + 0 + + + QFrame::NoFrame + true @@ -667,8 +711,8 @@ 0 0 - 780 - 456 + 567 + 532 @@ -937,8 +981,14 @@ Overlays + + 0 + + + QFrame::NoFrame + true @@ -947,8 +997,8 @@ 0 0 - 795 - 415 + 289 + 94 @@ -1022,8 +1072,8 @@ 0 0 - 795 - 415 + 797 + 490 @@ -1342,8 +1392,14 @@ CRS + + 0 + + + QFrame::NoFrame + true @@ -1352,8 +1408,8 @@ 0 0 - 795 - 415 + 446 + 420 @@ -1510,8 +1566,14 @@ Locale + + 0 + + + QFrame::NoFrame + true @@ -1520,8 +1582,8 @@ 0 0 - 780 - 527 + 519 + 583 @@ -1601,8 +1663,14 @@ Network + + 0 + + + QFrame::NoFrame + true @@ -1611,8 +1679,8 @@ 0 0 - 780 - 461 + 384 + 573