Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE] Configure custom environment variables
- Fix for #3097
- Could help plugins, like SEXTANTE, work better across platforms via abstracted coding based upon env vars
- In app prefs, configure variables and view current set, with tooltips to show pre-startup value (if any)
  • Loading branch information
dakcarto committed Jan 3, 2013
1 parent 1039423 commit 8d582ad
Show file tree
Hide file tree
Showing 7 changed files with 553 additions and 68 deletions.
4 changes: 4 additions & 0 deletions python/core/qgsapplication.sip
Expand Up @@ -152,6 +152,10 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv)
//! @note added in 1.4
static const QStringList svgPaths();

//! Returns the system environment variables passed to application.
//! @note added in 1.9
static const QMap<QString, QString> systemEnvVars();

//! Returns the path to the application prefix directory.
static const QString prefixPath();

Expand Down
45 changes: 45 additions & 0 deletions src/app/main.cpp
Expand Up @@ -569,6 +569,51 @@ int main( int argc, char *argv[] )

QSettings mySettings;

// custom environment variables
QMap<QString, QString> systemEnvVars = QgsApplication::systemEnvVars();
bool useCustomVars = mySettings.value( "qgis/customEnvVarsUse", QVariant( false ) ).toBool();
if ( useCustomVars )
{
QStringList customVarsList = mySettings.value( "qgis/customEnvVars", "" ).toStringList();
if ( !customVarsList.isEmpty() )
{
foreach ( const QString &varStr, customVarsList )
{
int pos = varStr.indexOf( QLatin1Char( '|' ) );
if ( pos == -1 )
continue;
QString envVarApply = varStr.left( pos );
QString varStrNameValue = varStr.mid( pos + 1 );
pos = varStrNameValue.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QString envVarName = varStrNameValue.left( pos );
QString envVarValue = varStrNameValue.mid( pos + 1 );

if ( systemEnvVars.contains( envVarName ) )
{
if ( envVarApply == "prepend" )
{
envVarValue += systemEnvVars.value( envVarName );
}
else if ( envVarApply == "append" )
{
envVarValue = systemEnvVars.value( envVarName ) + envVarValue;
}
}

if ( systemEnvVars.contains( envVarName ) && envVarApply == "unset" )
{
unsetenv( envVarName.toUtf8().constData() );
}
else
{
setenv( envVarName.toUtf8().constData(), envVarValue.toUtf8().constData(), envVarApply == "undefined" ? 0 : 1 );
}
}
}
}

// Set the application style. If it's not set QT will use the platform style except on Windows
// as it looks really ugly so we use QPlastiqueStyle.
QString style = mySettings.value( "/qgis/style" ).toString();
Expand Down
157 changes: 157 additions & 0 deletions src/app/qgsoptions.cpp
Expand Up @@ -39,6 +39,7 @@
#include <QSettings>
#include <QColorDialog>
#include <QLocale>
#include <QProcess>
#include <QToolBar>
#include <QSize>
#include <QStyleFactory>
Expand Down Expand Up @@ -110,6 +111,99 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
spinBoxIdentifyValue->setMinimum( 0.01 );
spinBoxIdentifyValue->setValue( identifyValue );

// custom environment variables
bool useCustomVars = settings.value( "qgis/customEnvVarsUse", QVariant( false ) ).toBool();
mCustomVariablesChkBx->setChecked( useCustomVars );
if ( !useCustomVars )
{
mAddCustomVarBtn->setEnabled( false );
mRemoveCustomVarBtn->setEnabled( false );
mCustomVariablesTable->setEnabled( false );
}
QStringList customVarsList = settings.value( "qgis/customEnvVars", "" ).toStringList();
mCustomVariablesTable->clearContents();
foreach ( const QString &varStr, customVarsList )
{
int pos = varStr.indexOf( QLatin1Char( '|' ) );
if ( pos == -1 )
continue;
QString varStrApply = varStr.left( pos );
QString varStrNameValue = varStr.mid( pos + 1 );
pos = varStrNameValue.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QString varStrName = varStrNameValue.left( pos );
QString varStrValue = varStrNameValue.mid( pos + 1 );

addCustomEnvVarRow( varStrName, varStrValue, varStrApply );
}
QFontMetrics fmCustomVar( mCustomVariablesTable->horizontalHeader()->font() );
int fmCustomVarH = fmCustomVar.height() + 2;
mCustomVariablesTable->horizontalHeader()->setFixedHeight( fmCustomVarH );

mCustomVariablesTable->setColumnWidth( 0, 120 );
if ( mCustomVariablesTable->rowCount() > 0 )
{
mCustomVariablesTable->resizeColumnToContents( 1 );
}
else
{
mCustomVariablesTable->setColumnWidth( 1, 120 );
}

// current environment variables
mCurrentVariablesTable->horizontalHeader()->setFixedHeight( fmCustomVarH );
QMap<QString, QString> sysVarsMap = QgsApplication::systemEnvVars();
QStringList currentVarsList = QProcess::systemEnvironment();
mCurrentVariablesTable->clearContents();

foreach ( const QString &varStr, currentVarsList )
{
int pos = varStr.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QStringList varStrItms;
QString varStrName = varStr.left( pos );
QString varStrValue = varStr.mid( pos + 1 );
varStrItms << varStrName << varStrValue;

// check if different than system variable
QString sysVarVal = QString( "" );
bool sysVarMissing = !sysVarsMap.contains( varStrName );
if ( sysVarMissing )
sysVarVal = tr( "not present" );

if ( !sysVarMissing && sysVarsMap.value( varStrName ) != varStrValue )
sysVarVal = sysVarsMap.value( varStrName );

if ( !sysVarVal.isEmpty() )
sysVarVal = tr( "System value: %1" ).arg( sysVarVal );

int rowCnt = mCurrentVariablesTable->rowCount();
mCurrentVariablesTable->insertRow( rowCnt );

QFont fItm;
for ( int i = 0; i < varStrItms.size(); ++i )
{
QTableWidgetItem* varNameItm = new QTableWidgetItem( varStrItms.at( i ) );
varNameItm->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable
| Qt::ItemIsEditable | Qt::ItemIsDragEnabled );
fItm = varNameItm->font();
if ( !sysVarVal.isEmpty() )
{
fItm.setBold( true );
varNameItm->setFont( fItm );
varNameItm->setToolTip( sysVarVal );
}
mCurrentVariablesTable->setItem( rowCnt, i, varNameItm );
}
fItm.setBold( true );
QFontMetrics fmRow( fItm );
mCurrentVariablesTable->setRowHeight( rowCnt, fmRow.height() + 6 );
}
if ( mCurrentVariablesTable->rowCount() > 0 )
mCurrentVariablesTable->resizeColumnToContents( 0 );

//local directories to search when loading c++ plugins
QString myPaths = settings.value( "plugins/searchPathsForPlugins", "" ).toString();
if ( !myPaths.isEmpty() )
Expand Down Expand Up @@ -781,6 +875,23 @@ void QgsOptions::saveOptions()
{
QSettings settings;

// custom environment variables
settings.setValue( "qgis/customEnvVarsUse", QVariant( mCustomVariablesChkBx->isChecked() ) );
QStringList customVars;
for ( int i = 0; i < mCustomVariablesTable->rowCount(); ++i )
{
if ( mCustomVariablesTable->item( i, 1 )->text().isEmpty() )
continue;
QComboBox* varApplyCmbBx = qobject_cast<QComboBox*>( mCustomVariablesTable->cellWidget( i, 0 ) );
QString customVar = varApplyCmbBx->itemData( varApplyCmbBx->currentIndex() ).toString();
customVar += "|";
customVar += mCustomVariablesTable->item( i, 1 )->text();
customVar += "=";
customVar += mCustomVariablesTable->item( i, 2 )->text();
customVars << customVar;
}
settings.setValue( "qgis/customEnvVars", QVariant( customVars ) );

//search directories for user plugins
QString myPaths;
for ( int i = 0; i < mListPluginPaths->count(); ++i )
Expand Down Expand Up @@ -1211,6 +1322,52 @@ QStringList QgsOptions::i18nList()
return myList;
}

void QgsOptions::addCustomEnvVarRow( QString varName, QString varVal, QString varApply )
{
int rowCnt = mCustomVariablesTable->rowCount();
mCustomVariablesTable->insertRow( rowCnt );

QComboBox* varApplyCmbBx = new QComboBox( this );
varApplyCmbBx->addItem( tr( "Overwrite" ), QVariant( "overwrite" ) );
varApplyCmbBx->addItem( tr( "If Undefined" ), QVariant( "undefined" ) );
varApplyCmbBx->addItem( tr( "Unset" ), QVariant( "unset" ) );
varApplyCmbBx->addItem( tr( "Prepend" ), QVariant( "prepend" ) );
varApplyCmbBx->addItem( tr( "Append" ), QVariant( "append" ) );
varApplyCmbBx->setCurrentIndex( varApply.isEmpty() ? 0 : varApplyCmbBx->findData( QVariant( varApply ) ) );

QFont cbf = varApplyCmbBx->font();
QFontMetrics cbfm = QFontMetrics( cbf );
cbf.setPointSize( cbf.pointSize() - 2 );
varApplyCmbBx->setFont( cbf );
mCustomVariablesTable->setCellWidget( rowCnt, 0, varApplyCmbBx );

Qt::ItemFlags itmFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable
| Qt::ItemIsEditable | Qt::ItemIsDropEnabled;

QTableWidgetItem* varNameItm = new QTableWidgetItem( varName );
varNameItm->setFlags( itmFlags );
mCustomVariablesTable->setItem( rowCnt, 1, varNameItm );

QTableWidgetItem* varValueItm = new QTableWidgetItem( varVal );
varNameItm->setFlags( itmFlags );
mCustomVariablesTable->setItem( rowCnt, 2, varValueItm );

mCustomVariablesTable->setRowHeight( rowCnt, cbfm.height() + 8 );
}

void QgsOptions::on_mAddCustomVarBtn_clicked()
{
addCustomEnvVarRow( QString( "" ), QString( "" ) );
mCustomVariablesTable->setFocus();
mCustomVariablesTable->setCurrentCell( mCustomVariablesTable->rowCount() - 1, 1 );
mCustomVariablesTable->edit( mCustomVariablesTable->currentIndex() );
}

void QgsOptions::on_mRemoveCustomVarBtn_clicked()
{
mCustomVariablesTable->removeRow( mCustomVariablesTable->currentRow() );
}

void QgsOptions::on_mBtnAddPluginPath_clicked()
{
QString myDir = QFileDialog::getExistingDirectory(
Expand Down
14 changes: 14 additions & 0 deletions src/app/qgsoptions.h
Expand Up @@ -117,6 +117,16 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
/**Remove an URL to exclude from Proxy*/
void on_mRemoveUrlPushButton_clicked();

/** Slot to add a custom environment variable to the app
* @note added in QGIS 1.9
*/
void on_mAddCustomVarBtn_clicked();

/** Slot to remove a custom environment variable from the app
* @note added in QGIS 1.9
*/
void on_mRemoveCustomVarBtn_clicked();

/* Let the user add a path to the list of search paths
* used for finding user Plugin libs.
* @note added in QGIS 1.7
Expand Down Expand Up @@ -197,6 +207,10 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
QgsCoordinateReferenceSystem mLayerDefaultCrs;
bool mLoadedGdalDriverList;

/** Generate table row for custom environment variables
* @note added in QGIS 1.9
*/
void addCustomEnvVarRow( QString varName, QString varVal, QString varApply = QString() );
};

#endif // #ifndef QGSOPTIONS_H
15 changes: 15 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -25,6 +25,7 @@
#include <QFileOpenEvent>
#include <QMessageBox>
#include <QPalette>
#include <QProcess>
#include <QSettings>
#include <QIcon>
#include <QPixmap>
Expand All @@ -50,6 +51,7 @@ QString ABISYM( QgsApplication::mLibraryPath );
QString ABISYM( QgsApplication::mLibexecPath );
QString ABISYM( QgsApplication::mThemeName );
QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
QString ABISYM( QgsApplication::mConfigPath );
bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
QString ABISYM( QgsApplication::mBuildSourcePath );
Expand Down Expand Up @@ -152,6 +154,19 @@ void QgsApplication::init( QString customConfigPath )

ABISYM( mDefaultSvgPaths ) << qgisSettingsDirPath() + QString( "svg/" );

// store system environment variables passed to application, before they are adjusted
QMap<QString, QString> systemEnvVarMap;
foreach ( const QString &varStr, QProcess::systemEnvironment() )
{
int pos = varStr.indexOf( QLatin1Char( '=' ) );
if ( pos == -1 )
continue;
QString varStrName = varStr.left( pos );
QString varStrValue = varStr.mid( pos + 1 );
systemEnvVarMap.insert( varStrName, varStrValue );
}
ABISYM( mSystemEnvVars ) = systemEnvVarMap;

// set a working directory up for gdal to write .aux.xml files into
// for cases where the raster dir is read only to the user
// if the env var is already set it will be used preferentially
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsapplication.h
Expand Up @@ -120,6 +120,10 @@ class CORE_EXPORT QgsApplication: public QApplication
//! @note added in 1.4
static const QStringList svgPaths();

//! Returns the system environment variables passed to application.
//! @note added in 1.9
static const QMap<QString, QString> systemEnvVars() { return ABISYM( mSystemEnvVars ); }

//! Returns the path to the application prefix directory.
static const QString prefixPath();

Expand Down Expand Up @@ -253,7 +257,7 @@ class CORE_EXPORT QgsApplication: public QApplication
* GDAL_SKIP environment variable)
* @note added in 2.0
*/
static QStringList skippedGdalDrivers( ) { return ABISYM( mGdalSkipList ); };
static QStringList skippedGdalDrivers( ) { return ABISYM( mGdalSkipList ); }

/** Apply the skipped drivers list to gdal
* @see skipGdalDriver
Expand All @@ -277,6 +281,7 @@ class CORE_EXPORT QgsApplication: public QApplication
static QString ABISYM( mLibexecPath );
static QString ABISYM( mThemeName );
static QStringList ABISYM( mDefaultSvgPaths );
static QMap<QString, QString> ABISYM( mSystemEnvVars );

static QString ABISYM( mConfigPath );

Expand Down

0 comments on commit 8d582ad

Please sign in to comment.