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