- add getUniqueValues method to QgsVectorDataProvider

- implement getUniqueValues in QgsPostgresProvider (fixes #399)
 - implement getUniqueValues, minValue and maxValue in OgsOgrProvider
 - use getUniqueValues in QgsUniqueValueDialog
- update QgsPostgresProvider::storageType interface (fixes #995)
  (applied patch from Steven Mizuno, thanks again)


git-svn-id: http://svn.osgeo.org/qgis/trunk@8233 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
jef 2008-03-16 16:52:11 +00:00
parent 95c8c42519
commit d8460108ff
9 changed files with 209 additions and 36 deletions

View File

@ -135,6 +135,15 @@ class QgsVectorDataProvider : QgsDataProvider
*/
virtual QVariant maxValue(int index);
/**
* Return unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list to fill
*
* Default implementation simply iterates the features
*/
virtual void getUniqueValues(int index, QStringList &uniqueValues);
/**
* Adds a list of features
* @return true in case of success and false in case of failure

View File

@ -157,33 +157,26 @@ void QgsUniqueValueDialog::changeClassificationAttribute()
QgsVectorDataProvider *provider = dynamic_cast<QgsVectorDataProvider *>(mVectorLayer->getDataProvider());
if (provider)
{
QString value;
QgsAttributeList attlist;
QgsSymbol* symbol;
int nr = provider->indexFromFieldName(attributeName);
if(nr == -1)
{
return;
}
attlist.append(nr);
provider->select(attlist, QgsRect(), false);
QgsFeature feat;
//go through all the features and insert their value into the map and into mClassListWidget
mClassListWidget->clear();
while(provider->getNextFeature(feat))
{
const QgsAttributeMap& attrs = feat.attributeMap();
value = attrs[nr].toString();
if(mValues.find(value)==mValues.end())
QStringList keys;
provider->getUniqueValues(nr, keys);
QStringListIterator it(keys);
while( it.hasNext() )
{
QString value = it.next();
symbol=new QgsSymbol(mVectorLayer->vectorType(), value);
mValues.insert(std::make_pair(value,symbol));
}
}
//set symbology for all QgsSiSyDialogs
QColor thecolor;

View File

@ -291,6 +291,21 @@ QVariant QgsVectorDataProvider::maxValue(int index)
return mCacheMaxValues[index];
}
void QgsVectorDataProvider::getUniqueValues(int index, QStringList &values)
{
QgsFeature f;
QgsAttributeList keys;
keys.append(index);
select(keys, QgsRect(), false);
QMap<QString,int> map;
while( getNextFeature(f) )
map.insert( f.attributeMap()[index].toString(), 1);
values = map.keys();
}
void QgsVectorDataProvider::fillMinMaxCache()
{
const QgsFieldMap& flds = fields();

View File

@ -153,7 +153,7 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
* @param index the index of the attribute
*
* Default implementation walks all numeric attributes and caches minimal
* and maximal values. If provider has facilities to retreive minimal
* and maximal values. If provider has facilities to retrieve minimal
* value directly, override this function.
*/
virtual QVariant minValue(int index);
@ -163,11 +163,20 @@ class CORE_EXPORT QgsVectorDataProvider : public QgsDataProvider
* @param index the index of the attribute
*
* Default implementation walks all numeric attributes and caches minimal
* and maximal values. If provider has facilities to retreive maximal
* and maximal values. If provider has facilities to retrieve maximal
* value directly, override this function.
*/
virtual QVariant maxValue(int index);
/**
* Return unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list to fill
*
* Default implementation simply iterates the features
*/
virtual void getUniqueValues(int index, QStringList &uniqueValues);
/**
* Adds a list of features
* @return true in case of success and false in case of failure

View File

@ -119,7 +119,7 @@ public:
/**
* Returns the permanent storage type for this layer as a friendly name.
*/
QString storageType() const;
virtual QString storageType() const;
/** Select features based on a bounding rectangle. Features can be retrieved with calls to getNextFeature.

View File

@ -30,6 +30,7 @@ email : sherman at mrcc.com
#include <QtDebug>
#include <QFile>
#include <QDir>
#include <QFileInfo>
#include <QMap>
#include <QString>
@ -483,7 +484,6 @@ bool QgsOgrProvider::addFeature(QgsFeature& f)
OGRFeatureH feature= OGR_F_Create(fdef);
QGis::WKBTYPE ftype = f.geometry()->wkbType();
unsigned char* wkb = f.geometry()->wkbBuffer();
OGRErr err;
if( f.geometry()->wkbSize() > 0 )
{
@ -901,8 +901,6 @@ static QString createFileFilter_(QString const &longName, QString const &glob)
QGISEXTERN QString fileVectorFilters()
{
static QString myFileFilters;
@ -1217,7 +1215,6 @@ QGISEXTERN bool createEmptyDataSource(const QString& uri,
return true;
}
QgsSpatialRefSys QgsOgrProvider::getSRS()
{
QgsDebugMsg("QgsOgrProvider::getSRS()");
@ -1246,3 +1243,109 @@ QgsSpatialRefSys QgsOgrProvider::getSRS()
return srs;
}
void QgsOgrProvider::getUniqueValues(int index, QStringList &uniqueValues)
{
QgsField fld = mAttributeFields[index];
QFileInfo fi( dataSourceUri() );
if( !fi.exists() )
return;
QString sql = QString("SELECT DISTINCT %1 FROM %2 ORDER BY %1").arg( fld.name() ).arg( fi.baseName() );
uniqueValues.clear();
OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
if(l==0)
return;
OGRFeatureH f;
while( f=OGR_L_GetNextFeature(l) )
{
uniqueValues.append( mEncoding->toUnicode(OGR_F_GetFieldAsString(f, 0)) );
OGR_F_Destroy(f);
}
OGR_DS_ReleaseResultSet(l, ogrDataSource);
}
QVariant QgsOgrProvider::minValue(int index)
{
QgsField fld = mAttributeFields[index];
QFileInfo fi( dataSourceUri() );
if( !fi.exists() )
return QVariant();
QString sql = QString("SELECT MIN(%1) FROM %2").arg( fld.name() ).arg( fi.baseName() );
OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
if(l==0)
return QVariant();
OGRFeatureH f = OGR_L_GetNextFeature(l);
if(f==0)
{
OGR_DS_ReleaseResultSet(l, ogrDataSource);
return QVariant();
}
QString str = mEncoding->toUnicode( mEncoding->toUnicode( OGR_F_GetFieldAsString(f,0) ) );
OGR_F_Destroy(f);
QVariant value;
switch (fld.type())
{
case QVariant::String: value = QVariant(str); break;
case QVariant::Int: value = QVariant(str.toInt()); break;
case QVariant::Double: value = QVariant(str.toDouble()); break;
//case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
default: assert(NULL && "unsupported field type");
}
OGR_DS_ReleaseResultSet(l, ogrDataSource);
return value;
}
QVariant QgsOgrProvider::maxValue(int index)
{
QgsField fld = mAttributeFields[index];
QFileInfo fi( dataSourceUri() );
if( !fi.exists() )
return QVariant();
QString sql = QString("SELECT MAX(%1) FROM %2").arg( fld.name() ).arg( fi.baseName() );
OGRLayerH l = OGR_DS_ExecuteSQL(ogrDataSource, sql.ascii(), NULL, "SQL");
if(l==0)
return QVariant();
OGRFeatureH f = OGR_L_GetNextFeature(l);
if(f==0)
{
OGR_DS_ReleaseResultSet(l, ogrDataSource);
return QVariant();
}
QString str = mEncoding->toUnicode( mEncoding->toUnicode( OGR_F_GetFieldAsString(f,0) ) );
OGR_F_Destroy(f);
QVariant value;
switch (fld.type())
{
case QVariant::String: value = QVariant(str); break;
case QVariant::Int: value = QVariant(str.toInt()); break;
case QVariant::Double: value = QVariant(str.toDouble()); break;
//case QVariant::DateTime: value = QVariant(QDateTime::fromString(str)); break;
default: assert(NULL && "unsupported field type");
}
OGR_DS_ReleaseResultSet(l, ogrDataSource);
return value;
}

View File

@ -182,6 +182,18 @@ class QgsOgrProvider : public QgsVectorDataProvider
*/
bool isValid();
/** Returns the minimum value of an attribute
* @param index the index of the attribute */
QVariant minValue(int index);
/** Returns the maximum value of an attribute
* @param index the index of the attribute */
QVariant maxValue(int index);
/** Return the unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list of unique values */
virtual void getUniqueValues(int index, QStringList &uniqueValues);
protected:
/** loads fields from input file to member attributeFields */

View File

@ -334,7 +334,7 @@ void QgsPostgresProvider::disconnectDb()
connection = 0;
}
QString QgsPostgresProvider::storageType()
QString QgsPostgresProvider::storageType() const
{
return "PostgreSQL database with PostGIS extension";
}
@ -1272,10 +1272,8 @@ bool QgsPostgresProvider::uniqueData(QString schemaName,
PGresult* unique = PQexec(connection, sql.toUtf8());
if (PQntuples(unique) == 1)
// if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
if (QString::fromUtf8(PQgetvalue(unique, 0, 0)).compare("t") == 0) //really should compare just first character as original did
isUnique = true;
if (PQntuples(unique)==1 && QString::fromUtf8(PQgetvalue(unique, 0, 0)).startsWith("t") == 0)
isUnique = true;
PQclear(unique);
@ -1634,6 +1632,37 @@ QVariant QgsPostgresProvider::minValue(int index)
return minValue.toDouble();
}
// Returns the list of unique values of an attribute
void QgsPostgresProvider::getUniqueValues(int index, QStringList &uniqueValues)
{
// get the field name
QgsField fld = attributeFields[index];
QString sql;
if(sqlWhereClause.isEmpty())
{
sql = QString("select distinct %1 from %2 order by %1")
.arg(quotedIdentifier(fld.name()))
.arg(mSchemaTableName);
}
else
{
sql = QString("select distinct %1 from %2 where %3 order by %1")
.arg(quotedIdentifier(fld.name()))
.arg(mSchemaTableName)
.arg(sqlWhereClause);
}
uniqueValues.clear();
PGresult *res= PQexec(connection, sql.toUtf8());
if (PQresultStatus(res) == PGRES_TUPLES_OK)
{
for(int i=0; i<PQntuples(res); i++)
uniqueValues.append( QString::fromUtf8(PQgetvalue(res,i,0)) );
}
PQclear(res);
}
// Returns the maximum value of an attribute
QVariant QgsPostgresProvider::maxValue(int index)
@ -1700,7 +1729,7 @@ QVariant QgsPostgresProvider::getDefaultValue(int fieldId)
if (PQntuples(result)==1 && !PQgetisnull(result, 0, 0) )
defaultValue = QString::fromUtf8(PQgetvalue(result, 0, 0));
QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );
// QgsDebugMsg( QString("defaultValue for %1 is NULL: %2").arg(fieldId).arg( defaultValue.isNull() ) );
PQclear(result);
@ -2391,7 +2420,7 @@ bool QgsPostgresProvider::deduceEndian()
// version 7.4, binary cursors return data in XDR whereas previous versions
// return data in the endian of the server
QString firstOid = "select regclass('" + mSchemaTableName + "')::oid";
QString firstOid = "select regclass(" + quotedValue(mSchemaTableName) + ")::oid";
PGresult * oidResult = PQexec(connection, firstOid.toUtf8());
// get the int value from a "normal" select
QString oidValue = QString::fromUtf8(PQgetvalue(oidResult,0,0));
@ -2577,13 +2606,13 @@ PGresult* QgsPostgresProvider::executeDbCommand(PGconn* connection,
return result;
}
QString QgsPostgresProvider::quotedIdentifier( QString ident )
QString QgsPostgresProvider::quotedIdentifier( QString ident ) const
{
ident.replace('"', "\"\"");
return ident.prepend("\"").append("\"");
}
QString QgsPostgresProvider::quotedValue( QString value )
QString QgsPostgresProvider::quotedValue( QString value ) const
{
if( value.isNull() )
return "NULL";

View File

@ -69,7 +69,7 @@ class QgsPostgresProvider:public QgsVectorDataProvider
/**
* Returns the permanent storage type for this layer as a friendly name.
*/
QString storageType();
virtual QString storageType() const;
/*! Get the QgsSpatialRefSys for this layer
* @note Must be reimplemented by each provider.
@ -131,8 +131,6 @@ class QgsPostgresProvider:public QgsVectorDataProvider
*/
size_t layerCount() const;
/**
* Get the number of features in the layer
*/
@ -184,14 +182,19 @@ class QgsPostgresProvider:public QgsVectorDataProvider
*/
void reset();
/** Returns the minimum value of an attributs
/** Returns the minimum value of an attribute
* @param index the index of the attribute */
QVariant minValue(int index);
/** Returns the maximum value of an attributs
/** Returns the maximum value of an attribute
* @param index the index of the attribute */
QVariant maxValue(int index);
/** Return the unique values of an attribute
* @param index the index of the attribute
* @param values reference to the list of unique values */
virtual void getUniqueValues(int index, QStringList &uniqueValues);
/**Returns true if layer is valid
*/
bool isValid();
@ -330,11 +333,11 @@ class QgsPostgresProvider:public QgsVectorDataProvider
/** Double quote a PostgreSQL identifier for placement in a SQL string.
*/
QString quotedIdentifier( QString ident );
QString quotedIdentifier( QString ident ) const;
/** Quote a value for placement in a SQL string.
*/
QString quotedValue( QString value );
QString quotedValue( QString value ) const;
/** Load the field list
*/