|
QGIS API Documentation
master-6227475
|
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;