QGIS API Documentation  2.3.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsvectordataprovider.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectordataprovider.cpp - DataProvider Interface for vector layers
3  --------------------------------------
4  Date : 26-Oct-2004
5  Copyright : (C) 2004 by Marco Hugentobler
6  email : marco.hugentobler@autoform.ch
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QSettings>
17 #include <QTextCodec>
18 
19 #include <cfloat> // for DBL_MAX
20 #include <climits>
21 
22 #include "qgsvectordataprovider.h"
23 #include "qgsfeature.h"
24 #include "qgsfeatureiterator.h"
25 #include "qgsfeaturerequest.h"
26 #include "qgsfield.h"
27 #include "qgslogger.h"
28 #include "qgsmessagelog.h"
29 
31  : QgsDataProvider( uri )
32  , mCacheMinMaxDirty( true )
33  , mAttrPalIndexName( QgsAttrPalIndexNameHash() )
34 {
35  QSettings settings;
36  setEncoding( settings.value( "/UI/encoding", "System" ).toString() );
37 }
38 
39 
41 {
42 }
43 
45 {
46  return "Generic vector file";
47 }
48 
50 {
51  return QString();
52 }
53 
55 {
56  Q_UNUSED( flist );
57  return false;
58 }
59 
61 {
62  Q_UNUSED( ids );
63  return false;
64 }
65 
66 bool QgsVectorDataProvider::addAttributes( const QList<QgsField> &attributes )
67 {
68  Q_UNUSED( attributes );
69  return false;
70 }
71 
73 {
74  Q_UNUSED( attributes );
75  return false;
76 }
77 
79 {
80  Q_UNUSED( attr_map );
81  return false;
82 }
83 
84 QVariant QgsVectorDataProvider::defaultValue( int fieldId )
85 {
86  Q_UNUSED( fieldId );
87  return QVariant();
88 }
89 
91 {
92  Q_UNUSED( geometry_map );
93  return false;
94 }
95 
97 {
98  return false;
99 }
100 
102 {
103  Q_UNUSED( field );
104  return true;
105 }
106 
108 {
110 }
111 
112 
113 void QgsVectorDataProvider::setEncoding( const QString& e )
114 {
115  QTextCodec* ncodec = QTextCodec::codecForName( e.toLocal8Bit().constData() );
116  if ( ncodec )
117  {
118  mEncoding = ncodec;
119  }
120  else
121  {
122  QgsMessageLog::logMessage( tr( "Codec %1 not found. Falling back to system locale" ).arg( e ) );
123  mEncoding = QTextCodec::codecForName( "System" );
124 
125  if ( !mEncoding )
126  mEncoding = QTextCodec::codecForLocale();
127 
128  Q_ASSERT( mEncoding );
129  }
130 }
131 
133 {
134  if ( mEncoding )
135  {
136  return mEncoding->name();
137  }
138 
139  return "";
140 }
141 
143 {
144  QStringList abilitiesList;
145 
146  int abilities = capabilities();
147 
148  if ( abilities & QgsVectorDataProvider::AddFeatures )
149  {
150  abilitiesList += tr( "Add Features" );
151  QgsDebugMsg( "Capability: Add Features" );
152  }
153 
154  if ( abilities & QgsVectorDataProvider::DeleteFeatures )
155  {
156  abilitiesList += tr( "Delete Features" );
157  QgsDebugMsg( "Capability: Delete Features" );
158  }
159 
161  {
162  abilitiesList += tr( "Change Attribute Values" );
163  QgsDebugMsg( "Capability: Change Attribute Values" );
164  }
165 
166  if ( abilities & QgsVectorDataProvider::AddAttributes )
167  {
168  abilitiesList += tr( "Add Attributes" );
169  QgsDebugMsg( "Capability: Add Attributes" );
170  }
171 
172  if ( abilities & QgsVectorDataProvider::DeleteAttributes )
173  {
174  abilitiesList += tr( "Delete Attributes" );
175  QgsDebugMsg( "Capability: Delete Attributes" );
176  }
177 
179  {
180  // TODO: Tighten up this test. See QgsOgrProvider for details.
181  abilitiesList += tr( "Create Spatial Index" );
182  QgsDebugMsg( "Capability: Create Spatial Index" );
183  }
184 
185  if ( abilities & QgsVectorDataProvider::SelectAtId )
186  {
187  abilitiesList += tr( "Fast Access to Features at ID" );
188  QgsDebugMsg( "Capability: Select at ID" );
189  }
190 
191  if ( abilities & QgsVectorDataProvider::ChangeGeometries )
192  {
193  abilitiesList += tr( "Change Geometries" );
194  QgsDebugMsg( "Capability: Change Geometries" );
195  }
196 
198  {
199  abilitiesList += tr( "Simplify Geometries" );
200  QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature" );
201  }
202 
204  {
205  abilitiesList += tr( "Simplify Geometries with topological validation" );
206  QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature ensuring that the result is a valid geometry" );
207  }
208 
209  return abilitiesList.join( ", " );
210 
211 }
212 
213 
214 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
215 {
216  const QgsFields &theFields = fields();
217 
218  for ( int i = 0; i < theFields.count(); ++i )
219  {
220  if ( QString::compare( theFields[i].name(), fieldName, Qt::CaseInsensitive ) == 0 )
221  {
222  return i;
223  }
224  }
225  return -1;
226 }
227 
228 QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
229 {
230  QMap<QString, int> resultMap;
231 
232  const QgsFields& theFields = fields();
233  for ( int i = 0; i < theFields.count(); ++i )
234  {
235  resultMap.insert( theFields[i].name(), i );
236  }
237 
238  return resultMap;
239 }
240 
242 {
243  return fields().allAttributesList();
244 }
245 
246 const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
247 {
248  return mNativeTypes;
249 }
250 
252 {
253  int i;
254  QgsDebugMsgLevel( QString( "field name = %1 type = %2 length = %3 precision = %4" )
255  .arg( field.name() )
256  .arg( QVariant::typeToName( field.type() ) )
257  .arg( field.length() )
258  .arg( field.precision() ), 2 );
259  for ( i = 0; i < mNativeTypes.size(); i++ )
260  {
261  QgsDebugMsgLevel( QString( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" )
262  .arg( QVariant::typeToName( mNativeTypes[i].mType ) )
263  .arg( mNativeTypes[i].mMinLen )
264  .arg( mNativeTypes[i].mMaxLen )
265  .arg( mNativeTypes[i].mMinPrec )
266  .arg( mNativeTypes[i].mMaxPrec ), 2 );
267  if ( field.type() == mNativeTypes[i].mType &&
268  field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
269  field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
270  {
271  QgsDebugMsg( "native type matches" );
272  return true;
273  }
274  }
275 
276  QgsDebugMsg( "no sufficient native type found" );
277  return false;
278 }
279 
281 {
282  if ( index < 0 || index >= fields().count() )
283  {
284  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
285  return QVariant();
286  }
287 
288  fillMinMaxCache();
289 
290  if ( !mCacheMinValues.contains( index ) )
291  return QVariant();
292 
293  return mCacheMinValues[index];
294 }
295 
297 {
298  if ( index < 0 || index >= fields().count() )
299  {
300  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
301  return QVariant();
302  }
303 
304  fillMinMaxCache();
305 
306  if ( !mCacheMaxValues.contains( index ) )
307  return QVariant();
308 
309  return mCacheMaxValues[index];
310 }
311 
312 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
313 {
314  QgsFeature f;
315  QgsAttributeList keys;
316  keys.append( index );
317  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
318 
319  QSet<QString> set;
320  values.clear();
321 
322  while ( fi.nextFeature( f ) )
323  {
324  if ( !set.contains( f.attribute( index ).toString() ) )
325  {
326  values.append( f.attribute( index ) );
327  set.insert( f.attribute( index ).toString() );
328  }
329 
330  if ( limit >= 0 && values.size() >= limit )
331  break;
332  }
333 }
334 
336 {
337  mCacheMinMaxDirty = true;
338 }
339 
341 {
342  if ( !mCacheMinMaxDirty )
343  return;
344 
345  const QgsFields& flds = fields();
346  for ( int i = 0; i < flds.count(); ++i )
347  {
348  if ( flds[i].type() == QVariant::Int )
349  {
350  mCacheMinValues[i] = QVariant( INT_MAX );
351  mCacheMaxValues[i] = QVariant( INT_MIN );
352  }
353  else if ( flds[i].type() == QVariant::Double )
354  {
355  mCacheMinValues[i] = QVariant( DBL_MAX );
356  mCacheMaxValues[i] = QVariant( -DBL_MAX );
357  }
358  else
359  {
360  mCacheMinValues[i] = QVariant();
361  mCacheMaxValues[i] = QVariant();
362  }
363  }
364 
365  QgsFeature f;
366  QgsAttributeList keys = mCacheMinValues.keys();
367  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
368 
369  while ( fi.nextFeature( f ) )
370  {
371  const QgsAttributes& attrs = f.attributes();
372  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
373  {
374  const QVariant& varValue = attrs[*it];
375 
376  if ( flds[*it].type() == QVariant::Int )
377  {
378  int value = varValue.toInt();
379  if ( value < mCacheMinValues[*it].toInt() )
380  mCacheMinValues[*it] = value;
381  if ( value > mCacheMaxValues[*it].toInt() )
382  mCacheMaxValues[*it] = value;
383  }
384  else if ( flds[*it].type() == QVariant::Double )
385  {
386  double value = varValue.toDouble();
387  if ( value < mCacheMinValues[*it].toDouble() )
388  mCacheMinValues[*it] = value;
389  if ( value > mCacheMaxValues[*it].toDouble() )
390  mCacheMaxValues[*it] = value;
391  }
392  else
393  {
394  QString value = varValue.toString();
395  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
396  {
397  mCacheMinValues[*it] = value;
398  }
399  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
400  {
401  mCacheMaxValues[*it] = value;
402  }
403  }
404  }
405  }
406 
407  mCacheMinMaxDirty = false;
408 }
409 
410 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
411 {
412  QVariant v( value );
413 
414  if ( !v.convert( type ) || value.isNull() )
415  v = QVariant( type );
416 
417  return v;
418 }
419 
420 static bool _compareEncodings( const QString& s1, const QString& s2 )
421 {
422  return s1.toLower() < s2.toLower();
423 }
424 
426 {
427  if ( smEncodings.isEmpty() )
428  {
429  foreach ( QString codec, QTextCodec::availableCodecs() )
430  {
431  smEncodings << codec;
432  }
433 #if 0
434  smEncodings << "BIG5";
435  smEncodings << "BIG5-HKSCS";
436  smEncodings << "EUCJP";
437  smEncodings << "EUCKR";
438  smEncodings << "GB2312";
439  smEncodings << "GBK";
440  smEncodings << "GB18030";
441  smEncodings << "JIS7";
442  smEncodings << "SHIFT-JIS";
443  smEncodings << "TSCII";
444  smEncodings << "UTF-8";
445  smEncodings << "UTF-16";
446  smEncodings << "KOI8-R";
447  smEncodings << "KOI8-U";
448  smEncodings << "ISO8859-1";
449  smEncodings << "ISO8859-2";
450  smEncodings << "ISO8859-3";
451  smEncodings << "ISO8859-4";
452  smEncodings << "ISO8859-5";
453  smEncodings << "ISO8859-6";
454  smEncodings << "ISO8859-7";
455  smEncodings << "ISO8859-8";
456  smEncodings << "ISO8859-8-I";
457  smEncodings << "ISO8859-9";
458  smEncodings << "ISO8859-10";
459  smEncodings << "ISO8859-11";
460  smEncodings << "ISO8859-12";
461  smEncodings << "ISO8859-13";
462  smEncodings << "ISO8859-14";
463  smEncodings << "ISO8859-15";
464  smEncodings << "IBM 850";
465  smEncodings << "IBM 866";
466  smEncodings << "CP874";
467  smEncodings << "CP1250";
468  smEncodings << "CP1251";
469  smEncodings << "CP1252";
470  smEncodings << "CP1253";
471  smEncodings << "CP1254";
472  smEncodings << "CP1255";
473  smEncodings << "CP1256";
474  smEncodings << "CP1257";
475  smEncodings << "CP1258";
476  smEncodings << "Apple Roman";
477  smEncodings << "TIS-620";
478  smEncodings << "System";
479 #endif
480  }
481 
482  // Do case-insensitive sorting of encodings
483  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
484 
485  return smEncodings;
486 }
487 
489 {
490  mErrors.clear();
491 }
492 
494 {
495  return !mErrors.isEmpty();
496 }
497 
499 {
500  return mErrors;
501 }
502 
504 {
505  mErrors << msg;
506 }
507 
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:55
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:324
static unsigned index
static bool _compareEncodings(const QString &s1, const QString &s2)
virtual bool addAttributes(const QList< QgsField > &attributes)
Adds new attributes.
QString capabilitiesString() const
Returns the above in friendly format.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:326
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:331
supports simplification of geometries on provider side according to a distance tolerance ...
virtual QgsAttributeList attributeIndexes()
Return list of indexes to fetch all attributes in nextFeature()
virtual bool deleteFeatures(const QgsFeatureIds &id)
Deletes one or more features.
virtual void setEncoding(const QString &e)
Set encoding used for accessing data from layer.
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:75
virtual void uniqueValues(int index, QList< QVariant > &uniqueValues, int limit=-1)
Return unique values of an attribute.
Container of fields for a vector layer.
Definition: qgsfield.h:164
QStringList errors()
Get recorded errors.
QgsVectorDataProvider(QString uri=QString())
Constructor of the vector provider.
static QVariant convertValue(QVariant::Type type, QString value)
QMap< int, QVariant > mCacheMaxValues
Abstract base class for spatial data provider implementations.
allows deletion of attributes (fields)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:114
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
virtual bool addFeatures(QgsFeatureList &flist)
Adds a list of features.
virtual QString name() const =0
return a provider name
virtual bool createAttributeIndex(int field)
Create an attribute index on the datasource.
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
static const QStringList & availableEncodings()
Returns a list of available encodings.
allows creation of spatial index
QString encoding() const
Get encoding which is used for accessing data.
QSet< int > QgsAttributeIds
virtual QVariant maximumValue(int index)
Returns the maximum value of an attribute.
virtual bool createSpatialIndex()
Creates a spatial index on the datasource (if supported by the provider type).
QTextCodec * mEncoding
Encoding.
bool supportedType(const QgsField &field) const
check if provider supports type of field
allows addition of new attributes (fields)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:37
virtual QString dataComment() const
Return a short comment for the data that this provider is providing access to (e.g.
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
bool hasErrors()
Provider has errors to report.
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
const QList< NativeType > & nativeTypes() const
Returns the names of the supported types.
virtual QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< int > QgsAttributeList
QList< NativeType > mNativeTypes
The names of the providers native types.
const QgsAttributes & attributes() const
Definition: qgsfeature.h:143
allows modifications of geometries
virtual QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())=0
Query the provider for features specified in request.
void clearErrors()
Clear recorded errors.
int count() const
Return number of items.
Definition: qgsfield.h:198
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:31
fast access to features using their ID
QMap< QString, int > fieldNameMap() const
Return a map where the key is the name of the field and the value is its index.
virtual bool changeGeometryValues(QgsGeometryMap &geometry_map)
Changes geometries of existing features.
supports topological simplification of geometries on provider side according to a distance tolerance ...
QStringList mErrors
list of errors
virtual const QgsFields & fields() const =0
Return a map of indexes with field names for this layer.
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
virtual QVariant defaultValue(int fieldId)
Returns the default value for field specified by fieldId.
QMap< QgsFeatureId, QgsAttributeMap > QgsChangedAttributesMap
Definition: qgsfeature.h:321
static QStringList smEncodings
QVector< QVariant > QgsAttributes
Definition: qgsfeature.h:100
virtual QVariant minimumValue(int index)
Returns the minimum value of an attribute.
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:70
virtual ~QgsVectorDataProvider()
Destructor.
virtual bool deleteAttributes(const QgsAttributeIds &attributes)
Deletes existing attributes.
bool nextFeature(QgsFeature &f)
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:184
QHash< int, QString > QgsAttrPalIndexNameHash
allows modification of attribute values
bool isNull(const QVariant &v)
QMap< int, QVariant > mCacheMinValues
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:60
#define tr(sourceText)