Quantum GIS API Documentation  1.7.4
src/core/qgsvectordataprovider.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002     qgsvectordataprovider.cpp - DataProvider Interface for vector layers
00003      --------------------------------------
00004     Date                 : 26-Oct-2004
00005     Copyright            : (C) 2004 by Marco Hugentobler
00006     email                : [email protected]
00007  ***************************************************************************
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  ***************************************************************************/
00015 /* $Id$ */
00016 
00017 #include <QSettings>
00018 #include <QTextCodec>
00019 
00020 #include <cfloat> // for DBL_MAX
00021 #include <climits>
00022 
00023 #include "qgsvectordataprovider.h"
00024 #include "qgsfeature.h"
00025 #include "qgsfield.h"
00026 #include "qgslogger.h"
00027 
00028 QgsVectorDataProvider::QgsVectorDataProvider( QString uri )
00029     : QgsDataProvider( uri )
00030     , mCacheMinMaxDirty( true )
00031     , mFetchFeaturesWithoutGeom( true )
00032 {
00033   QSettings settings;
00034   setEncoding( settings.value( "/UI/encoding", QString( "System" ) ).toString() );
00035 }
00036 
00037 
00038 QgsVectorDataProvider::~QgsVectorDataProvider()
00039 {
00040 }
00041 
00042 QString QgsVectorDataProvider::storageType() const
00043 {
00044   return "Generic vector file";
00045 }
00046 
00047 long QgsVectorDataProvider::updateFeatureCount()
00048 {
00049   return -1;
00050 }
00051 
00052 bool QgsVectorDataProvider::featureAtId( int featureId,
00053     QgsFeature& feature,
00054     bool fetchGeometry,
00055     QgsAttributeList fetchAttributes )
00056 {
00057   select( fetchAttributes, QgsRectangle(), fetchGeometry );
00058 
00059   while ( nextFeature( feature ) )
00060   {
00061     if ( feature.id() == featureId )
00062       return true;
00063   }
00064 
00065   return false;
00066 }
00067 
00068 QString QgsVectorDataProvider::dataComment() const
00069 {
00070   return QString();
00071 }
00072 
00073 bool QgsVectorDataProvider::addFeatures( QgsFeatureList &flist )
00074 {
00075   return false;
00076 }
00077 
00078 bool QgsVectorDataProvider::deleteFeatures( const QgsFeatureIds & id )
00079 {
00080   return false;
00081 }
00082 
00083 bool QgsVectorDataProvider::addAttributes( const QList<QgsField> & attributes )
00084 {
00085   return false;
00086 }
00087 
00088 bool QgsVectorDataProvider::addAttributes( const QMap<QString, QString> &attributes )
00089 {
00090   const QList< NativeType > &types = nativeTypes();
00091   QList< QgsField > list;
00092 
00093   for ( QMap<QString, QString>::const_iterator it = attributes.constBegin(); it != attributes.constEnd(); it++ )
00094   {
00095     int i;
00096     for ( i = 0; i < types.size() && types[i].mTypeName != it.value(); i++ )
00097       ;
00098 
00099     if ( i == types.size() )
00100       return false;
00101 
00102     list << QgsField( it.key(), types[i].mType, it.value() );
00103   }
00104 
00105   return addAttributes( list );
00106 }
00107 
00108 bool QgsVectorDataProvider::deleteAttributes( const QgsAttributeIds& attributes )
00109 {
00110   return false;
00111 }
00112 
00113 bool QgsVectorDataProvider::changeAttributeValues( const QgsChangedAttributesMap & attr_map )
00114 {
00115   return false;
00116 }
00117 
00118 QVariant QgsVectorDataProvider::defaultValue( int fieldId )
00119 {
00120   return QVariant();
00121 }
00122 
00123 bool QgsVectorDataProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
00124 {
00125   return false;
00126 }
00127 
00128 bool QgsVectorDataProvider::createSpatialIndex()
00129 {
00130   return false;
00131 }
00132 
00133 bool QgsVectorDataProvider::createAttributeIndex( int field )
00134 {
00135   return true;
00136 }
00137 
00138 int QgsVectorDataProvider::capabilities() const
00139 {
00140   return QgsVectorDataProvider::NoCapabilities;
00141 }
00142 
00143 
00144 void QgsVectorDataProvider::setEncoding( const QString& e )
00145 {
00146   QTextCodec* ncodec = QTextCodec::codecForName( e.toLocal8Bit().data() );
00147   if ( ncodec )
00148   {
00149     mEncoding = ncodec;
00150   }
00151   else
00152   {
00153     QgsDebugMsg( "error finding QTextCodec for " + e );
00154   }
00155 }
00156 
00157 QString QgsVectorDataProvider::encoding() const
00158 {
00159   if ( mEncoding )
00160   {
00161     return mEncoding->name();
00162   }
00163 
00164   return "";
00165 }
00166 
00167 QString QgsVectorDataProvider::capabilitiesString() const
00168 {
00169   QStringList abilitiesList;
00170 
00171   int abilities = capabilities();
00172 
00173   if ( abilities & QgsVectorDataProvider::AddFeatures )
00174   {
00175     abilitiesList += tr( "Add Features" );
00176     QgsDebugMsg( "Capability: Add Features" );
00177   }
00178 
00179   if ( abilities & QgsVectorDataProvider::DeleteFeatures )
00180   {
00181     abilitiesList += tr( "Delete Features" );
00182     QgsDebugMsg( "Capability: Delete Features" );
00183   }
00184 
00185   if ( abilities & QgsVectorDataProvider::ChangeAttributeValues )
00186   {
00187     abilitiesList += tr( "Change Attribute Values" );
00188     QgsDebugMsg( "Capability: Change Attribute Values" );
00189   }
00190 
00191   if ( abilities & QgsVectorDataProvider::AddAttributes )
00192   {
00193     abilitiesList += tr( "Add Attributes" );
00194     QgsDebugMsg( "Capability: Add Attributes" );
00195   }
00196 
00197   if ( abilities & QgsVectorDataProvider::DeleteAttributes )
00198   {
00199     abilitiesList += tr( "Delete Attributes" );
00200     QgsDebugMsg( "Capability: Delete Attributes" );
00201   }
00202 
00203   if ( abilities & QgsVectorDataProvider::CreateSpatialIndex )
00204   {
00205     // TODO: Tighten up this test.  See QgsOgrProvider for details.
00206     abilitiesList += tr( "Create Spatial Index" );
00207     QgsDebugMsg( "Capability: Create Spatial Index" );
00208   }
00209 
00210   if ( abilities & QgsVectorDataProvider::SelectAtId )
00211   {
00212     abilitiesList += tr( "Fast Access to Features at ID" );
00213     QgsDebugMsg( "Capability: Select at ID" );
00214   }
00215 
00216   if ( abilities & QgsVectorDataProvider::ChangeGeometries )
00217   {
00218     abilitiesList += tr( "Change Geometries" );
00219     QgsDebugMsg( "Capability: Change Geometries" );
00220   }
00221 
00222   return abilitiesList.join( ", " );
00223 
00224 }
00225 
00226 
00227 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
00228 {
00229   const QgsFieldMap &theFields = fields();
00230 
00231   for ( QgsFieldMap::const_iterator it = theFields.constBegin(); it != theFields.constEnd(); ++it )
00232   {
00233     if ( QString::compare( it->name(), fieldName, Qt::CaseInsensitive ) == 0 )
00234     {
00235       return it.key();
00236     }
00237   }
00238   return -1;
00239 }
00240 
00241 QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
00242 {
00243   QMap<QString, int> resultMap;
00244 
00245   const QgsFieldMap& theFields = fields();
00246   QgsFieldMap::const_iterator field_it = theFields.constBegin();
00247   for ( ; field_it != theFields.constEnd(); ++field_it )
00248   {
00249     resultMap.insert( field_it.value().name(), field_it.key() );
00250   }
00251 
00252   return resultMap;
00253 }
00254 
00255 QgsAttributeList QgsVectorDataProvider::attributeIndexes()
00256 {
00257   uint count = fieldCount();
00258   QgsAttributeList list;
00259 
00260   for ( uint i = 0; i < count; i++ )
00261     list.append( i );
00262 
00263   return list;
00264 }
00265 
00266 void QgsVectorDataProvider::enableGeometrylessFeatures( bool fetch )
00267 {
00268   mFetchFeaturesWithoutGeom = fetch;
00269 }
00270 
00271 const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
00272 {
00273   return mNativeTypes;
00274 }
00275 
00276 const QMap<QString, QVariant::Type> &QgsVectorDataProvider::supportedNativeTypes() const
00277 {
00278   if ( mOldTypeList.size() > 0 )
00279     return mOldTypeList;
00280 
00281   QgsVectorDataProvider *p = ( QgsVectorDataProvider * )this;
00282 
00283   const QList< QgsVectorDataProvider::NativeType > &types = nativeTypes();
00284 
00285   for ( QList< QgsVectorDataProvider::NativeType >::const_iterator it = types.constBegin(); it != types.constEnd(); it++ )
00286   {
00287     p->mOldTypeList.insert( it->mTypeName, it->mType );
00288   }
00289 
00290   return p->mOldTypeList;
00291 }
00292 
00293 bool QgsVectorDataProvider::supportedType( const QgsField &field ) const
00294 {
00295   int i;
00296   for ( i = 0; i < mNativeTypes.size(); i++ )
00297   {
00298     if ( field.type() == mNativeTypes[i].mType &&
00299          field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
00300          field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
00301     {
00302       break;
00303     }
00304   }
00305 
00306   return i < mNativeTypes.size();
00307 }
00308 
00309 QVariant QgsVectorDataProvider::minimumValue( int index )
00310 {
00311   if ( !fields().contains( index ) )
00312   {
00313     QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
00314     return QVariant();
00315   }
00316 
00317   fillMinMaxCache();
00318 
00319   if ( !mCacheMinValues.contains( index ) )
00320     return QVariant();
00321 
00322   return mCacheMinValues[index];
00323 }
00324 
00325 QVariant QgsVectorDataProvider::maximumValue( int index )
00326 {
00327   if ( !fields().contains( index ) )
00328   {
00329     QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
00330     return QVariant();
00331   }
00332 
00333   fillMinMaxCache();
00334 
00335   if ( !mCacheMaxValues.contains( index ) )
00336     return QVariant();
00337 
00338   return mCacheMaxValues[index];
00339 }
00340 
00341 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
00342 {
00343   QgsFeature f;
00344   QgsAttributeList keys;
00345   keys.append( index );
00346   select( keys, QgsRectangle(), false );
00347 
00348   QSet<QString> set;
00349   values.clear();
00350 
00351   while ( nextFeature( f ) )
00352   {
00353     if ( !set.contains( f.attributeMap()[index].toString() ) )
00354     {
00355       values.append( f.attributeMap()[index] );
00356       set.insert( f.attributeMap()[index].toString() );
00357     }
00358 
00359     if ( limit >= 0 && values.size() >= limit )
00360       break;
00361   }
00362 }
00363 
00364 void QgsVectorDataProvider::clearMinMaxCache()
00365 {
00366   mCacheMinMaxDirty = true;
00367 }
00368 
00369 void QgsVectorDataProvider::fillMinMaxCache()
00370 {
00371   if ( !mCacheMinMaxDirty )
00372     return;
00373 
00374   const QgsFieldMap& flds = fields();
00375   for ( QgsFieldMap::const_iterator it = flds.begin(); it != flds.end(); ++it )
00376   {
00377     if ( it->type() == QVariant::Int )
00378     {
00379       mCacheMinValues[it.key()] = QVariant( INT_MAX );
00380       mCacheMaxValues[it.key()] = QVariant( INT_MIN );
00381     }
00382     else if ( it->type() == QVariant::Double )
00383     {
00384       mCacheMinValues[it.key()] = QVariant( DBL_MAX );
00385       mCacheMaxValues[it.key()] = QVariant( -DBL_MAX );
00386     }
00387     else
00388     {
00389       mCacheMinValues[it.key()] = QVariant();
00390       mCacheMaxValues[it.key()] = QVariant();
00391     }
00392   }
00393 
00394   QgsFeature f;
00395   QgsAttributeList keys = mCacheMinValues.keys();
00396   select( keys, QgsRectangle(), false );
00397 
00398   while ( nextFeature( f ) )
00399   {
00400     QgsAttributeMap attrMap = f.attributeMap();
00401     for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
00402     {
00403       const QVariant& varValue = attrMap[*it];
00404 
00405       if ( flds[*it].type() == QVariant::Int )
00406       {
00407         int value = varValue.toInt();
00408         if ( value < mCacheMinValues[*it].toInt() )
00409           mCacheMinValues[*it] = value;
00410         if ( value > mCacheMaxValues[*it].toInt() )
00411           mCacheMaxValues[*it] = value;
00412       }
00413       else if ( flds[*it].type() == QVariant::Double )
00414       {
00415         double value = varValue.toDouble();
00416         if ( value < mCacheMinValues[*it].toDouble() )
00417           mCacheMinValues[*it] = value;
00418         if ( value > mCacheMaxValues[*it].toDouble() )
00419           mCacheMaxValues[*it] = value;
00420       }
00421       else
00422       {
00423         QString value = varValue.toString();
00424         if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
00425         {
00426           mCacheMinValues[*it] = value;
00427         }
00428         if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
00429         {
00430           mCacheMaxValues[*it] = value;
00431         }
00432       }
00433     }
00434   }
00435 
00436   mCacheMinMaxDirty = false;
00437 }
00438 
00439 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
00440 {
00441   QVariant v( value );
00442 
00443   if ( !v.convert( type ) )
00444     v = QVariant( QString::null );
00445 
00446   return v;
00447 }
00448 
00449 const QStringList &QgsVectorDataProvider::availableEncodings()
00450 {
00451   if ( smEncodings.isEmpty() )
00452   {
00453     smEncodings << "BIG5";
00454     smEncodings << "BIG5-HKSCS";
00455     smEncodings << "EUCJP";
00456     smEncodings << "EUCKR";
00457     smEncodings << "GB2312";
00458     smEncodings << "GBK";
00459     smEncodings << "GB18030";
00460     smEncodings << "JIS7";
00461     smEncodings << "SHIFT-JIS";
00462     smEncodings << "TSCII";
00463     smEncodings << "UTF-8";
00464     smEncodings << "UTF-16";
00465     smEncodings << "KOI8-R";
00466     smEncodings << "KOI8-U";
00467     smEncodings << "ISO8859-1";
00468     smEncodings << "ISO8859-2";
00469     smEncodings << "ISO8859-3";
00470     smEncodings << "ISO8859-4";
00471     smEncodings << "ISO8859-5";
00472     smEncodings << "ISO8859-6";
00473     smEncodings << "ISO8859-7";
00474     smEncodings << "ISO8859-8";
00475     smEncodings << "ISO8859-8-I";
00476     smEncodings << "ISO8859-9";
00477     smEncodings << "ISO8859-10";
00478     smEncodings << "ISO8859-11";
00479     smEncodings << "ISO8859-12";
00480     smEncodings << "ISO8859-13";
00481     smEncodings << "ISO8859-14";
00482     smEncodings << "ISO8859-15";
00483     smEncodings << "IBM 850";
00484     smEncodings << "IBM 866";
00485     smEncodings << "CP874";
00486     smEncodings << "CP1250";
00487     smEncodings << "CP1251";
00488     smEncodings << "CP1252";
00489     smEncodings << "CP1253";
00490     smEncodings << "CP1254";
00491     smEncodings << "CP1255";
00492     smEncodings << "CP1256";
00493     smEncodings << "CP1257";
00494     smEncodings << "CP1258";
00495     smEncodings << "Apple Roman";
00496     smEncodings << "TIS-620";
00497     smEncodings << "System";
00498   }
00499 
00500   return smEncodings;
00501 }
00502 
00503 void QgsVectorDataProvider::clearErrors()
00504 {
00505   mErrors.clear();
00506 }
00507 
00508 bool QgsVectorDataProvider::hasErrors()
00509 {
00510   return !mErrors.isEmpty();
00511 }
00512 
00513 QStringList QgsVectorDataProvider::errors()
00514 {
00515   return mErrors;
00516 }
00517 
00518 void QgsVectorDataProvider::pushError( QString msg )
00519 {
00520   mErrors << msg;
00521 }
00522 
00523 QStringList QgsVectorDataProvider::smEncodings;
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines