Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make QgsVectorLayer uniqueValues/min/maxValue consider edits
Previously these methods would inconsistently handle the
edit buffer, eg uniqueValues would consider changed attributes
but not added features. Now uniqueValues, minimumValue and
maximumValue all consider both added features and changed
attribute values when performing their calculation.

The most noticable effect of this fix is that the unique
values widget now correctly shows values for features which
have been added but not yet committed to the provider.

(cherry-picked from 50c3592)
  • Loading branch information
nyalldawson committed Aug 17, 2016
1 parent e37ffd0 commit 64b7def
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 10 deletions.
26 changes: 22 additions & 4 deletions python/core/qgsvectorlayer.sip
Expand Up @@ -1317,17 +1317,35 @@ class QgsVectorLayer : QgsMapLayer
/** Caches joined attributes if required (and not already done) */
void createJoinCaches();

/** Returns unique values for column
/** Calculates a list of unique values contained within an attribute in the layer. Note that
* in some circumstances when unsaved changes are present for the layer then the returned list
* may contain outdated values (for instance when the attribute value in a saved feature has
* been changed inside the edit buffer then the previous saved value will be included in the
* returned list).
* @param index column index for attribute
* @param uniqueValues out: result list
* @param limit maximum number of values to return (-1 if unlimited)
* @param limit maximum number of values to return (or -1 if unlimited)
* @see minimumValue()
* @see maximumValue()
*/
void uniqueValues( int index, QList<QVariant> &uniqueValues /Out/, int limit = -1 );

/** Returns minimum value for an attribute column or invalid variant in case of error */
/** Returns the minimum value for an attribute column or an invalid variant in case of error.
* Note that in some circumstances when unsaved changes are present for the layer then the
* returned value may be outdated (for instance when the attribute value in a saved feature has
* been changed inside the edit buffer then the previous saved value may be returned as the minimum).
* @see maximumValue()
* @see uniqueValues()
*/
QVariant minimumValue( int index );

/** Returns maximum value for an attribute column or invalid variant in case of error */
/** Returns the maximum value for an attribute column or an invalid variant in case of error.
* Note that in some circumstances when unsaved changes are present for the layer then the
* returned value may be outdated (for instance when the attribute value in a saved feature has
* been changed inside the edit buffer then the previous saved value may be returned as the maximum).
* @see minimumValue()
* @see uniqueValues()
*/
QVariant maximumValue( int index );

/** Calculates an aggregated value from the layer's features.
Expand Down
77 changes: 75 additions & 2 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -3156,6 +3156,23 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
vals << v.toString();
}

QgsFeatureMap added = mEditBuffer->addedFeatures();
QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
while ( addedIt.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
{
addedIt.next();
QVariant v = addedIt.value().attribute( index );
if ( v.isValid() )
{
QString vs = v.toString();
if ( !vals.contains( vs ) )
{
vals << vs;
uniqueValues << v;
}
}
}

QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
while ( it.hasNext() && ( limit < 0 || uniqueValues.count() < limit ) )
{
Expand Down Expand Up @@ -3234,7 +3251,35 @@ QVariant QgsVectorLayer::minimumValue( int index )
return QVariant();

case QgsFields::OriginProvider: //a provider field
return mDataProvider->minimumValue( index );
{
QVariant min = mDataProvider->minimumValue( index );
if ( mEditBuffer )
{
QgsFeatureMap added = mEditBuffer->addedFeatures();
QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
while ( addedIt.hasNext() )
{
addedIt.next();
QVariant v = addedIt.value().attribute( index );
if ( v.isValid() && qgsVariantLessThan( v, min ) )
{
min = v;
}
}

QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
while ( it.hasNext() )
{
it.next();
QVariant v = it.value().value( index );
if ( v.isValid() && qgsVariantLessThan( v, min ) )
{
min = v;
}
}
}
return min;
}

case QgsFields::OriginEdit:
{
Expand Down Expand Up @@ -3293,7 +3338,35 @@ QVariant QgsVectorLayer::maximumValue( int index )
return QVariant();

case QgsFields::OriginProvider: //a provider field
return mDataProvider->maximumValue( index );
{
QVariant min = mDataProvider->maximumValue( index );
if ( mEditBuffer )
{
QgsFeatureMap added = mEditBuffer->addedFeatures();
QMapIterator< QgsFeatureId, QgsFeature > addedIt( added );
while ( addedIt.hasNext() )
{
addedIt.next();
QVariant v = addedIt.value().attribute( index );
if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
{
min = v;
}
}

QMapIterator< QgsFeatureId, QgsAttributeMap > it( mEditBuffer->changedAttributeValues() );
while ( it.hasNext() )
{
it.next();
QVariant v = it.value().value( index );
if ( v.isValid() && qgsVariantGreaterThan( v, min ) )
{
min = v;
}
}
}
return min;
}

case QgsFields::OriginEdit:
// the layer is editable, but in certain cases it can still be avoided going through all features
Expand Down
26 changes: 22 additions & 4 deletions src/core/qgsvectorlayer.h
Expand Up @@ -1707,17 +1707,35 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
/** Caches joined attributes if required (and not already done) */
void createJoinCaches();

/** Returns unique values for column
/** Calculates a list of unique values contained within an attribute in the layer. Note that
* in some circumstances when unsaved changes are present for the layer then the returned list
* may contain outdated values (for instance when the attribute value in a saved feature has
* been changed inside the edit buffer then the previous saved value will be included in the
* returned list).
* @param index column index for attribute
* @param uniqueValues out: result list
* @param limit maximum number of values to return (-1 if unlimited)
* @param limit maximum number of values to return (or -1 if unlimited)
* @see minimumValue()
* @see maximumValue()
*/
void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 );

/** Returns minimum value for an attribute column or invalid variant in case of error */
/** Returns the minimum value for an attribute column or an invalid variant in case of error.
* Note that in some circumstances when unsaved changes are present for the layer then the
* returned value may be outdated (for instance when the attribute value in a saved feature has
* been changed inside the edit buffer then the previous saved value may be returned as the minimum).
* @see maximumValue()
* @see uniqueValues()
*/
QVariant minimumValue( int index );

/** Returns maximum value for an attribute column or invalid variant in case of error */
/** Returns the maximum value for an attribute column or an invalid variant in case of error.
* Note that in some circumstances when unsaved changes are present for the layer then the
* returned value may be outdated (for instance when the attribute value in a saved feature has
* been changed inside the edit buffer then the previous saved value may be returned as the maximum).
* @see minimumValue()
* @see uniqueValues()
*/
QVariant maximumValue( int index );

/** Calculates an aggregated value from the layer's features.
Expand Down

0 comments on commit 64b7def

Please sign in to comment.