Skip to content

Commit df6c710

Browse files
committed
Use QgsStatisticalSummary for merge attributes dialog
Adds a bunch of new stats and avoids code duplication
1 parent cdf21b7 commit df6c710

File tree

2 files changed

+52
-159
lines changed

2 files changed

+52
-159
lines changed

src/app/qgsmergeattributesdialog.cpp

+42-149
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,29 @@
2525
#include "qgsvectorlayer.h"
2626
#include "qgsvectordataprovider.h"
2727
#include "qgsattributeeditor.h"
28+
#include "qgsstatisticalsummary.h"
2829

2930
#include <limits>
3031
#include <QComboBox>
3132
#include <QSettings>
3233

34+
QList< QgsStatisticalSummary::Statistic > QgsMergeAttributesDialog::mDisplayStats =
35+
QList< QgsStatisticalSummary::Statistic > () << QgsStatisticalSummary::Count
36+
<< QgsStatisticalSummary::Sum
37+
<< QgsStatisticalSummary::Mean
38+
<< QgsStatisticalSummary::Median
39+
<< QgsStatisticalSummary::StDev
40+
<< QgsStatisticalSummary::StDevSample
41+
<< QgsStatisticalSummary::Min
42+
<< QgsStatisticalSummary::Max
43+
<< QgsStatisticalSummary::Range
44+
<< QgsStatisticalSummary::Minority
45+
<< QgsStatisticalSummary::Majority
46+
<< QgsStatisticalSummary::Variety
47+
<< QgsStatisticalSummary::FirstQuartile
48+
<< QgsStatisticalSummary::ThirdQuartile
49+
<< QgsStatisticalSummary::InterQuartileRange;
50+
3351
QgsMergeAttributesDialog::QgsMergeAttributesDialog( const QgsFeatureList &features, QgsVectorLayer *vl, QgsMapCanvas *canvas, QWidget *parent, Qt::WindowFlags f )
3452
: QDialog( parent, f )
3553
, mFeatureList( features )
@@ -152,16 +170,15 @@ QComboBox *QgsMergeAttributesDialog::createMergeComboBox( QVariant::Type columnT
152170
QgsFeatureList::const_iterator f_it = mFeatureList.constBegin();
153171
for ( ; f_it != mFeatureList.constEnd(); ++f_it )
154172
{
155-
newComboBox->addItem( tr( "Feature %1" ).arg( f_it->id() ), QString::number( f_it->id() ) );
173+
newComboBox->addItem( tr( "Feature %1" ).arg( f_it->id() ), QString( "f%1" ).arg( f_it->id() ) );
156174
}
157175

158176
if ( columnType == QVariant::Double || columnType == QVariant::Int )
159177
{
160-
newComboBox->addItem( tr( "Minimum" ), "minimum" );
161-
newComboBox->addItem( tr( "Maximum" ), "maximum" );
162-
newComboBox->addItem( tr( "Median" ), "median" );
163-
newComboBox->addItem( tr( "Sum" ), "sum" );
164-
newComboBox->addItem( tr( "Mean" ), "mean" );
178+
Q_FOREACH ( QgsStatisticalSummary::Statistic stat, mDisplayStats )
179+
{
180+
newComboBox->addItem( QgsStatisticalSummary::displayName( stat ) , stat );
181+
}
165182
}
166183
else if ( columnType == QVariant::String )
167184
{
@@ -250,39 +267,26 @@ void QgsMergeAttributesDialog::refreshMergedValue( int col )
250267
//evaluate behaviour (feature value or min / max / mean )
251268
QString mergeBehaviourString = comboBox->itemData( comboBox->currentIndex() ).toString();
252269
QVariant mergeResult; // result to show in the merge result field
253-
if ( mergeBehaviourString == "minimum" )
254-
{
255-
mergeResult = minimumAttribute( col );
256-
}
257-
else if ( mergeBehaviourString == "maximum" )
258-
{
259-
mergeResult = maximumAttribute( col );
260-
}
261-
else if ( mergeBehaviourString == "mean" )
262-
{
263-
mergeResult = meanAttribute( col );
264-
}
265-
else if ( mergeBehaviourString == "median" )
266-
{
267-
mergeResult = medianAttribute( col );
268-
}
269-
else if ( mergeBehaviourString == "sum" )
270-
{
271-
mergeResult = sumAttribute( col );
272-
}
273-
else if ( mergeBehaviourString == "concat" )
270+
if ( mergeBehaviourString == "concat" )
274271
{
275272
mergeResult = concatenationAttribute( col );
276273
}
277274
else if ( mergeBehaviourString == "skip" )
278275
{
279276
mergeResult = tr( "Skipped" );
280277
}
281-
else //an existing feature value
278+
else if ( mergeBehaviourString.startsWith( "f" ) )
282279
{
283-
int featureId = mergeBehaviourString.toInt();
280+
//an existing feature value - TODO should be QgsFeatureId, not int
281+
int featureId = mergeBehaviourString.mid( 1 ).toInt();
284282
mergeResult = featureAttribute( featureId, col );
285283
}
284+
else
285+
{
286+
//numerical statistic
287+
QgsStatisticalSummary::Statistic stat = ( QgsStatisticalSummary::Statistic )( comboBox->itemData( comboBox->currentIndex() ).toInt() );
288+
mergeResult = calcStatistic( col, stat );
289+
}
286290

287291
//insert string into table widget
288292
QTableWidgetItem* newTotalItem = new QTableWidgetItem();
@@ -311,141 +315,30 @@ QVariant QgsMergeAttributesDialog::featureAttribute( int featureId, int col )
311315
}
312316
}
313317

314-
QVariant QgsMergeAttributesDialog::minimumAttribute( int col )
315-
{
316-
double minimumValue = std::numeric_limits<double>::max();
317-
double currentValue;
318-
bool conversion = false;
319-
int numberOfConsideredFeatures = 0;
320318

321-
for ( int i = 0; i < mFeatureList.size(); ++i )
322-
{
323-
currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion );
324-
if ( conversion )
325-
{
326-
if ( currentValue < minimumValue )
327-
{
328-
minimumValue = currentValue;
329-
++numberOfConsideredFeatures;
330-
}
331-
}
332-
}
333-
334-
if ( numberOfConsideredFeatures < 1 )
335-
{
336-
return QVariant( mVectorLayer->fields().at( col ).type() );
337-
}
338-
339-
return QVariant( minimumValue );
340-
}
341-
342-
QVariant QgsMergeAttributesDialog::maximumAttribute( int col )
319+
QVariant QgsMergeAttributesDialog::calcStatistic( int col, QgsStatisticalSummary::Statistic stat )
343320
{
344-
double maximumValue = -std::numeric_limits<double>::max();
345-
double currentValue;
346-
bool conversion = false;
347-
int numberOfConsideredFeatures = 0;
348-
349-
for ( int i = 0; i < mFeatureList.size(); ++i )
350-
{
351-
currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion );
352-
if ( conversion )
353-
{
354-
if ( currentValue > maximumValue )
355-
{
356-
maximumValue = currentValue;
357-
++numberOfConsideredFeatures;
358-
}
359-
}
360-
}
361-
362-
if ( numberOfConsideredFeatures < 1 )
363-
{
364-
return QVariant( mVectorLayer->fields().at( col ).type() );
365-
}
366-
367-
return QVariant( maximumValue );
368-
}
321+
QgsStatisticalSummary summary( stat );
369322

370-
QVariant QgsMergeAttributesDialog::meanAttribute( int col )
371-
{
372-
int numberOfConsideredFeatures = 0;
373-
double currentValue;
374-
double sum = 0;
375323
bool conversion = false;
376-
324+
QList<double> values;
377325
for ( int i = 0; i < mFeatureList.size(); ++i )
378326
{
379-
currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion );
327+
double currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion );
380328
if ( conversion )
381329
{
382-
sum += currentValue;
383-
++numberOfConsideredFeatures;
330+
values << currentValue;
384331
}
385332
}
386333

387-
if ( numberOfConsideredFeatures < 1 )
334+
if ( values.isEmpty() )
388335
{
389-
return QVariant( mVectorLayer->fields().at( col ).type() );
336+
return QVariant( mVectorLayer->fields()[col].type() );
390337
}
391338

392-
double mean = sum / numberOfConsideredFeatures;
393-
return QVariant( mean );
394-
}
395-
396-
QVariant QgsMergeAttributesDialog::medianAttribute( int col )
397-
{
398-
//bring all values into a list and sort
399-
QList<double> valueList;
400-
double currentValue;
401-
bool conversionSuccess;
402-
403-
for ( int i = 0; i < mFeatureList.size(); ++i )
404-
{
405-
currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversionSuccess );
406-
if ( !conversionSuccess )
407-
{
408-
continue;
409-
}
410-
valueList.push_back( currentValue );
411-
}
412-
qSort( valueList );
413-
414-
double medianValue;
415-
int size = valueList.size();
416-
339+
summary.calculate( values );
417340

418-
if ( size < 1 )
419-
{
420-
return QVariant( mVectorLayer->fields().at( col ).type() );
421-
}
422-
423-
bool even = ( size % 2 ) < 1;
424-
if ( even )
425-
{
426-
medianValue = ( valueList[size / 2 - 1] + valueList[size / 2] ) / 2;
427-
}
428-
else //odd
429-
{
430-
medianValue = valueList[( size + 1 ) / 2 - 1];
431-
}
432-
return QVariant( medianValue );
433-
}
434-
435-
QVariant QgsMergeAttributesDialog::sumAttribute( int col )
436-
{
437-
double sum = 0.0;
438-
bool conversion = false;
439-
440-
for ( int i = 0; i < mFeatureList.size(); ++i )
441-
{
442-
double currentValue = mTableWidget->item( i + 1, col )->text().toDouble( &conversion );
443-
if ( conversion )
444-
{
445-
sum += currentValue;
446-
}
447-
}
448-
return QVariant( sum );
341+
return QVariant::fromValue( summary.statistic( stat ) );
449342
}
450343

451344
QVariant QgsMergeAttributesDialog::concatenationAttribute( int col )

src/app/qgsmergeattributesdialog.h

+10-10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include "ui_qgsmergeattributesdialogbase.h"
2323
#include "qgsfeature.h"
24+
#include "qgsstatisticalsummary.h"
2425

2526
class QgsMapCanvas;
2627
class QgsRubberBand;
@@ -67,18 +68,14 @@ class APP_EXPORT QgsMergeAttributesDialog: public QDialog, private Ui::QgsMergeA
6768
void refreshMergedValue( int col );
6869
/** Inserts the attribute value of a specific feature into the row of merged attributes*/
6970
QVariant featureAttribute( int featureId, int col );
70-
/** Calculates and inserts the minimum attribute value of a column*/
71-
QVariant minimumAttribute( int col );
72-
/** Calculates and inserts the maximum value of a column*/
73-
QVariant maximumAttribute( int col );
74-
/** Calculates and inserts the mean value of a column*/
75-
QVariant meanAttribute( int col );
76-
/** Calculates and inserts the median value of a column*/
77-
QVariant medianAttribute( int col );
78-
/** Calculates and inserts the sum of a column*/
79-
QVariant sumAttribute( int col );
8071
/** Appends the values of the features for the final value*/
8172
QVariant concatenationAttribute( int col );
73+
74+
/** Calculates a summary statistic for a column. Returns null if no valid numerical
75+
* values found in column.
76+
*/
77+
QVariant calcStatistic( int col, QgsStatisticalSummary::Statistic stat );
78+
8279
/** Sets mSelectionRubberBand to a new feature*/
8380
void createRubberBandForFeature( int featureId );
8481

@@ -87,6 +84,9 @@ class APP_EXPORT QgsMergeAttributesDialog: public QDialog, private Ui::QgsMergeA
8784
QgsMapCanvas* mMapCanvas;
8885
/** Item that highlights the selected feature in the merge table*/
8986
QgsRubberBand* mSelectionRubberBand;
87+
88+
static QList< QgsStatisticalSummary::Statistic > mDisplayStats;
89+
9090
};
9191

9292
#endif // QGSMERGEATTRIBUTESDIALOG_H

0 commit comments

Comments
 (0)