[QGIS Commit] r8233 - in trunk/qgis: python/core src/app src/core src/providers/grass src/providers/ogr src/providers/postgres

svn_qgis at osgeo.org svn_qgis at osgeo.org
Sun Mar 16 12:52:11 EDT 2008


Author: jef
Date: 2008-03-16 12:52:11 -0400 (Sun, 16 Mar 2008)
New Revision: 8233

Modified:
   trunk/qgis/python/core/qgsvectordataprovider.sip
   trunk/qgis/src/app/qgsuniquevaluedialog.cpp
   trunk/qgis/src/core/qgsvectordataprovider.cpp
   trunk/qgis/src/core/qgsvectordataprovider.h
   trunk/qgis/src/providers/grass/qgsgrassprovider.h
   trunk/qgis/src/providers/ogr/qgsogrprovider.cpp
   trunk/qgis/src/providers/ogr/qgsogrprovider.h
   trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
   trunk/qgis/src/providers/postgres/qgspostgresprovider.h
Log:
- 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)


Modified: trunk/qgis/python/core/qgsvectordataprovider.sip
===================================================================
--- trunk/qgis/python/core/qgsvectordataprovider.sip	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/python/core/qgsvectordataprovider.sip	2008-03-16 16:52:11 UTC (rev 8233)
@@ -135,6 +135,15 @@
        */
       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

Modified: trunk/qgis/src/app/qgsuniquevaluedialog.cpp
===================================================================
--- trunk/qgis/src/app/qgsuniquevaluedialog.cpp	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/app/qgsuniquevaluedialog.cpp	2008-03-16 16:52:11 UTC (rev 8233)
@@ -157,33 +157,26 @@
   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;

Modified: trunk/qgis/src/core/qgsvectordataprovider.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectordataprovider.cpp	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/core/qgsvectordataprovider.cpp	2008-03-16 16:52:11 UTC (rev 8233)
@@ -291,6 +291,21 @@
   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();

Modified: trunk/qgis/src/core/qgsvectordataprovider.h
===================================================================
--- trunk/qgis/src/core/qgsvectordataprovider.h	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/core/qgsvectordataprovider.h	2008-03-16 16:52:11 UTC (rev 8233)
@@ -153,7 +153,7 @@
        * @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,12 +163,21 @@
        * @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
        */

Modified: trunk/qgis/src/providers/grass/qgsgrassprovider.h
===================================================================
--- trunk/qgis/src/providers/grass/qgsgrassprovider.h	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/providers/grass/qgsgrassprovider.h	2008-03-16 16:52:11 UTC (rev 8233)
@@ -119,7 +119,7 @@
   /**
     *   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.

Modified: trunk/qgis/src/providers/ogr/qgsogrprovider.cpp
===================================================================
--- trunk/qgis/src/providers/ogr/qgsogrprovider.cpp	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/providers/ogr/qgsogrprovider.cpp	2008-03-16 16:52:11 UTC (rev 8233)
@@ -30,6 +30,7 @@
 
 #include <QtDebug>
 #include <QFile>
+#include <QDir>
 #include <QFileInfo>
 #include <QMap>
 #include <QString>
@@ -483,7 +484,6 @@
   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 @@
 
 
 
-
-
 QGISEXTERN QString fileVectorFilters()
 {
   static QString myFileFilters;
@@ -1217,7 +1215,6 @@
   return true;
 }
 
-
 QgsSpatialRefSys QgsOgrProvider::getSRS()
 {
   QgsDebugMsg("QgsOgrProvider::getSRS()");
@@ -1246,3 +1243,109 @@
 
   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;
+}

Modified: trunk/qgis/src/providers/ogr/qgsogrprovider.h
===================================================================
--- trunk/qgis/src/providers/ogr/qgsogrprovider.h	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/providers/ogr/qgsogrprovider.h	2008-03-16 16:52:11 UTC (rev 8233)
@@ -182,7 +182,19 @@
     */
     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 */
     void loadFields();

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.cpp	2008-03-16 16:52:11 UTC (rev 8233)
@@ -334,7 +334,7 @@
   connection = 0;
 }
 
-QString QgsPostgresProvider::storageType()
+QString QgsPostgresProvider::storageType() const
 {
   return "PostgreSQL database with PostGIS extension";
 }
@@ -1272,10 +1272,8 @@
 
   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 @@
   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 @@
   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 @@
   // 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 @@
   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";

Modified: trunk/qgis/src/providers/postgres/qgspostgresprovider.h
===================================================================
--- trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2008-03-16 16:35:51 UTC (rev 8232)
+++ trunk/qgis/src/providers/postgres/qgspostgresprovider.h	2008-03-16 16:52:11 UTC (rev 8233)
@@ -69,7 +69,7 @@
     /**
       *   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 @@
     */
     size_t layerCount() const;
 
-
-
     /**
      * Get the number of features in the layer
      */
@@ -184,14 +182,19 @@
      */
     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 @@
 
     /** 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
     */



More information about the QGIS-commit mailing list