mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-13 00:03:09 -04:00
- 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:
parent
95c8c42519
commit
d8460108ff
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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";
|
||||
|
@ -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
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user