Skip to content

Commit 8d582ad

Browse files
committed
[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)
1 parent 1039423 commit 8d582ad

File tree

7 files changed

+553
-68
lines changed

7 files changed

+553
-68
lines changed

python/core/qgsapplication.sip

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ static void qtgui_UpdatePyArgv(PyObject *argvlist, int argc, char **argv)
152152
//! @note added in 1.4
153153
static const QStringList svgPaths();
154154

155+
//! Returns the system environment variables passed to application.
156+
//! @note added in 1.9
157+
static const QMap<QString, QString> systemEnvVars();
158+
155159
//! Returns the path to the application prefix directory.
156160
static const QString prefixPath();
157161

src/app/main.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,51 @@ int main( int argc, char *argv[] )
569569

570570
QSettings mySettings;
571571

572+
// custom environment variables
573+
QMap<QString, QString> systemEnvVars = QgsApplication::systemEnvVars();
574+
bool useCustomVars = mySettings.value( "qgis/customEnvVarsUse", QVariant( false ) ).toBool();
575+
if ( useCustomVars )
576+
{
577+
QStringList customVarsList = mySettings.value( "qgis/customEnvVars", "" ).toStringList();
578+
if ( !customVarsList.isEmpty() )
579+
{
580+
foreach ( const QString &varStr, customVarsList )
581+
{
582+
int pos = varStr.indexOf( QLatin1Char( '|' ) );
583+
if ( pos == -1 )
584+
continue;
585+
QString envVarApply = varStr.left( pos );
586+
QString varStrNameValue = varStr.mid( pos + 1 );
587+
pos = varStrNameValue.indexOf( QLatin1Char( '=' ) );
588+
if ( pos == -1 )
589+
continue;
590+
QString envVarName = varStrNameValue.left( pos );
591+
QString envVarValue = varStrNameValue.mid( pos + 1 );
592+
593+
if ( systemEnvVars.contains( envVarName ) )
594+
{
595+
if ( envVarApply == "prepend" )
596+
{
597+
envVarValue += systemEnvVars.value( envVarName );
598+
}
599+
else if ( envVarApply == "append" )
600+
{
601+
envVarValue = systemEnvVars.value( envVarName ) + envVarValue;
602+
}
603+
}
604+
605+
if ( systemEnvVars.contains( envVarName ) && envVarApply == "unset" )
606+
{
607+
unsetenv( envVarName.toUtf8().constData() );
608+
}
609+
else
610+
{
611+
setenv( envVarName.toUtf8().constData(), envVarValue.toUtf8().constData(), envVarApply == "undefined" ? 0 : 1 );
612+
}
613+
}
614+
}
615+
}
616+
572617
// Set the application style. If it's not set QT will use the platform style except on Windows
573618
// as it looks really ugly so we use QPlastiqueStyle.
574619
QString style = mySettings.value( "/qgis/style" ).toString();

src/app/qgsoptions.cpp

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include <QSettings>
4040
#include <QColorDialog>
4141
#include <QLocale>
42+
#include <QProcess>
4243
#include <QToolBar>
4344
#include <QSize>
4445
#include <QStyleFactory>
@@ -110,6 +111,99 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
110111
spinBoxIdentifyValue->setMinimum( 0.01 );
111112
spinBoxIdentifyValue->setValue( identifyValue );
112113

114+
// custom environment variables
115+
bool useCustomVars = settings.value( "qgis/customEnvVarsUse", QVariant( false ) ).toBool();
116+
mCustomVariablesChkBx->setChecked( useCustomVars );
117+
if ( !useCustomVars )
118+
{
119+
mAddCustomVarBtn->setEnabled( false );
120+
mRemoveCustomVarBtn->setEnabled( false );
121+
mCustomVariablesTable->setEnabled( false );
122+
}
123+
QStringList customVarsList = settings.value( "qgis/customEnvVars", "" ).toStringList();
124+
mCustomVariablesTable->clearContents();
125+
foreach ( const QString &varStr, customVarsList )
126+
{
127+
int pos = varStr.indexOf( QLatin1Char( '|' ) );
128+
if ( pos == -1 )
129+
continue;
130+
QString varStrApply = varStr.left( pos );
131+
QString varStrNameValue = varStr.mid( pos + 1 );
132+
pos = varStrNameValue.indexOf( QLatin1Char( '=' ) );
133+
if ( pos == -1 )
134+
continue;
135+
QString varStrName = varStrNameValue.left( pos );
136+
QString varStrValue = varStrNameValue.mid( pos + 1 );
137+
138+
addCustomEnvVarRow( varStrName, varStrValue, varStrApply );
139+
}
140+
QFontMetrics fmCustomVar( mCustomVariablesTable->horizontalHeader()->font() );
141+
int fmCustomVarH = fmCustomVar.height() + 2;
142+
mCustomVariablesTable->horizontalHeader()->setFixedHeight( fmCustomVarH );
143+
144+
mCustomVariablesTable->setColumnWidth( 0, 120 );
145+
if ( mCustomVariablesTable->rowCount() > 0 )
146+
{
147+
mCustomVariablesTable->resizeColumnToContents( 1 );
148+
}
149+
else
150+
{
151+
mCustomVariablesTable->setColumnWidth( 1, 120 );
152+
}
153+
154+
// current environment variables
155+
mCurrentVariablesTable->horizontalHeader()->setFixedHeight( fmCustomVarH );
156+
QMap<QString, QString> sysVarsMap = QgsApplication::systemEnvVars();
157+
QStringList currentVarsList = QProcess::systemEnvironment();
158+
mCurrentVariablesTable->clearContents();
159+
160+
foreach ( const QString &varStr, currentVarsList )
161+
{
162+
int pos = varStr.indexOf( QLatin1Char( '=' ) );
163+
if ( pos == -1 )
164+
continue;
165+
QStringList varStrItms;
166+
QString varStrName = varStr.left( pos );
167+
QString varStrValue = varStr.mid( pos + 1 );
168+
varStrItms << varStrName << varStrValue;
169+
170+
// check if different than system variable
171+
QString sysVarVal = QString( "" );
172+
bool sysVarMissing = !sysVarsMap.contains( varStrName );
173+
if ( sysVarMissing )
174+
sysVarVal = tr( "not present" );
175+
176+
if ( !sysVarMissing && sysVarsMap.value( varStrName ) != varStrValue )
177+
sysVarVal = sysVarsMap.value( varStrName );
178+
179+
if ( !sysVarVal.isEmpty() )
180+
sysVarVal = tr( "System value: %1" ).arg( sysVarVal );
181+
182+
int rowCnt = mCurrentVariablesTable->rowCount();
183+
mCurrentVariablesTable->insertRow( rowCnt );
184+
185+
QFont fItm;
186+
for ( int i = 0; i < varStrItms.size(); ++i )
187+
{
188+
QTableWidgetItem* varNameItm = new QTableWidgetItem( varStrItms.at( i ) );
189+
varNameItm->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable
190+
| Qt::ItemIsEditable | Qt::ItemIsDragEnabled );
191+
fItm = varNameItm->font();
192+
if ( !sysVarVal.isEmpty() )
193+
{
194+
fItm.setBold( true );
195+
varNameItm->setFont( fItm );
196+
varNameItm->setToolTip( sysVarVal );
197+
}
198+
mCurrentVariablesTable->setItem( rowCnt, i, varNameItm );
199+
}
200+
fItm.setBold( true );
201+
QFontMetrics fmRow( fItm );
202+
mCurrentVariablesTable->setRowHeight( rowCnt, fmRow.height() + 6 );
203+
}
204+
if ( mCurrentVariablesTable->rowCount() > 0 )
205+
mCurrentVariablesTable->resizeColumnToContents( 0 );
206+
113207
//local directories to search when loading c++ plugins
114208
QString myPaths = settings.value( "plugins/searchPathsForPlugins", "" ).toString();
115209
if ( !myPaths.isEmpty() )
@@ -781,6 +875,23 @@ void QgsOptions::saveOptions()
781875
{
782876
QSettings settings;
783877

878+
// custom environment variables
879+
settings.setValue( "qgis/customEnvVarsUse", QVariant( mCustomVariablesChkBx->isChecked() ) );
880+
QStringList customVars;
881+
for ( int i = 0; i < mCustomVariablesTable->rowCount(); ++i )
882+
{
883+
if ( mCustomVariablesTable->item( i, 1 )->text().isEmpty() )
884+
continue;
885+
QComboBox* varApplyCmbBx = qobject_cast<QComboBox*>( mCustomVariablesTable->cellWidget( i, 0 ) );
886+
QString customVar = varApplyCmbBx->itemData( varApplyCmbBx->currentIndex() ).toString();
887+
customVar += "|";
888+
customVar += mCustomVariablesTable->item( i, 1 )->text();
889+
customVar += "=";
890+
customVar += mCustomVariablesTable->item( i, 2 )->text();
891+
customVars << customVar;
892+
}
893+
settings.setValue( "qgis/customEnvVars", QVariant( customVars ) );
894+
784895
//search directories for user plugins
785896
QString myPaths;
786897
for ( int i = 0; i < mListPluginPaths->count(); ++i )
@@ -1211,6 +1322,52 @@ QStringList QgsOptions::i18nList()
12111322
return myList;
12121323
}
12131324

1325+
void QgsOptions::addCustomEnvVarRow( QString varName, QString varVal, QString varApply )
1326+
{
1327+
int rowCnt = mCustomVariablesTable->rowCount();
1328+
mCustomVariablesTable->insertRow( rowCnt );
1329+
1330+
QComboBox* varApplyCmbBx = new QComboBox( this );
1331+
varApplyCmbBx->addItem( tr( "Overwrite" ), QVariant( "overwrite" ) );
1332+
varApplyCmbBx->addItem( tr( "If Undefined" ), QVariant( "undefined" ) );
1333+
varApplyCmbBx->addItem( tr( "Unset" ), QVariant( "unset" ) );
1334+
varApplyCmbBx->addItem( tr( "Prepend" ), QVariant( "prepend" ) );
1335+
varApplyCmbBx->addItem( tr( "Append" ), QVariant( "append" ) );
1336+
varApplyCmbBx->setCurrentIndex( varApply.isEmpty() ? 0 : varApplyCmbBx->findData( QVariant( varApply ) ) );
1337+
1338+
QFont cbf = varApplyCmbBx->font();
1339+
QFontMetrics cbfm = QFontMetrics( cbf );
1340+
cbf.setPointSize( cbf.pointSize() - 2 );
1341+
varApplyCmbBx->setFont( cbf );
1342+
mCustomVariablesTable->setCellWidget( rowCnt, 0, varApplyCmbBx );
1343+
1344+
Qt::ItemFlags itmFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable
1345+
| Qt::ItemIsEditable | Qt::ItemIsDropEnabled;
1346+
1347+
QTableWidgetItem* varNameItm = new QTableWidgetItem( varName );
1348+
varNameItm->setFlags( itmFlags );
1349+
mCustomVariablesTable->setItem( rowCnt, 1, varNameItm );
1350+
1351+
QTableWidgetItem* varValueItm = new QTableWidgetItem( varVal );
1352+
varNameItm->setFlags( itmFlags );
1353+
mCustomVariablesTable->setItem( rowCnt, 2, varValueItm );
1354+
1355+
mCustomVariablesTable->setRowHeight( rowCnt, cbfm.height() + 8 );
1356+
}
1357+
1358+
void QgsOptions::on_mAddCustomVarBtn_clicked()
1359+
{
1360+
addCustomEnvVarRow( QString( "" ), QString( "" ) );
1361+
mCustomVariablesTable->setFocus();
1362+
mCustomVariablesTable->setCurrentCell( mCustomVariablesTable->rowCount() - 1, 1 );
1363+
mCustomVariablesTable->edit( mCustomVariablesTable->currentIndex() );
1364+
}
1365+
1366+
void QgsOptions::on_mRemoveCustomVarBtn_clicked()
1367+
{
1368+
mCustomVariablesTable->removeRow( mCustomVariablesTable->currentRow() );
1369+
}
1370+
12141371
void QgsOptions::on_mBtnAddPluginPath_clicked()
12151372
{
12161373
QString myDir = QFileDialog::getExistingDirectory(

src/app/qgsoptions.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,16 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
117117
/**Remove an URL to exclude from Proxy*/
118118
void on_mRemoveUrlPushButton_clicked();
119119

120+
/** Slot to add a custom environment variable to the app
121+
* @note added in QGIS 1.9
122+
*/
123+
void on_mAddCustomVarBtn_clicked();
124+
125+
/** Slot to remove a custom environment variable from the app
126+
* @note added in QGIS 1.9
127+
*/
128+
void on_mRemoveCustomVarBtn_clicked();
129+
120130
/* Let the user add a path to the list of search paths
121131
* used for finding user Plugin libs.
122132
* @note added in QGIS 1.7
@@ -197,6 +207,10 @@ class QgsOptions : public QDialog, private Ui::QgsOptionsBase
197207
QgsCoordinateReferenceSystem mLayerDefaultCrs;
198208
bool mLoadedGdalDriverList;
199209

210+
/** Generate table row for custom environment variables
211+
* @note added in QGIS 1.9
212+
*/
213+
void addCustomEnvVarRow( QString varName, QString varVal, QString varApply = QString() );
200214
};
201215

202216
#endif // #ifndef QGSOPTIONS_H

src/core/qgsapplication.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <QFileOpenEvent>
2626
#include <QMessageBox>
2727
#include <QPalette>
28+
#include <QProcess>
2829
#include <QSettings>
2930
#include <QIcon>
3031
#include <QPixmap>
@@ -50,6 +51,7 @@ QString ABISYM( QgsApplication::mLibraryPath );
5051
QString ABISYM( QgsApplication::mLibexecPath );
5152
QString ABISYM( QgsApplication::mThemeName );
5253
QStringList ABISYM( QgsApplication::mDefaultSvgPaths );
54+
QMap<QString, QString> ABISYM( QgsApplication::mSystemEnvVars );
5355
QString ABISYM( QgsApplication::mConfigPath );
5456
bool ABISYM( QgsApplication::mRunningFromBuildDir ) = false;
5557
QString ABISYM( QgsApplication::mBuildSourcePath );
@@ -152,6 +154,19 @@ void QgsApplication::init( QString customConfigPath )
152154

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

157+
// store system environment variables passed to application, before they are adjusted
158+
QMap<QString, QString> systemEnvVarMap;
159+
foreach ( const QString &varStr, QProcess::systemEnvironment() )
160+
{
161+
int pos = varStr.indexOf( QLatin1Char( '=' ) );
162+
if ( pos == -1 )
163+
continue;
164+
QString varStrName = varStr.left( pos );
165+
QString varStrValue = varStr.mid( pos + 1 );
166+
systemEnvVarMap.insert( varStrName, varStrValue );
167+
}
168+
ABISYM( mSystemEnvVars ) = systemEnvVarMap;
169+
155170
// set a working directory up for gdal to write .aux.xml files into
156171
// for cases where the raster dir is read only to the user
157172
// if the env var is already set it will be used preferentially

src/core/qgsapplication.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ class CORE_EXPORT QgsApplication: public QApplication
120120
//! @note added in 1.4
121121
static const QStringList svgPaths();
122122

123+
//! Returns the system environment variables passed to application.
124+
//! @note added in 1.9
125+
static const QMap<QString, QString> systemEnvVars() { return ABISYM( mSystemEnvVars ); }
126+
123127
//! Returns the path to the application prefix directory.
124128
static const QString prefixPath();
125129

@@ -253,7 +257,7 @@ class CORE_EXPORT QgsApplication: public QApplication
253257
* GDAL_SKIP environment variable)
254258
* @note added in 2.0
255259
*/
256-
static QStringList skippedGdalDrivers( ) { return ABISYM( mGdalSkipList ); };
260+
static QStringList skippedGdalDrivers( ) { return ABISYM( mGdalSkipList ); }
257261

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

281286
static QString ABISYM( mConfigPath );
282287

0 commit comments

Comments
 (0)