QGIS API Documentation  master-6164ace
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                : marco.hugentobler@autoform.ch
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 "qgsfeatureiterator.h"
00025 #include "qgsfeaturerequest.h"
00026 #include "qgsfield.h"
00027 #include "qgslogger.h"
00028 #include "qgsmessagelog.h"
00029 
00030 QgsVectorDataProvider::QgsVectorDataProvider( QString uri )
00031     : QgsDataProvider( uri )
00032     , mCacheMinMaxDirty( true )
00033     , mAttrPalIndexName( QgsAttrPalIndexNameHash() )
00034 {
00035   QSettings settings;
00036   setEncoding( settings.value( "/UI/encoding", "System" ).toString() );
00037 }
00038 
00039 
00040 QgsVectorDataProvider::~QgsVectorDataProvider()
00041 {
00042 }
00043 
00044 QString QgsVectorDataProvider::storageType() const
00045 {
00046   return "Generic vector file";
00047 }
00048 
00049 QString QgsVectorDataProvider::dataComment() const
00050 {
00051   return QString();
00052 }
00053 
00054 bool QgsVectorDataProvider::addFeatures( QgsFeatureList &flist )
00055 {
00056   Q_UNUSED( flist );
00057   return false;
00058 }
00059 
00060 bool QgsVectorDataProvider::deleteFeatures( const QgsFeatureIds &ids )
00061 {
00062   Q_UNUSED( ids );
00063   return false;
00064 }
00065 
00066 bool QgsVectorDataProvider::addAttributes( const QList<QgsField> &attributes )
00067 {
00068   Q_UNUSED( attributes );
00069   return false;
00070 }
00071 
00072 bool QgsVectorDataProvider::deleteAttributes( const QgsAttributeIds &attributes )
00073 {
00074   Q_UNUSED( attributes );
00075   return false;
00076 }
00077 
00078 bool QgsVectorDataProvider::changeAttributeValues( const QgsChangedAttributesMap &attr_map )
00079 {
00080   Q_UNUSED( attr_map );
00081   return false;
00082 }
00083 
00084 QVariant QgsVectorDataProvider::defaultValue( int fieldId )
00085 {
00086   Q_UNUSED( fieldId );
00087   return QVariant();
00088 }
00089 
00090 bool QgsVectorDataProvider::changeGeometryValues( QgsGeometryMap &geometry_map )
00091 {
00092   Q_UNUSED( geometry_map );
00093   return false;
00094 }
00095 
00096 bool QgsVectorDataProvider::createSpatialIndex()
00097 {
00098   return false;
00099 }
00100 
00101 bool QgsVectorDataProvider::createAttributeIndex( int field )
00102 {
00103   Q_UNUSED( field );
00104   return true;
00105 }
00106 
00107 int QgsVectorDataProvider::capabilities() const
00108 {
00109   return QgsVectorDataProvider::NoCapabilities;
00110 }
00111 
00112 
00113 void QgsVectorDataProvider::setEncoding( const QString& e )
00114 {
00115   QTextCodec* ncodec = QTextCodec::codecForName( e.toLocal8Bit().constData() );
00116   if ( ncodec )
00117   {
00118     mEncoding = ncodec;
00119   }
00120   else
00121   {
00122     QgsMessageLog::logMessage( tr( "Codec %1 not found. Falling back to system locale" ).arg( e ) );
00123     mEncoding = QTextCodec::codecForName( "System" );
00124 
00125     if ( !mEncoding )
00126       mEncoding = QTextCodec::codecForLocale();
00127 
00128     Q_ASSERT( mEncoding );
00129   }
00130 }
00131 
00132 QString QgsVectorDataProvider::encoding() const
00133 {
00134   if ( mEncoding )
00135   {
00136     return mEncoding->name();
00137   }
00138 
00139   return "";
00140 }
00141 
00142 QString QgsVectorDataProvider::capabilitiesString() const
00143 {
00144   QStringList abilitiesList;
00145 
00146   int abilities = capabilities();
00147 
00148   if ( abilities & QgsVectorDataProvider::AddFeatures )
00149   {
00150     abilitiesList += tr( "Add Features" );
00151     QgsDebugMsg( "Capability: Add Features" );
00152   }
00153 
00154   if ( abilities & QgsVectorDataProvider::DeleteFeatures )
00155   {
00156     abilitiesList += tr( "Delete Features" );
00157     QgsDebugMsg( "Capability: Delete Features" );
00158   }
00159 
00160   if ( abilities & QgsVectorDataProvider::ChangeAttributeValues )
00161   {
00162     abilitiesList += tr( "Change Attribute Values" );
00163     QgsDebugMsg( "Capability: Change Attribute Values" );
00164   }
00165 
00166   if ( abilities & QgsVectorDataProvider::AddAttributes )
00167   {
00168     abilitiesList += tr( "Add Attributes" );
00169     QgsDebugMsg( "Capability: Add Attributes" );
00170   }
00171 
00172   if ( abilities & QgsVectorDataProvider::DeleteAttributes )
00173   {
00174     abilitiesList += tr( "Delete Attributes" );
00175     QgsDebugMsg( "Capability: Delete Attributes" );
00176   }
00177 
00178   if ( abilities & QgsVectorDataProvider::CreateSpatialIndex )
00179   {
00180     // TODO: Tighten up this test.  See QgsOgrProvider for details.
00181     abilitiesList += tr( "Create Spatial Index" );
00182     QgsDebugMsg( "Capability: Create Spatial Index" );
00183   }
00184 
00185   if ( abilities & QgsVectorDataProvider::SelectAtId )
00186   {
00187     abilitiesList += tr( "Fast Access to Features at ID" );
00188     QgsDebugMsg( "Capability: Select at ID" );
00189   }
00190 
00191   if ( abilities & QgsVectorDataProvider::ChangeGeometries )
00192   {
00193     abilitiesList += tr( "Change Geometries" );
00194     QgsDebugMsg( "Capability: Change Geometries" );
00195   }
00196 
00197   return abilitiesList.join( ", " );
00198 
00199 }
00200 
00201 
00202 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
00203 {
00204   const QgsFields &theFields = fields();
00205 
00206   for ( int i = 0; i < theFields.count(); ++i )
00207   {
00208     if ( QString::compare( theFields[i].name(), fieldName, Qt::CaseInsensitive ) == 0 )
00209     {
00210       return i;
00211     }
00212   }
00213   return -1;
00214 }
00215 
00216 QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
00217 {
00218   QMap<QString, int> resultMap;
00219 
00220   const QgsFields& theFields = fields();
00221   for ( int i = 0; i < theFields.count(); ++i )
00222   {
00223     resultMap.insert( theFields[i].name(), i );
00224   }
00225 
00226   return resultMap;
00227 }
00228 
00229 QgsAttributeList QgsVectorDataProvider::attributeIndexes()
00230 {
00231   int count = fields().count();
00232   QgsAttributeList list;
00233 
00234   for ( int i = 0; i < count; i++ )
00235     list.append( i );
00236 
00237   return list;
00238 }
00239 
00240 const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
00241 {
00242   return mNativeTypes;
00243 }
00244 
00245 bool QgsVectorDataProvider::supportedType( const QgsField &field ) const
00246 {
00247   int i;
00248   for ( i = 0; i < mNativeTypes.size(); i++ )
00249   {
00250     if ( field.type() == mNativeTypes[i].mType &&
00251          field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
00252          field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
00253     {
00254       return true;
00255     }
00256   }
00257 
00258   return false;
00259 }
00260 
00261 QVariant QgsVectorDataProvider::minimumValue( int index )
00262 {
00263   if ( index < 0 || index >= fields().count() )
00264   {
00265     QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
00266     return QVariant();
00267   }
00268 
00269   fillMinMaxCache();
00270 
00271   if ( !mCacheMinValues.contains( index ) )
00272     return QVariant();
00273 
00274   return mCacheMinValues[index];
00275 }
00276 
00277 QVariant QgsVectorDataProvider::maximumValue( int index )
00278 {
00279   if ( index < 0 || index >= fields().count() )
00280   {
00281     QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
00282     return QVariant();
00283   }
00284 
00285   fillMinMaxCache();
00286 
00287   if ( !mCacheMaxValues.contains( index ) )
00288     return QVariant();
00289 
00290   return mCacheMaxValues[index];
00291 }
00292 
00293 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
00294 {
00295   QgsFeature f;
00296   QgsAttributeList keys;
00297   keys.append( index );
00298   QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
00299 
00300   QSet<QString> set;
00301   values.clear();
00302 
00303   while ( fi.nextFeature( f ) )
00304   {
00305     if ( !set.contains( f.attribute( index ).toString() ) )
00306     {
00307       values.append( f.attribute( index ) );
00308       set.insert( f.attribute( index ).toString() );
00309     }
00310 
00311     if ( limit >= 0 && values.size() >= limit )
00312       break;
00313   }
00314 }
00315 
00316 void QgsVectorDataProvider::clearMinMaxCache()
00317 {
00318   mCacheMinMaxDirty = true;
00319 }
00320 
00321 void QgsVectorDataProvider::fillMinMaxCache()
00322 {
00323   if ( !mCacheMinMaxDirty )
00324     return;
00325 
00326   const QgsFields& flds = fields();
00327   for ( int i = 0; i < flds.count(); ++i )
00328   {
00329     if ( flds[i].type() == QVariant::Int )
00330     {
00331       mCacheMinValues[i] = QVariant( INT_MAX );
00332       mCacheMaxValues[i] = QVariant( INT_MIN );
00333     }
00334     else if ( flds[i].type() == QVariant::Double )
00335     {
00336       mCacheMinValues[i] = QVariant( DBL_MAX );
00337       mCacheMaxValues[i] = QVariant( -DBL_MAX );
00338     }
00339     else
00340     {
00341       mCacheMinValues[i] = QVariant();
00342       mCacheMaxValues[i] = QVariant();
00343     }
00344   }
00345 
00346   QgsFeature f;
00347   QgsAttributeList keys = mCacheMinValues.keys();
00348   QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
00349 
00350   while ( fi.nextFeature( f ) )
00351   {
00352     const QgsAttributes& attrs = f.attributes();
00353     for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
00354     {
00355       const QVariant& varValue = attrs[*it];
00356 
00357       if ( flds[*it].type() == QVariant::Int )
00358       {
00359         int value = varValue.toInt();
00360         if ( value < mCacheMinValues[*it].toInt() )
00361           mCacheMinValues[*it] = value;
00362         if ( value > mCacheMaxValues[*it].toInt() )
00363           mCacheMaxValues[*it] = value;
00364       }
00365       else if ( flds[*it].type() == QVariant::Double )
00366       {
00367         double value = varValue.toDouble();
00368         if ( value < mCacheMinValues[*it].toDouble() )
00369           mCacheMinValues[*it] = value;
00370         if ( value > mCacheMaxValues[*it].toDouble() )
00371           mCacheMaxValues[*it] = value;
00372       }
00373       else
00374       {
00375         QString value = varValue.toString();
00376         if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
00377         {
00378           mCacheMinValues[*it] = value;
00379         }
00380         if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
00381         {
00382           mCacheMaxValues[*it] = value;
00383         }
00384       }
00385     }
00386   }
00387 
00388   mCacheMinMaxDirty = false;
00389 }
00390 
00391 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
00392 {
00393   QVariant v( value );
00394 
00395   if ( !v.convert( type ) )
00396     v = QVariant( QString::null );
00397 
00398   return v;
00399 }
00400 
00401 static bool _compareEncodings( const QString& s1, const QString& s2 )
00402 {
00403   return s1.toLower() < s2.toLower();
00404 }
00405 
00406 const QStringList &QgsVectorDataProvider::availableEncodings()
00407 {
00408   if ( smEncodings.isEmpty() )
00409   {
00410     foreach ( QString codec, QTextCodec::availableCodecs() )
00411     {
00412       smEncodings << codec;
00413     }
00414 #if 0
00415     smEncodings << "BIG5";
00416     smEncodings << "BIG5-HKSCS";
00417     smEncodings << "EUCJP";
00418     smEncodings << "EUCKR";
00419     smEncodings << "GB2312";
00420     smEncodings << "GBK";
00421     smEncodings << "GB18030";
00422     smEncodings << "JIS7";
00423     smEncodings << "SHIFT-JIS";
00424     smEncodings << "TSCII";
00425     smEncodings << "UTF-8";
00426     smEncodings << "UTF-16";
00427     smEncodings << "KOI8-R";
00428     smEncodings << "KOI8-U";
00429     smEncodings << "ISO8859-1";
00430     smEncodings << "ISO8859-2";
00431     smEncodings << "ISO8859-3";
00432     smEncodings << "ISO8859-4";
00433     smEncodings << "ISO8859-5";
00434     smEncodings << "ISO8859-6";
00435     smEncodings << "ISO8859-7";
00436     smEncodings << "ISO8859-8";
00437     smEncodings << "ISO8859-8-I";
00438     smEncodings << "ISO8859-9";
00439     smEncodings << "ISO8859-10";
00440     smEncodings << "ISO8859-11";
00441     smEncodings << "ISO8859-12";
00442     smEncodings << "ISO8859-13";
00443     smEncodings << "ISO8859-14";
00444     smEncodings << "ISO8859-15";
00445     smEncodings << "IBM 850";
00446     smEncodings << "IBM 866";
00447     smEncodings << "CP874";
00448     smEncodings << "CP1250";
00449     smEncodings << "CP1251";
00450     smEncodings << "CP1252";
00451     smEncodings << "CP1253";
00452     smEncodings << "CP1254";
00453     smEncodings << "CP1255";
00454     smEncodings << "CP1256";
00455     smEncodings << "CP1257";
00456     smEncodings << "CP1258";
00457     smEncodings << "Apple Roman";
00458     smEncodings << "TIS-620";
00459     smEncodings << "System";
00460 #endif
00461   }
00462 
00463   // Do case-insensitive sorting of encodings
00464   qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
00465 
00466   return smEncodings;
00467 }
00468 
00469 void QgsVectorDataProvider::clearErrors()
00470 {
00471   mErrors.clear();
00472 }
00473 
00474 bool QgsVectorDataProvider::hasErrors()
00475 {
00476   return !mErrors.isEmpty();
00477 }
00478 
00479 QStringList QgsVectorDataProvider::errors()
00480 {
00481   return mErrors;
00482 }
00483 
00484 void QgsVectorDataProvider::pushError( QString msg )
00485 {
00486   mErrors << msg;
00487 }
00488 
00489 QStringList QgsVectorDataProvider::smEncodings;
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines