[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)
This commit is contained in:
Larry Shaffer 2013-01-01 19:48:31 -07:00
parent 103942391d
commit 8d582ade2e
7 changed files with 553 additions and 68 deletions

View File

@ -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();

View File

@ -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();

View File

@ -39,6 +39,7 @@
#include <QSettings>
#include <QColorDialog>
#include <QLocale>
#include <QProcess>
#include <QToolBar>
#include <QSize>
#include <QStyleFactory>
@ -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() )
@ -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 )
@ -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(

View File

@ -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
@ -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

View File

@ -25,6 +25,7 @@
#include <QFileOpenEvent>
#include <QMessageBox>
#include <QPalette>
#include <QProcess>
#include <QSettings>
#include <QIcon>
#include <QPixmap>
@ -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 );
@ -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

View File

@ -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();
@ -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
@ -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 );

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>808</width>
<width>816</width>
<height>674</height>
</rect>
</property>
@ -33,7 +33,7 @@
<item row="2" column="0">
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>4</number>
<number>0</number>
</property>
<property name="iconSize">
<size>
@ -66,8 +66,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>770</width>
<height>1062</height>
<width>771</width>
<height>1020</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
@ -966,56 +966,247 @@
<widget class="QWidget" name="tab_2">
<attribute name="icon">
<iconset resource="../../images/images.qrc">
<normaloff>:/images/themes/default/mActionShowPluginManager.png</normaloff>:/images/themes/default/mActionShowPluginManager.png</iconset>
<normaloff>:/images/themes/default/propertyicons/action.png</normaloff>:/images/themes/default/propertyicons/action.png</iconset>
</attribute>
<attribute name="title">
<string>Plugins</string>
<string>System</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_25">
<layout class="QGridLayout" name="gridLayout_30">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Plugin paths</string>
<widget class="QScrollArea" name="scrollArea_9">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<layout class="QGridLayout" name="_2">
<item row="0" column="0">
<widget class="QLabel" name="mSVGLabel_2">
<property name="text">
<string>Path(s) to search for additional C++ plugins libraries</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>31</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="mBtnAddPluginPath">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="mBtnRemovePluginPath">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QListWidget" name="mListPluginPaths"/>
</item>
</layout>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>786</width>
<height>588</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_9">
<item>
<widget class="QGroupBox" name="mEnvironmentGrpBx">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Environment</string>
</property>
<layout class="QGridLayout" name="gridLayout_31">
<item row="1" column="0" colspan="4">
<widget class="QTableWidget" name="mCustomVariablesTable">
<property name="minimumSize">
<size>
<width>0</width>
<height>120</height>
</size>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<property name="cornerButtonEnabled">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>4</number>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Apply</string>
</property>
</column>
<column>
<property name="text">
<string>Variable</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="mRemoveCustomVarBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="mAddCustomVarBtn">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QgsCollapsibleGroupBox" name="mCurrentVariablesGrpBx">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="title">
<string>Current environment variables (read-only - bold indicates modified at startup)</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="QTableWidget" name="mCurrentVariablesTable">
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::DragOnly</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>100</number>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Variable</string>
</property>
</column>
<column>
<property name="text">
<string>Value</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mCustomVariablesChkBx">
<property name="text">
<string>Use custom environment variables (restart required - include separators)</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer_9">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Plugin paths</string>
</property>
<layout class="QGridLayout" name="_2">
<item row="0" column="0">
<widget class="QLabel" name="mSVGLabel_2">
<property name="text">
<string>Path(s) to search for additional C++ plugins libraries</string>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>31</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="mBtnAddPluginPath">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="mBtnRemovePluginPath">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QListWidget" name="mListPluginPaths"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -1045,8 +1236,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1010</width>
<height>815</height>
<width>963</width>
<height>826</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_8">
@ -1560,8 +1751,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>770</width>
<height>691</height>
<width>771</width>
<height>717</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_4">
@ -1920,8 +2111,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>274</width>
<height>87</height>
<width>786</width>
<height>588</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_10">
@ -2001,8 +2192,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>581</width>
<height>606</height>
<width>771</width>
<height>618</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_13">
@ -2377,8 +2568,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>653</width>
<height>415</height>
<width>786</width>
<height>588</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_15">
@ -2564,8 +2755,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>519</width>
<height>565</height>
<width>786</width>
<height>588</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_17">
@ -2661,8 +2852,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>505</width>
<height>573</height>
<width>771</width>
<height>598</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_20">
@ -2902,6 +3093,12 @@
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QToolButton</extends>
@ -3036,12 +3233,60 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>450</x>
<y>508</y>
<x>371</x>
<y>517</y>
</hint>
<hint type="destinationlabel">
<x>518</x>
<y>508</y>
<x>546</x>
<y>521</y>
</hint>
</hints>
</connection>
<connection>
<sender>mCustomVariablesChkBx</sender>
<signal>toggled(bool)</signal>
<receiver>mAddCustomVarBtn</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>100</x>
<y>79</y>
</hint>
<hint type="destinationlabel">
<x>651</x>
<y>92</y>
</hint>
</hints>
</connection>
<connection>
<sender>mCustomVariablesChkBx</sender>
<signal>toggled(bool)</signal>
<receiver>mRemoveCustomVarBtn</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>68</x>
<y>76</y>
</hint>
<hint type="destinationlabel">
<x>754</x>
<y>89</y>
</hint>
</hints>
</connection>
<connection>
<sender>mCustomVariablesChkBx</sender>
<signal>toggled(bool)</signal>
<receiver>mCustomVariablesTable</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>81</x>
<y>82</y>
</hint>
<hint type="destinationlabel">
<x>180</x>
<y>179</y>
</hint>
</hints>
</connection>