15 changes: 3 additions & 12 deletions src/plugins/heatmap/heatmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
//QGIS includes
#include "../qgisplugin.h"
#include "qgsvectorlayer.h"
#include "qgscoordinatereferencesystem.h"

//forward declarations
class QAction;
Expand Down Expand Up @@ -78,20 +79,10 @@ class Heatmap: public QObject, public QgisPlugin
void unload();
//! show the help document
void help();
//! the worker slot to create heatmap
/*
* Signal: createRaster
* Params:
* QgsVectorLayer* -> Input point layer
* int -> Buffer distance
* float -> Decay ratio
* QString -> Output filename
* QString -> Output Format Short Name
*/
void createRaster( QgsVectorLayer*, int, float, QString, QString );

private:

//! Worker to convert meters to map units
float mapUnitsOf( float meters, QgsCoordinateReferenceSystem crs );
// MANDATORY PLUGIN PROPERTY DECLARATIONS .....

int mPluginType;
Expand Down
373 changes: 311 additions & 62 deletions src/plugins/heatmap/heatmapgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@
#include "qgsmaplayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"
#include "qgsvectordataprovider.h"
#include "qgslogger.h"
#include "qgsgeometry.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsdistancearea.h"

// GDAL includes
#include "gdal_priv.h"
Expand All @@ -35,6 +40,8 @@ HeatmapGui::HeatmapGui( QWidget* parent, Qt::WFlags fl )
{
setupUi( this );

QgsDebugMsg( tr( "Creating Heatmap Dialog" ) );

// Adding point layers to the mInputVectorCombo
foreach( QgsMapLayer *l, QgsMapLayerRegistry::instance()->mapLayers() )
{
Expand Down Expand Up @@ -70,6 +77,7 @@ HeatmapGui::HeatmapGui( QWidget* parent, Qt::WFlags fl )
}
mFormatCombo->setCurrentIndex( myTiffIndex );

updateBBox();
//finally set right the ok button
enableOrDisableOkButton();
}
Expand All @@ -78,70 +86,13 @@ HeatmapGui::~HeatmapGui()
{
}

/*
*
* Private Slots
*
*/
void HeatmapGui::on_mButtonBox_accepted()
{
// Variables to be emitted with the createRaster signal
int bufferDistance;
float decayRatio;
QString outputFileName;
QString outputFormat;

QString dummyText;

// The input vector layer
QString myLayerId = mInputVectorCombo->itemData( mInputVectorCombo->currentIndex() ).toString();

QgsVectorLayer* inputLayer = qobject_cast<QgsVectorLayer *>( QgsMapLayerRegistry::instance()->mapLayer( myLayerId ) );
if ( !inputLayer )
{
QMessageBox::information( 0, tr( "Layer not found" ), tr( "Layer %1 not found." ).arg( myLayerId ) );
return;
}

// The buffer distance
dummyText = mBufferLineEdit->text();
bufferDistance = dummyText.toInt();
if ( bufferDistance == 0 )
{
QMessageBox::information( 0, tr( "Invalid buffer value" ), tr( "Buffer distance cannot be zero. Please enter a valid value." ) );
return;
}
// The decay ratio
dummyText = mDecayLineEdit->text();
decayRatio = dummyText.toFloat();

// The output filename
outputFileName = mOutputRasterLineEdit->text();
QFileInfo myFileInfo( outputFileName );
if ( outputFileName.isEmpty() || !myFileInfo.dir().exists() )
{
QMessageBox::information( 0, tr( "Invalid output filename" ), tr( "Please enter a valid output file path and name." ) );
return;
}

// The output format
outputFormat = mFormatCombo->itemData( mFormatCombo->currentIndex() ).toString();

// append the file format if the suffix is empty
QString suffix = myFileInfo.suffix();
if ( suffix.isEmpty() )
{
QMap<QString, QString>::const_iterator it = mExtensionMap.find( outputFormat );
if ( it != mExtensionMap.end() && it.key() == outputFormat )
{
// making sure that there is really a extension value available
// Some drivers donot seem to have any extension at all
if ( it.value() != NULL || it.value() != "" )
{
outputFileName.append( "." );
outputFileName.append( it.value() );
}
}
}

emit createRaster( inputLayer, bufferDistance, decayRatio, outputFileName, outputFormat );

//and finally
accept();
}

Expand Down Expand Up @@ -180,6 +131,101 @@ void HeatmapGui::on_mOutputRasterLineEdit_editingFinished()
enableOrDisableOkButton();
}

void HeatmapGui::on_advancedGroupBox_toggled( bool enabled )
{
if ( enabled )
{
// if there are no layers point layers then show error dialog and toggle
if ( mInputVectorCombo->count() == 0 )
{
QMessageBox::information( 0, tr( "No valid layers found!" ), tr( "Advanced options cannot be enabled." ) );
advancedGroupBox->setChecked( false );
return;
}
// if there are layers then populate fields
populateFields();
updateBBox();
}
}

void HeatmapGui::on_rowLineEdit_editingFinished()
{
mRows = rowLineEdit->text().toInt();
mYcellsize = mBBox.height() / mRows;
mXcellsize = mYcellsize;
mColumns = mBBox.width() / mXcellsize + 1;

updateSize();
}

void HeatmapGui::on_columnLineEdit_editingFinished()
{
mColumns = columnLineEdit->text().toInt();
mXcellsize = mBBox.width() / mColumns;
mYcellsize = mXcellsize;
mRows = mBBox.height() / mYcellsize + 1;

updateSize();
}

void HeatmapGui::on_cellXLineEdit_editingFinished()
{
mXcellsize = cellXLineEdit->text().toFloat();
mYcellsize = mXcellsize;
mRows = mBBox.height() / mYcellsize + 1;
mColumns = mBBox.width() / mXcellsize + 1;

updateSize();
}

void HeatmapGui::on_cellYLineEdit_editingFinished()
{
mYcellsize = cellYLineEdit->text().toFloat();
mXcellsize = mYcellsize;
mRows = mBBox.height() / mYcellsize + 1;
mColumns = mBBox.width() / mXcellsize + 1;

updateSize();
}

void HeatmapGui::on_radiusFieldUnitCombo_currentIndexChanged( int index )
{
updateBBox();
// DebugMsg to avoid index not used warning
QgsDebugMsg( tr( "Unit index set to %1" ).arg( index ) );
}

void HeatmapGui::on_mRadiusUnitCombo_currentIndexChanged( int index )
{
QgsDebugMsg( tr( "Unit index set to %1" ).arg( index ) );
updateBBox();
}

void HeatmapGui::on_mInputVectorCombo_currentIndexChanged( int index )
{
if ( advancedGroupBox->isChecked() )
{
populateFields();
updateBBox();
}
QgsDebugMsg( tr( "Input vector index changed to %1" ).arg( index ) );
}

void HeatmapGui::on_radiusFieldCombo_currentIndexChanged( int index )
{
updateBBox();
QgsDebugMsg( tr( "Radius Field index changed to %1" ).arg( index ) );
}

void HeatmapGui::on_mBufferLineEdit_editingFinished()
{
updateBBox();
}
/*
*
* Private Functions
*
*/
void HeatmapGui::enableOrDisableOkButton()
{
bool enabled = true;
Expand All @@ -191,3 +237,206 @@ void HeatmapGui::enableOrDisableOkButton()
}
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( enabled );
}

void HeatmapGui::populateFields()
{
QgsVectorLayer* inputLayer = inputVectorLayer();
// The fields
QgsVectorDataProvider* provider = inputLayer->dataProvider();
QgsFieldMap fieldMap = provider->fields();
// Populate fields
radiusFieldCombo->clear();
weightFieldCombo->clear();

QMap<int, QgsField>::const_iterator i = fieldMap.constBegin();
while ( i != fieldMap.constEnd() )
{
radiusFieldCombo->addItem( i.value().name(), QVariant( i.key() ) );
weightFieldCombo->addItem( i.value().name(), QVariant( i.key() ) );
++i;
}

}

void HeatmapGui::updateSize()
{
rowLineEdit->setText( QString::number( mRows ) );
columnLineEdit->setText( QString::number( mColumns ) );
cellXLineEdit->setText( QString::number( mXcellsize ) );
cellYLineEdit->setText( QString::number( mYcellsize ) );
}

void HeatmapGui::updateBBox()
{
// Set the row/cols and cell sizes here
QgsVectorLayer *inputLayer = inputVectorLayer();

mBBox = inputLayer->extent();
QgsCoordinateReferenceSystem layerCrs = inputLayer->crs();

float radiusInMapUnits;
if ( useRadius->isChecked() )
{
float maxInField = inputLayer->maximumValue( radiusFieldCombo->itemData( radiusFieldCombo->currentIndex() ).toInt() ).toFloat();

if ( radiusFieldUnitCombo->currentIndex() == HeatmapGui::Meters )
{
radiusInMapUnits = mapUnitsOf( maxInField, layerCrs );
}
else if ( radiusFieldUnitCombo->currentIndex() == HeatmapGui::MapUnits )
{
radiusInMapUnits = maxInField;
}
}
else
{
float radiusValue = mBufferLineEdit->text().toFloat();
if ( mRadiusUnitCombo->currentIndex() == HeatmapGui::Meters )
{
radiusInMapUnits = mapUnitsOf( radiusValue, layerCrs );
}
else if ( mRadiusUnitCombo->currentIndex() == HeatmapGui::MapUnits )
{
radiusInMapUnits = radiusValue;
}
}
// get the distance converted into map units
mBBox.setXMinimum( mBBox.xMinimum() - radiusInMapUnits );
mBBox.setYMinimum( mBBox.yMinimum() - radiusInMapUnits );
mBBox.setXMaximum( mBBox.xMaximum() + radiusInMapUnits );
mBBox.setYMaximum( mBBox.yMaximum() + radiusInMapUnits );
mRows = 500;
mYcellsize = mBBox.height() / mRows;
mXcellsize = mYcellsize;
// +1 should be added wherever a fractional part of cell might occur
mColumns = mBBox.width() / mXcellsize + 1;
mRows += 1;

if ( advancedGroupBox->isChecked() )
{
updateSize();
}
}

float HeatmapGui::mapUnitsOf( float meters, QgsCoordinateReferenceSystem layerCrs )
{
// converter function to transform metres input to mapunits
// so that bounding box can be updated
QgsDistanceArea da;
da.setSourceCrs( layerCrs.srsid() );
da.setEllipsoid( layerCrs.ellipsoidAcronym() );
if ( da.geographic() )
{
da.setProjectionsEnabled( true );
}
double unitDistance = da.measureLine( QgsPoint( 0.0, 0.0 ), QgsPoint( 0.0, 1.0 ) );
QgsDebugMsg( tr( "Converted %1 meters to %2 mapunits" ).arg( meters ).arg( meters / unitDistance ) );
return meters / unitDistance;
}
/*
*
* Public functions
*
*/

bool HeatmapGui::weighted()
{
return useWeight->isChecked();
}

bool HeatmapGui::variableRadius()
{
return useRadius->isChecked();
}

float HeatmapGui::radius()
{
float radius = mBufferLineEdit->text().toInt();
if ( mRadiusUnitCombo->currentIndex() == HeatmapGui::Meters )
{
radius = mapUnitsOf( radius, inputVectorLayer()->crs() );
}
return radius;
}

int HeatmapGui::radiusUnit()
{
if ( useRadius->isChecked() )
{
return radiusFieldUnitCombo->currentIndex();
}
return mRadiusUnitCombo->currentIndex();
}

float HeatmapGui::decayRatio()
{
return mDecayLineEdit->text().toFloat();
}

int HeatmapGui::radiusField()
{
int radiusindex;
radiusindex = radiusFieldCombo->currentIndex();
return radiusFieldCombo->itemData( radiusindex ).toInt();
}

int HeatmapGui::weightField()
{
int weightindex;
weightindex = weightFieldCombo->currentIndex();
return weightFieldCombo->itemData( weightindex ).toInt();
}

QString HeatmapGui::outputFilename()
{
QString outputFileName;
QString outputFormat;

outputFileName = mOutputRasterLineEdit->text();
QFileInfo myFileInfo( outputFileName );
if ( outputFileName.isEmpty() || !myFileInfo.dir().exists() )
{
QMessageBox::information( 0, tr( "Invalid output filename" ), tr( "Please enter a valid output file path and name." ) );
return NULL;
}

// The output format
outputFormat = mFormatCombo->itemData( mFormatCombo->currentIndex() ).toString();
// append the file format if the suffix is empty
QString suffix = myFileInfo.suffix();
if ( suffix.isEmpty() )
{
QMap<QString, QString>::const_iterator it = mExtensionMap.find( outputFormat );
if ( it != mExtensionMap.end() && it.key() == outputFormat )
{
// making sure that there is really a extension value available
// Some drivers donot seem to have any extension at all
if ( it.value() != NULL || it.value() != "" )
{
outputFileName.append( "." );
outputFileName.append( it.value() );
}
}
}

return outputFileName;
}

QString HeatmapGui::outputFormat()
{
return mFormatCombo->itemData( mFormatCombo->currentIndex() ).toString();
}

QgsVectorLayer* HeatmapGui::inputVectorLayer()
{
QString myLayerId = mInputVectorCombo->itemData( mInputVectorCombo->currentIndex() ).toString();

QgsVectorLayer* inputLayer = qobject_cast<QgsVectorLayer *>( QgsMapLayerRegistry::instance()->mapLayer( myLayerId ) );
if ( !inputLayer )
{
QMessageBox::information( 0, tr( "Layer not found" ), tr( "Layer %1 not found." ).arg( myLayerId ) );
return NULL;
}
return inputLayer;
}

101 changes: 86 additions & 15 deletions src/plugins/heatmap/heatmapgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
#include <ui_heatmapguibase.h>

#include "qgsvectorlayer.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsgeometry.h"
/**
@author Tim Sutton
@author Arunmozhi
*/
class HeatmapGui : public QDialog, private Ui::HeatmapGuiBase
{
Expand All @@ -26,29 +28,98 @@ class HeatmapGui : public QDialog, private Ui::HeatmapGuiBase
HeatmapGui( QWidget* parent = 0, Qt::WFlags fl = 0 );
~HeatmapGui();

// Buffer unit type
// Should have been private, made public to be used in heatmap.cpp
enum mBufferType
{
Meters,
MapUnits
};

/** Returns whether to apply weighted heat */
bool weighted();

/** Returns whether the radius is static or based on a field */
bool variableRadius();

/** Returns the fixed radius value */
float radius();

/** Return the radius Unit (meters/map units) */
int radiusUnit();

/** Return the decay ratio */
float decayRatio();

/** Return the attribute field for variable radius */
int radiusField();

/** Returns the attrinute field for weighted heat */
int weightField();

/** Returns the output filename/path */
QString outputFilename();

/** Returns the GDAL Format for output raster */
QString outputFormat();

/** Returns the input Vector layer */
QgsVectorLayer* inputVectorLayer();

/** Returns the no of rows for the raster */
int rows() { return mRows; }

/** Returns the no of columns in the raster */
int columns() { return mColumns; }

/** Returns the cell size X value */
float cellSizeX() { return mXcellsize; }

/** Returns the cell size Y valuue */
float cellSizeY() { return mYcellsize; }

/** Return the BBox */
QgsRectangle bbox() { return mBBox; }

private:
QMap<QString, QString> mExtensionMap;

// bbox of layer for lineedit changes
QgsRectangle mBBox;
float mXcellsize, mYcellsize;
int mRows, mColumns;

/** Function to check wether all constrains are satisfied and enable the OK button */
void enableOrDisableOkButton();

/** Populate the attribute fields from selected vector for radius&weight */
void populateFields();

/** Set the mBBox value - mainly used for updation purpose */
void updateBBox();

/** Update the LineEdits cellsize and row&col values */
void updateSize();

/** Convert Maters value to the corresponding map units based on Layer projection */
float mapUnitsOf( float meters, QgsCoordinateReferenceSystem layerCrs );

private slots:
void on_mButtonBox_accepted();
void on_mButtonBox_rejected();
void on_mButtonBox_helpRequested();
void on_mBrowseButton_clicked(); // Function to open the file dialog
void on_mBrowseButton_clicked();
void on_mOutputRasterLineEdit_editingFinished();

signals:
/*
* Signal: createRaster
* Params:
* QgsVectorLayer* -> Input point layer
* int -> Buffer distance
* float -> Decay ratio
* QString -> Output filename
* QString -> Output Format Short Name
*/
void createRaster( QgsVectorLayer*, int, float, QString, QString );

void on_advancedGroupBox_toggled( bool enabled );
void on_rowLineEdit_editingFinished();
void on_columnLineEdit_editingFinished();
void on_cellXLineEdit_editingFinished();
void on_cellYLineEdit_editingFinished();
void on_radiusFieldCombo_currentIndexChanged( int index );
void on_radiusFieldUnitCombo_currentIndexChanged( int index );
void on_mRadiusUnitCombo_currentIndexChanged( int index );
void on_mInputVectorCombo_currentIndexChanged( int index );
void on_mBufferLineEdit_editingFinished();
};

#endif
350 changes: 300 additions & 50 deletions src/plugins/heatmap/heatmapguibase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@
<rect>
<x>0</x>
<y>0</y>
<width>428</width>
<height>254</height>
<width>430</width>
<height>380</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>430</width>
<height>380</height>
</size>
</property>
<property name="windowTitle">
<string>Heatmap Plugin</string>
</property>
Expand Down Expand Up @@ -37,6 +43,19 @@
<item row="1" column="1">
<widget class="QLineEdit" name="mOutputRasterLineEdit"/>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="mBrowseButton">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="text">
<string>...</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="mFormatLabel">
<property name="text">
Expand All @@ -47,61 +66,196 @@
<item row="3" column="1" colspan="2">
<widget class="QComboBox" name="mFormatCombo"/>
</item>
<item row="4" column="0" colspan="3">
<widget class="QGroupBox" name="mPointAttributeBox">
<property name="title">
<string>Heatmap Point Attributes</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="mBufferLabel">
<property name="text">
<string>Buffer Radius</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="mBufferLineEdit">
<property name="text">
<string>10</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="mDecayLabel">
<property name="text">
<string>Decay Ratio</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="mDecayLineEdit">
<property name="text">
<string>0.5</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="0" colspan="3">
<item row="9" column="0" colspan="3">
<widget class="QDialogButtonBox" name="mButtonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Help|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="mBrowseButton">
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
<item row="4" column="0">
<widget class="QLabel" name="mRadiusLabel">
<property name="text">
<string>Radius</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="mBufferLineEdit">
<property name="text">
<string>...</string>
<string>10</string>
</property>
<property name="autoDefault">
</widget>
</item>
<item row="4" column="2">
<widget class="QComboBox" name="mRadiusUnitCombo">
<item>
<property name="text">
<string>meters</string>
</property>
</item>
<item>
<property name="text">
<string>map units</string>
</property>
</item>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="mDecayLabel">
<property name="text">
<string>Decay Ratio</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QLineEdit" name="mDecayLineEdit">
<property name="text">
<string>0.1</string>
</property>
</widget>
</item>
<item row="6" column="0" colspan="3">
<widget class="QGroupBox" name="advancedGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Advanced</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<widget class="QWidget" name="gridLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>391</width>
<height>61</height>
</rect>
</property>
<layout class="QGridLayout" name="advancedGrid">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<item row="0" column="0">
<widget class="QLabel" name="rowLabel">
<property name="text">
<string>Row</string>
</property>
<property name="buddy">
<cstring>rowLineEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="cellsizeXLabel">
<property name="text">
<string>Cell Size X</string>
</property>
<property name="buddy">
<cstring>cellXLineEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="columnLabel">
<property name="text">
<string>Column</string>
</property>
<property name="buddy">
<cstring>columnLineEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="cellsizeYLabel">
<property name="text">
<string>Cell Size Y</string>
</property>
<property name="buddy">
<cstring>cellYLineEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="rowLineEdit"/>
</item>
<item row="0" column="3">
<widget class="QLineEdit" name="columnLineEdit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="cellXLineEdit"/>
</item>
<item row="1" column="3">
<widget class="QLineEdit" name="cellYLineEdit"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="gridLayoutWidget_4">
<property name="geometry">
<rect>
<x>10</x>
<y>90</y>
<width>391</width>
<height>61</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QCheckBox" name="useRadius">
<property name="text">
<string>Use Radius from field</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="radiusFieldCombo">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="radiusFieldUnitCombo">
<property name="enabled">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>meters</string>
</property>
</item>
<item>
<property name="text">
<string>map units</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="useWeight">
<property name="text">
<string>Use Weight from field</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QComboBox" name="weightFieldCombo">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
Expand All @@ -115,8 +269,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>195</x>
<y>123</y>
<x>213</x>
<y>370</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
Expand All @@ -131,14 +285,110 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>195</x>
<y>123</y>
<x>213</x>
<y>370</y>
</hint>
<hint type="destinationlabel">
<x>199</x>
<y>79</y>
</hint>
</hints>
</connection>
<connection>
<sender>useWeight</sender>
<signal>toggled(bool)</signal>
<receiver>weightFieldCombo</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>109</x>
<y>315</y>
</hint>
<hint type="destinationlabel">
<x>408</x>
<y>318</y>
</hint>
</hints>
</connection>
<connection>
<sender>useRadius</sender>
<signal>toggled(bool)</signal>
<receiver>radiusFieldCombo</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>108</x>
<y>283</y>
</hint>
<hint type="destinationlabel">
<x>294</x>
<y>286</y>
</hint>
</hints>
</connection>
<connection>
<sender>useRadius</sender>
<signal>toggled(bool)</signal>
<receiver>radiusFieldUnitCombo</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>108</x>
<y>283</y>
</hint>
<hint type="destinationlabel">
<x>408</x>
<y>286</y>
</hint>
</hints>
</connection>
<connection>
<sender>useRadius</sender>
<signal>toggled(bool)</signal>
<receiver>mBufferLineEdit</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>108</x>
<y>283</y>
</hint>
<hint type="destinationlabel">
<x>325</x>
<y>131</y>
</hint>
</hints>
</connection>
<connection>
<sender>useRadius</sender>
<signal>toggled(bool)</signal>
<receiver>mRadiusUnitCombo</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>108</x>
<y>283</y>
</hint>
<hint type="destinationlabel">
<x>420</x>
<y>131</y>
</hint>
</hints>
</connection>
<connection>
<sender>useRadius</sender>
<signal>toggled(bool)</signal>
<receiver>mRadiusLabel</receiver>
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>83</x>
<y>275</y>
</hint>
<hint type="destinationlabel">
<x>58</x>
<y>116</y>
</hint>
</hints>
</connection>
</connections>
</ui>