mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Move uniqueValues to QgsFeatureSource
Also change signature of QgsVectorLayer/QgsVectorDataProvider uniqueValues method to match (and improve API)
This commit is contained in:
parent
f69d1c2065
commit
3388857526
@ -2275,6 +2275,7 @@ clause fragment which must be evaluated by the provider in order to calculate th
|
||||
QGIS 3.0 defaultValue() only returns literal, constant defaultValues. A new method defaultValueClause
|
||||
has been added which returns the SQL clause fragments which must be evaluated by the provider itself.
|
||||
- isSaveAndLoadStyleToDBSupported() was renamed to isSaveAndLoadStyleToDatabaseSupported()
|
||||
- The c++ signature for uniqueValues() has changed (the PyQGIS method remains unchanged)
|
||||
|
||||
|
||||
QgsVectorJoinInfo {#qgis_api_break_3_0_QgsVectorJoinInfo}
|
||||
@ -2335,6 +2336,7 @@ displayExpression instead. For the map tip use mapTipTemplate() instead.
|
||||
- addFeatures() no longer accepts a makeSelected boolean, and will not automatically select newly added features. If desired, features must be manually selected by calling selectByIds() after addFeatures()
|
||||
- annotationForm() and setAnnotationForm() have been removed. Form path is stored in individual QgsFormAnnotation objects.
|
||||
- setLayerTransparency, layerTransparency, and layerTransparencyChanged were removed. Use opacity, setOpacity and opacityChanged instead.
|
||||
- The c++ signature for uniqueValues() has changed (the PyQGIS method remains unchanged)
|
||||
|
||||
|
||||
QgsVectorLayerEditBuffer {#qgis_api_break_3_0_QgsVectorLayerEditBuffer}
|
||||
|
@ -69,6 +69,15 @@ class QgsFeatureSource
|
||||
:rtype: long
|
||||
%End
|
||||
|
||||
virtual QSet<QVariant> uniqueValues( int fieldIndex, int limit = -1 ) const;
|
||||
%Docstring
|
||||
Returns the set of unique values contained within the specified ``fieldIndex`` from this source.
|
||||
If specified, the ``limit`` option can be used to limit the number of returned values.
|
||||
The base class implementation uses a non-optimised approach of looping through
|
||||
all features in the source.
|
||||
:rtype: set of QVariant
|
||||
%End
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -156,16 +156,6 @@ Bitmask of all provider's editing capabilities
|
||||
:rtype: QVariant
|
||||
%End
|
||||
|
||||
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues /Out/, int limit = -1 ) const;
|
||||
%Docstring
|
||||
Return unique values of an attribute
|
||||
\param index the index of the attribute
|
||||
\param uniqueValues values reference to the list to fill
|
||||
\param limit maxmum number of the values to return
|
||||
|
||||
Default implementation simply iterates the features
|
||||
%End
|
||||
|
||||
virtual QStringList uniqueStringsMatching( int index, const QString &substring, int limit = -1,
|
||||
QgsFeedback *feedback = 0 ) const;
|
||||
%Docstring
|
||||
|
@ -1507,18 +1507,19 @@ Assembles mUpdatedFields considering provider fields, joined fields and added fi
|
||||
:rtype: QgsEditorWidgetSetup
|
||||
%End
|
||||
|
||||
void uniqueValues( int index, QList<QVariant> &uniqueValues /Out/, int limit = -1 ) const;
|
||||
virtual QSet<QVariant> uniqueValues( int fieldIndex, int limit = -1 ) const;
|
||||
|
||||
%Docstring
|
||||
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 fieldIndex column index for attribute
|
||||
\param limit maximum number of values to return (or -1 if unlimited)
|
||||
.. seealso:: minimumValue()
|
||||
.. seealso:: maximumValue()
|
||||
:rtype: set of QVariant
|
||||
%End
|
||||
|
||||
QStringList uniqueStringsMatching( int index, const QString &substring, int limit = -1,
|
||||
|
@ -158,6 +158,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgsfeatureiterator.cpp
|
||||
qgsfeaturerequest.cpp
|
||||
qgsfeaturesink.cpp
|
||||
qgsfeaturesource.cpp
|
||||
qgsfeaturestore.cpp
|
||||
qgsfield.cpp
|
||||
qgsfieldconstraints.cpp
|
||||
|
@ -787,8 +787,7 @@ void QgsDxfExport::writeTables()
|
||||
}
|
||||
else
|
||||
{
|
||||
QList<QVariant> values;
|
||||
vl->uniqueValues( attrIdx, values );
|
||||
QSet<QVariant> values = vl->uniqueValues( attrIdx );
|
||||
Q_FOREACH ( const QVariant &v, values )
|
||||
{
|
||||
layerNames << dxfLayerName( v.toString() );
|
||||
|
@ -274,9 +274,8 @@ QList<QVariant> QgsProcessingUtils::uniqueValues( QgsVectorLayer *layer, int fie
|
||||
if ( !useSelection )
|
||||
{
|
||||
// not using selection, so use provider optimised version
|
||||
QList<QVariant> values;
|
||||
layer->uniqueValues( fieldIndex, values );
|
||||
return values;
|
||||
QSet<QVariant> values = layer->uniqueValues( fieldIndex );
|
||||
return values.toList();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -173,7 +173,7 @@ template<class Object> inline QgsSignalBlocker<Object> whileBlocking( Object *ob
|
||||
}
|
||||
|
||||
//! Hash for QVariant
|
||||
uint qHash( const QVariant &variant );
|
||||
CORE_EXPORT uint qHash( const QVariant &variant );
|
||||
|
||||
//! Returns a string representation of a double
|
||||
//! \param a double value
|
||||
|
42
src/core/qgsfeaturesource.cpp
Normal file
42
src/core/qgsfeaturesource.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
qgsfeaturesource.cpp
|
||||
-------------------
|
||||
begin : May 2017
|
||||
copyright : (C) 2017 by Nyall Dawson
|
||||
email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsfeaturesource.h"
|
||||
#include "qgsfeaturerequest.h"
|
||||
#include "qgsfeatureiterator.h"
|
||||
|
||||
QSet<QVariant> QgsFeatureSource::uniqueValues( int fieldIndex, int limit ) const
|
||||
{
|
||||
if ( fieldIndex < 0 || fieldIndex >= fields().count() )
|
||||
return QSet<QVariant>();
|
||||
|
||||
QgsFeatureRequest req;
|
||||
req.setFlags( QgsFeatureRequest::NoGeometry );
|
||||
req.setSubsetOfAttributes( QgsAttributeList() << fieldIndex );
|
||||
|
||||
QSet<QVariant> values;
|
||||
QgsFeatureIterator it = getFeatures( req );
|
||||
QgsFeature f;
|
||||
while ( it.nextFeature( f ) )
|
||||
{
|
||||
values.insert( f.attribute( fieldIndex ) );
|
||||
if ( limit > 0 && values.size() >= limit )
|
||||
return values;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
10
src/core/qgsfeaturesource.h
Executable file → Normal file
10
src/core/qgsfeaturesource.h
Executable file → Normal file
@ -20,9 +20,9 @@
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis.h"
|
||||
#include "qgsfeaturerequest.h"
|
||||
|
||||
class QgsFeatureIterator;
|
||||
class QgsFeatureRequest;
|
||||
class QgsCoordinateReferenceSystem;
|
||||
class QgsFields;
|
||||
|
||||
@ -79,6 +79,14 @@ class CORE_EXPORT QgsFeatureSource
|
||||
*/
|
||||
virtual long featureCount() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the set of unique values contained within the specified \a fieldIndex from this source.
|
||||
* If specified, the \a limit option can be used to limit the number of returned values.
|
||||
* The base class implementation uses a non-optimised approach of looping through
|
||||
* all features in the source.
|
||||
*/
|
||||
virtual QSet<QVariant> uniqueValues( int fieldIndex, int limit = -1 ) const;
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( QgsFeatureSource * )
|
||||
|
@ -433,28 +433,6 @@ QVariant QgsVectorDataProvider::maximumValue( int index ) const
|
||||
return mCacheMaxValues[index];
|
||||
}
|
||||
|
||||
void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit ) const
|
||||
{
|
||||
QgsFeature f;
|
||||
QgsAttributeList keys;
|
||||
keys.append( index );
|
||||
QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ).setFlags( QgsFeatureRequest::NoGeometry ) );
|
||||
|
||||
QSet<QString> set;
|
||||
values.clear();
|
||||
|
||||
while ( fi.nextFeature( f ) )
|
||||
{
|
||||
if ( !set.contains( f.attribute( index ).toString() ) )
|
||||
{
|
||||
values.append( f.attribute( index ) );
|
||||
set.insert( f.attribute( index ).toString() );
|
||||
}
|
||||
|
||||
if ( limit >= 0 && values.size() >= limit )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList QgsVectorDataProvider::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
|
||||
{
|
||||
|
@ -186,16 +186,6 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider, public QgsFeat
|
||||
*/
|
||||
virtual QVariant maximumValue( int index ) const;
|
||||
|
||||
/**
|
||||
* Return unique values of an attribute
|
||||
* \param index the index of the attribute
|
||||
* \param uniqueValues values reference to the list to fill
|
||||
* \param limit maxmum number of the values to return
|
||||
*
|
||||
* Default implementation simply iterates the features
|
||||
*/
|
||||
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues SIP_OUT, int limit = -1 ) const;
|
||||
|
||||
/**
|
||||
* Returns unique string values of an attribute which contain a specified subset string. Subset
|
||||
* matching is done in a case-insensitive manner.
|
||||
|
@ -3010,23 +3010,23 @@ QString QgsVectorLayer::defaultValueExpression( int index ) const
|
||||
return mFields.at( index ).defaultValueExpression();
|
||||
}
|
||||
|
||||
void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit ) const
|
||||
QSet<QVariant> QgsVectorLayer::uniqueValues( int index, int limit ) const
|
||||
{
|
||||
uniqueValues.clear();
|
||||
QSet<QVariant> uniqueValues;
|
||||
if ( !mDataProvider )
|
||||
{
|
||||
return;
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
QgsFields::FieldOrigin origin = mFields.fieldOrigin( index );
|
||||
switch ( origin )
|
||||
{
|
||||
case QgsFields::OriginUnknown:
|
||||
return;
|
||||
return uniqueValues;
|
||||
|
||||
case QgsFields::OriginProvider: //a provider field
|
||||
{
|
||||
mDataProvider->uniqueValues( index, uniqueValues, limit );
|
||||
uniqueValues = mDataProvider->uniqueValues( index, limit );
|
||||
|
||||
if ( mEditBuffer )
|
||||
{
|
||||
@ -3070,7 +3070,7 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
case QgsFields::OriginEdit:
|
||||
@ -3080,8 +3080,8 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
|
||||
!mEditBuffer->mDeletedAttributeIds.contains( index ) &&
|
||||
mEditBuffer->mChangedAttributeValues.isEmpty() )
|
||||
{
|
||||
mDataProvider->uniqueValues( index, uniqueValues, limit );
|
||||
return;
|
||||
uniqueValues = mDataProvider->uniqueValues( index, limit );
|
||||
return uniqueValues;
|
||||
}
|
||||
FALLTHROUGH;
|
||||
//we need to go through each feature
|
||||
@ -3108,12 +3108,12 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
|
||||
}
|
||||
}
|
||||
|
||||
uniqueValues = val.values();
|
||||
return;
|
||||
return val.values().toSet();
|
||||
}
|
||||
}
|
||||
|
||||
Q_ASSERT_X( false, "QgsVectorLayer::uniqueValues()", "Unknown source of the field!" );
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
QStringList QgsVectorLayer::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
|
||||
|
@ -1423,13 +1423,12 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer, public QgsExpressionConte
|
||||
* 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 fieldIndex column index for attribute
|
||||
* \param limit maximum number of values to return (or -1 if unlimited)
|
||||
* \see minimumValue()
|
||||
* \see maximumValue()
|
||||
*/
|
||||
void uniqueValues( int index, QList<QVariant> &uniqueValues SIP_OUT, int limit = -1 ) const;
|
||||
QSet<QVariant> uniqueValues( int fieldIndex, int limit = -1 ) const override;
|
||||
|
||||
/**
|
||||
* Returns unique string values of an attribute which contain a specified subset string. Subset
|
||||
|
@ -466,13 +466,12 @@ void QgsRelationReferenceWidget::init()
|
||||
{
|
||||
Q_FOREACH ( const QString &fieldName, mFilterFields )
|
||||
{
|
||||
QVariantList uniqueValues;
|
||||
int idx = mReferencedLayer->fields().lookupField( fieldName );
|
||||
QComboBox *cb = new QComboBox();
|
||||
cb->setProperty( "Field", fieldName );
|
||||
cb->setProperty( "FieldAlias", mReferencedLayer->attributeDisplayName( idx ) );
|
||||
mFilterComboBoxes << cb;
|
||||
mReferencedLayer->uniqueValues( idx, uniqueValues );
|
||||
QVariantList uniqueValues = mReferencedLayer->uniqueValues( idx ).toList();
|
||||
cb->addItem( mReferencedLayer->attributeDisplayName( idx ) );
|
||||
QVariant nullValue = QgsApplication::nullRepresentation();
|
||||
cb->addItem( nullValue.toString(), QVariant( mReferencedLayer->fields().at( idx ).type() ) );
|
||||
|
@ -61,9 +61,7 @@ void QgsUniqueValuesWidgetWrapper::initWidget( QWidget *editor )
|
||||
|
||||
QStringList sValues;
|
||||
|
||||
QList<QVariant> values;
|
||||
|
||||
layer()->uniqueValues( fieldIdx(), values );
|
||||
QSet< QVariant> values = layer()->uniqueValues( fieldIdx() );
|
||||
|
||||
Q_FOREACH ( const QVariant &v, values )
|
||||
{
|
||||
|
@ -336,9 +336,8 @@ void QgsExpressionBuilderWidget::fillFieldValues( const QString &fieldName, int
|
||||
if ( fieldIndex < 0 )
|
||||
return;
|
||||
|
||||
QList<QVariant> values;
|
||||
QStringList strValues;
|
||||
mLayer->uniqueValues( fieldIndex, values, countLimit );
|
||||
QSet<QVariant> values = mLayer->uniqueValues( fieldIndex, countLimit );
|
||||
Q_FOREACH ( const QVariant &value, values )
|
||||
{
|
||||
QString strValue;
|
||||
|
@ -117,29 +117,27 @@ void QgsQueryBuilder::fillValues( int idx, int limit )
|
||||
mModelValues->clear();
|
||||
|
||||
// determine the field type
|
||||
QList<QVariant> values;
|
||||
mLayer->uniqueValues( idx, values, limit );
|
||||
QSet<QVariant> values = mLayer->uniqueValues( idx, limit );
|
||||
|
||||
QgsSettings settings;
|
||||
QString nullValue = QgsApplication::nullRepresentation();
|
||||
|
||||
QgsDebugMsg( QString( "nullValue: %1" ).arg( nullValue ) );
|
||||
|
||||
for ( int i = 0; i < values.size(); i++ )
|
||||
Q_FOREACH ( const QVariant &var, values )
|
||||
{
|
||||
QString value;
|
||||
if ( values[i].isNull() )
|
||||
if ( var.isNull() )
|
||||
value = nullValue;
|
||||
else if ( values[i].type() == QVariant::Date && mLayer->providerType() == QLatin1String( "ogr" ) && mLayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
|
||||
value = values[i].toDate().toString( QStringLiteral( "yyyy/MM/dd" ) );
|
||||
else if ( var.type() == QVariant::Date && mLayer->providerType() == QLatin1String( "ogr" ) && mLayer->storageType() == QLatin1String( "ESRI Shapefile" ) )
|
||||
value = var.toDate().toString( QStringLiteral( "yyyy/MM/dd" ) );
|
||||
else
|
||||
value = values[i].toString();
|
||||
value = var.toString();
|
||||
|
||||
QStandardItem *myItem = new QStandardItem( value );
|
||||
myItem->setEditable( false );
|
||||
myItem->setData( values[i], Qt::UserRole + 1 );
|
||||
myItem->setData( var, Qt::UserRole + 1 );
|
||||
mModelValues->insertRow( mModelValues->rowCount(), myItem );
|
||||
QgsDebugMsg( QString( "Value is null: %1\nvalue: %2" ).arg( values[i].isNull() ).arg( values[i].isNull() ? nullValue : values[i].toString() ) );
|
||||
QgsDebugMsg( QString( "Value is null: %1\nvalue: %2" ).arg( var.isNull() ).arg( var.isNull() ? nullValue : var.toString() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,7 +649,7 @@ void QgsCategorizedSymbolRendererWidget::addCategories()
|
||||
}
|
||||
else
|
||||
{
|
||||
mLayer->uniqueValues( idx, unique_vals );
|
||||
unique_vals = mLayer->uniqueValues( idx ).toList();
|
||||
}
|
||||
|
||||
// ask to abort if too many classes
|
||||
|
@ -607,9 +607,9 @@ QVariant QgsMssqlProvider::maximumValue( int index ) const
|
||||
}
|
||||
|
||||
// Returns the list of unique values of an attribute
|
||||
void QgsMssqlProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit ) const
|
||||
QSet<QVariant> QgsMssqlProvider::uniqueValues( int index, int limit ) const
|
||||
{
|
||||
uniqueValues.clear();
|
||||
QSet<QVariant> uniqueValues;
|
||||
|
||||
// get the field name
|
||||
QgsField fld = mAttributeFields.at( index );
|
||||
@ -643,9 +643,10 @@ void QgsMssqlProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, i
|
||||
// read all features
|
||||
while ( query.next() )
|
||||
{
|
||||
uniqueValues.append( query.value( 0 ) );
|
||||
uniqueValues.insert( query.value( 0 ) );
|
||||
}
|
||||
}
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
|
||||
|
@ -66,7 +66,7 @@ class QgsMssqlProvider : public QgsVectorDataProvider
|
||||
virtual QStringList subLayers() const override;
|
||||
virtual QVariant minimumValue( int index ) const override;
|
||||
virtual QVariant maximumValue( int index ) const override;
|
||||
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 ) const override;
|
||||
virtual QSet<QVariant> uniqueValues( int index, int limit = -1 ) const override;
|
||||
virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest &request ) const override;
|
||||
|
||||
virtual QgsWkbTypes::Type wkbType() const override;
|
||||
|
@ -30,6 +30,8 @@ email : sherman at mrcc.com
|
||||
#include "qgsgeometry.h"
|
||||
#include "qgscoordinatereferencesystem.h"
|
||||
#include "qgsvectorlayerexporter.h"
|
||||
#include "qgis.h"
|
||||
|
||||
|
||||
#define CPL_SUPRESS_CPLUSPLUS //#spellok
|
||||
#include <gdal.h> // to collect version information
|
||||
@ -2949,17 +2951,17 @@ QgsCoordinateReferenceSystem QgsOgrProvider::crs() const
|
||||
return srs;
|
||||
}
|
||||
|
||||
void QgsOgrProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit ) const
|
||||
QSet<QVariant> QgsOgrProvider::uniqueValues( int index, int limit ) const
|
||||
{
|
||||
uniqueValues.clear();
|
||||
QSet<QVariant> uniqueValues;
|
||||
|
||||
if ( !mValid || index < 0 || index >= mAttributeFields.count() )
|
||||
return;
|
||||
return uniqueValues;
|
||||
|
||||
QgsField fld = mAttributeFields.at( index );
|
||||
if ( fld.name().isNull() )
|
||||
{
|
||||
return; //not a provider field
|
||||
return uniqueValues; //not a provider field
|
||||
}
|
||||
|
||||
QByteArray sql = "SELECT DISTINCT " + quotedIdentifier( textEncoding()->fromUnicode( fld.name() ) );
|
||||
@ -2977,7 +2979,7 @@ void QgsOgrProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int
|
||||
if ( !l )
|
||||
{
|
||||
QgsDebugMsg( "Failed to execute SQL" );
|
||||
return QgsVectorDataProvider::uniqueValues( index, uniqueValues, limit );
|
||||
return QgsVectorDataProvider::uniqueValues( index, limit );
|
||||
}
|
||||
|
||||
OGRFeatureH f;
|
||||
@ -2991,6 +2993,7 @@ void QgsOgrProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int
|
||||
}
|
||||
|
||||
OGR_DS_ReleaseResultSet( ogrDataSource, l );
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
QStringList QgsOgrProvider::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
|
||||
|
@ -103,7 +103,7 @@ class QgsOgrProvider : public QgsVectorDataProvider
|
||||
bool isValid() const override;
|
||||
QVariant minimumValue( int index ) const override;
|
||||
QVariant maximumValue( int index ) const override;
|
||||
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 ) const override;
|
||||
virtual QSet< QVariant > uniqueValues( int index, int limit = -1 ) const override;
|
||||
virtual QStringList uniqueStringsMatching( int index, const QString &substring, int limit = -1,
|
||||
QgsFeedback *feedback = nullptr ) const override;
|
||||
|
||||
|
@ -1553,9 +1553,9 @@ QVariant QgsPostgresProvider::minimumValue( int index ) const
|
||||
}
|
||||
|
||||
// Returns the list of unique values of an attribute
|
||||
void QgsPostgresProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit ) const
|
||||
QSet<QVariant> QgsPostgresProvider::uniqueValues( int index, int limit ) const
|
||||
{
|
||||
uniqueValues.clear();
|
||||
QSet<QVariant> uniqueValues;
|
||||
|
||||
try
|
||||
{
|
||||
@ -1583,12 +1583,13 @@ void QgsPostgresProvider::uniqueValues( int index, QList<QVariant> &uniqueValues
|
||||
if ( res.PQresultStatus() == PGRES_TUPLES_OK )
|
||||
{
|
||||
for ( int i = 0; i < res.PQntuples(); i++ )
|
||||
uniqueValues.append( convertValue( fld.type(), fld.subType(), res.PQgetvalue( i, 0 ) ) );
|
||||
uniqueValues.insert( convertValue( fld.type(), fld.subType(), res.PQgetvalue( i, 0 ) ) );
|
||||
}
|
||||
}
|
||||
catch ( PGFieldNotFound )
|
||||
{
|
||||
}
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
QStringList QgsPostgresProvider::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
|
||||
|
@ -126,7 +126,7 @@ class QgsPostgresProvider : public QgsVectorDataProvider
|
||||
QString dataComment() const override;
|
||||
QVariant minimumValue( int index ) const override;
|
||||
QVariant maximumValue( int index ) const override;
|
||||
virtual void uniqueValues( int index, QList<QVariant> &uniqueValues, int limit = -1 ) const override;
|
||||
virtual QSet< QVariant > uniqueValues( int index, int limit = -1 ) const override;
|
||||
virtual QStringList uniqueStringsMatching( int index, const QString &substring, int limit = -1,
|
||||
QgsFeedback *feedback = nullptr ) const override;
|
||||
virtual void enumValues( int index, QStringList &enumList ) const override;
|
||||
|
@ -3641,17 +3641,17 @@ QVariant QgsSpatiaLiteProvider::maximumValue( int index ) const
|
||||
}
|
||||
|
||||
// Returns the list of unique values of an attribute
|
||||
void QgsSpatiaLiteProvider::uniqueValues( int index, QList < QVariant > &uniqueValues, int limit ) const
|
||||
QSet<QVariant> QgsSpatiaLiteProvider::uniqueValues( int index, int limit ) const
|
||||
{
|
||||
sqlite3_stmt *stmt = nullptr;
|
||||
QString sql;
|
||||
|
||||
uniqueValues.clear();
|
||||
QSet<QVariant> uniqueValues;
|
||||
|
||||
// get the field name
|
||||
if ( index < 0 || index >= mAttributeFields.count() )
|
||||
{
|
||||
return; //invalid field
|
||||
return uniqueValues; //invalid field
|
||||
}
|
||||
QgsField fld = mAttributeFields.at( index );
|
||||
|
||||
@ -3674,7 +3674,7 @@ void QgsSpatiaLiteProvider::uniqueValues( int index, QList < QVariant > &uniqueV
|
||||
{
|
||||
// some error occurred
|
||||
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql, sqlite3_errmsg( mSqliteHandle ) ), tr( "SpatiaLite" ) );
|
||||
return;
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
while ( 1 )
|
||||
@ -3694,16 +3694,16 @@ void QgsSpatiaLiteProvider::uniqueValues( int index, QList < QVariant > &uniqueV
|
||||
switch ( sqlite3_column_type( stmt, 0 ) )
|
||||
{
|
||||
case SQLITE_INTEGER:
|
||||
uniqueValues.append( QVariant( sqlite3_column_int( stmt, 0 ) ) );
|
||||
uniqueValues.insert( QVariant( sqlite3_column_int( stmt, 0 ) ) );
|
||||
break;
|
||||
case SQLITE_FLOAT:
|
||||
uniqueValues.append( QVariant( sqlite3_column_double( stmt, 0 ) ) );
|
||||
uniqueValues.insert( QVariant( sqlite3_column_double( stmt, 0 ) ) );
|
||||
break;
|
||||
case SQLITE_TEXT:
|
||||
uniqueValues.append( QVariant( QString::fromUtf8( ( const char * ) sqlite3_column_text( stmt, 0 ) ) ) );
|
||||
uniqueValues.insert( QVariant( QString::fromUtf8( ( const char * ) sqlite3_column_text( stmt, 0 ) ) ) );
|
||||
break;
|
||||
default:
|
||||
uniqueValues.append( QVariant( mAttributeFields.at( index ).type() ) );
|
||||
uniqueValues.insert( QVariant( mAttributeFields.at( index ).type() ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3711,13 +3711,13 @@ void QgsSpatiaLiteProvider::uniqueValues( int index, QList < QVariant > &uniqueV
|
||||
{
|
||||
QgsMessageLog::logMessage( tr( "SQLite error: %2\nSQL: %1" ).arg( sql, sqlite3_errmsg( mSqliteHandle ) ), tr( "SpatiaLite" ) );
|
||||
sqlite3_finalize( stmt );
|
||||
return;
|
||||
return uniqueValues;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_finalize( stmt );
|
||||
|
||||
return;
|
||||
return uniqueValues;
|
||||
}
|
||||
|
||||
QStringList QgsSpatiaLiteProvider::uniqueStringsMatching( int index, const QString &substring, int limit, QgsFeedback *feedback ) const
|
||||
|
@ -96,7 +96,7 @@ class QgsSpatiaLiteProvider: public QgsVectorDataProvider
|
||||
QgsFields fields() const override;
|
||||
QVariant minimumValue( int index ) const override;
|
||||
QVariant maximumValue( int index ) const override;
|
||||
virtual void uniqueValues( int index, QList < QVariant > &uniqueValues, int limit = -1 ) const override;
|
||||
virtual QSet<QVariant> uniqueValues( int index, int limit = -1 ) const override;
|
||||
virtual QStringList uniqueStringsMatching( int index, const QString &substring, int limit = -1,
|
||||
QgsFeedback *feedback = nullptr ) const override;
|
||||
|
||||
|
@ -310,9 +310,8 @@ void TestQgsVectorLayer::uniqueValues()
|
||||
QgsVectorLayer *vLayer = static_cast< QgsVectorLayer * >( mpPointsLayer );
|
||||
|
||||
//test with invalid field
|
||||
QList<QVariant> values;
|
||||
vLayer->uniqueValues( 1000, values );
|
||||
QCOMPARE( values.length(), 0 );
|
||||
QSet<QVariant> values = vLayer->uniqueValues( 1000 );
|
||||
QCOMPARE( values.count(), 0 );
|
||||
}
|
||||
|
||||
void TestQgsVectorLayer::minimumValue()
|
||||
|
@ -51,6 +51,7 @@ ADD_PYTHON_TEST(PyQgsExpressionLineEdit test_qgsexpressionlineedit.py)
|
||||
ADD_PYTHON_TEST(PyQgsExtentGroupBox test_qgsextentgroupbox.py)
|
||||
ADD_PYTHON_TEST(PyQgsFeature test_qgsfeature.py)
|
||||
ADD_PYTHON_TEST(PyQgsFeatureSink test_qgsfeaturesink.py)
|
||||
ADD_PYTHON_TEST(PyQgsFeatureSource test_qgsfeaturesource.py)
|
||||
ADD_PYTHON_TEST(PyQgsFieldFormattersTest test_qgsfieldformatters.py)
|
||||
ADD_PYTHON_TEST(PyQgsFillSymbolLayers test_qgsfillsymbollayers.py)
|
||||
ADD_PYTHON_TEST(PyQgsProject test_qgsproject.py)
|
||||
|
67
tests/src/python/test_qgsfeaturesource.py
Normal file
67
tests/src/python/test_qgsfeaturesource.py
Normal file
@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsFeatureSource.
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
"""
|
||||
__author__ = '(C) 2017 by Nyall Dawson'
|
||||
__date__ = '26/04/2017'
|
||||
__copyright__ = 'Copyright 2017, The QGIS Project'
|
||||
# This will get replaced with a git SHA1 when you do a git archive
|
||||
__revision__ = '$Format:%H$'
|
||||
import qgis # NOQA
|
||||
|
||||
import os
|
||||
|
||||
from qgis.core import (QgsVectorLayer,
|
||||
QgsFeature,
|
||||
QgsGeometry,
|
||||
QgsPointXY)
|
||||
from qgis.PyQt.QtCore import QVariant
|
||||
from qgis.testing import start_app, unittest
|
||||
start_app()
|
||||
|
||||
|
||||
def createLayerWithFivePoints():
|
||||
layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
|
||||
"addfeat", "memory")
|
||||
pr = layer.dataProvider()
|
||||
f = QgsFeature()
|
||||
f.setAttributes(["test", 1])
|
||||
f.setGeometry(QgsGeometry.fromPoint(QgsPointXY(100, 200)))
|
||||
f2 = QgsFeature()
|
||||
f2.setAttributes(["test2", 3])
|
||||
f2.setGeometry(QgsGeometry.fromPoint(QgsPointXY(200, 200)))
|
||||
f3 = QgsFeature()
|
||||
f3.setAttributes(["test2", 3])
|
||||
f3.setGeometry(QgsGeometry.fromPoint(QgsPointXY(300, 200)))
|
||||
f4 = QgsFeature()
|
||||
f4.setAttributes(["test3", 3])
|
||||
f4.setGeometry(QgsGeometry.fromPoint(QgsPointXY(400, 300)))
|
||||
f5 = QgsFeature()
|
||||
f5.setAttributes(["test4", 4])
|
||||
f5.setGeometry(QgsGeometry.fromPoint(QgsPointXY(0, 0)))
|
||||
assert pr.addFeatures([f, f2, f3, f4, f5])
|
||||
assert layer.featureCount() == 5
|
||||
return layer
|
||||
|
||||
|
||||
class TestQgsFeatureSource(unittest.TestCase):
|
||||
|
||||
def testUniqueValues(self):
|
||||
"""
|
||||
Test retrieving unique values using base class method
|
||||
"""
|
||||
|
||||
# memory provider uses base class method
|
||||
layer = createLayerWithFivePoints()
|
||||
self.assertFalse(layer.dataProvider().uniqueValues(-1))
|
||||
self.assertFalse(layer.dataProvider().uniqueValues(100))
|
||||
self.assertEqual(layer.dataProvider().uniqueValues(0), {'test', 'test2', 'test3', 'test4'})
|
||||
self.assertEqual(layer.dataProvider().uniqueValues(1), {1, 3, 3, 4})
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user