QGIS API Documentation
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 : [email protected]
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 #include <limits>
22 
23 #include "qgsvectordataprovider.h"
24 #include "qgsfeature.h"
25 #include "qgsfeatureiterator.h"
26 #include "qgsfeaturerequest.h"
27 #include "qgsfield.h"
28 #include "qgslogger.h"
29 #include "qgsmessagelog.h"
30 
32  : QgsDataProvider( uri )
33  , mCacheMinMaxDirty( true )
34  , mAttrPalIndexName( QgsAttrPalIndexNameHash() )
35 {
36  QSettings settings;
37  setEncoding( settings.value( "/UI/encoding", "System" ).toString() );
38 }
39 
40 
42 {
43 }
44 
46 {
47  return "Generic vector file";
48 }
49 
51 {
52  return QString();
53 }
54 
56 {
57  Q_UNUSED( flist );
58  return false;
59 }
60 
62 {
63  Q_UNUSED( ids );
64  return false;
65 }
66 
68 {
69  Q_UNUSED( attributes );
70  return false;
71 }
72 
74 {
75  Q_UNUSED( attributes );
76  return false;
77 }
78 
80 {
81  Q_UNUSED( attr_map );
82  return false;
83 }
84 
86 {
87  Q_UNUSED( fieldId );
88  return QVariant();
89 }
90 
92 {
93  Q_UNUSED( geometry_map );
94  return false;
95 }
96 
98  const QgsGeometryMap &geometry_map )
99 {
100  Q_UNUSED( attr_map );
101  Q_UNUSED( geometry_map );
102  return false;
103 }
104 
106 {
107  return false;
108 }
109 
111 {
112  Q_UNUSED( field );
113  return true;
114 }
115 
117 {
119 }
120 
121 
123 {
125  if ( ncodec )
126  {
127  mEncoding = ncodec;
128  }
129  else
130  {
131  QgsMessageLog::logMessage( tr( "Codec %1 not found. Falling back to system locale" ).arg( e ) );
132  mEncoding = QTextCodec::codecForName( "System" );
133 
134  if ( !mEncoding )
136 
137  Q_ASSERT( mEncoding );
138  }
139 }
140 
142 {
143  if ( mEncoding )
144  {
145  return mEncoding->name();
146  }
147 
148  return "";
149 }
150 
152 {
153  QStringList abilitiesList;
154 
155  int abilities = capabilities();
156 
157  if ( abilities & QgsVectorDataProvider::AddFeatures )
158  {
159  abilitiesList += tr( "Add Features" );
160  QgsDebugMsg( "Capability: Add Features" );
161  }
162 
163  if ( abilities & QgsVectorDataProvider::DeleteFeatures )
164  {
165  abilitiesList += tr( "Delete Features" );
166  QgsDebugMsg( "Capability: Delete Features" );
167  }
168 
170  {
171  abilitiesList += tr( "Change Attribute Values" );
172  QgsDebugMsg( "Capability: Change Attribute Values" );
173  }
174 
175  if ( abilities & QgsVectorDataProvider::AddAttributes )
176  {
177  abilitiesList += tr( "Add Attributes" );
178  QgsDebugMsg( "Capability: Add Attributes" );
179  }
180 
181  if ( abilities & QgsVectorDataProvider::DeleteAttributes )
182  {
183  abilitiesList += tr( "Delete Attributes" );
184  QgsDebugMsg( "Capability: Delete Attributes" );
185  }
186 
188  {
189  // TODO: Tighten up this test. See QgsOgrProvider for details.
190  abilitiesList += tr( "Create Spatial Index" );
191  QgsDebugMsg( "Capability: Create Spatial Index" );
192  }
193 
194  if ( abilities & QgsVectorDataProvider::SelectAtId )
195  {
196  abilitiesList += tr( "Fast Access to Features at ID" );
197  QgsDebugMsg( "Capability: Select at ID" );
198  }
199 
200  if ( abilities & QgsVectorDataProvider::ChangeGeometries )
201  {
202  abilitiesList += tr( "Change Geometries" );
203  QgsDebugMsg( "Capability: Change Geometries" );
204  }
205 
207  {
208  abilitiesList += tr( "Presimplify Geometries" );
209  QgsDebugMsg( "Capability: Simplify Geometries before fetching the feature" );
210  }
211 
213  {
214  abilitiesList += tr( "Presimplify Geometries with Validity Check" );
215  QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature ensuring that the result is a valid geometry" );
216  }
217 
218  if ( abilities & QgsVectorDataProvider::ChangeFeatures )
219  {
220  abilitiesList += tr( "Simultaneous Geometry and Attribute Updates" );
221  QgsDebugMsg( "Capability: change both feature attributes and geometry at once" );
222  }
223 
224  return abilitiesList.join( ", " );
225 }
226 
227 
228 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
229 {
230  return fields().fieldNameIndex( fieldName );
231 }
232 
234 {
235  QMap<QString, int> resultMap;
236 
237  const QgsFields& theFields = fields();
238  for ( int i = 0; i < theFields.count(); ++i )
239  {
240  resultMap.insert( theFields[i].name(), i );
241  }
242 
243  return resultMap;
244 }
245 
247 {
248  return fields().allAttributesList();
249 }
250 
252 {
253  return mNativeTypes;
254 }
255 
257 {
258  int i;
259  QgsDebugMsgLevel( QString( "field name = %1 type = %2 length = %3 precision = %4" )
260  .arg( field.name(),
261  QVariant::typeToName( field.type() ) )
262  .arg( field.length() )
263  .arg( field.precision() ), 2 );
264  for ( i = 0; i < mNativeTypes.size(); i++ )
265  {
266  QgsDebugMsgLevel( QString( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" )
267  .arg( QVariant::typeToName( mNativeTypes[i].mType ) )
268  .arg( mNativeTypes[i].mMinLen )
269  .arg( mNativeTypes[i].mMaxLen )
270  .arg( mNativeTypes[i].mMinPrec )
271  .arg( mNativeTypes[i].mMaxPrec ), 2 );
272 
273  if ( field.type() != mNativeTypes[i].mType )
274  continue;
275 
276  if ( field.length() == -1 )
277  {
278  // source length unlimited
279  if ( mNativeTypes[i].mMinLen > -1 || mNativeTypes[i].mMaxLen > -1 )
280  {
281  // destination limited
282  continue;
283  }
284  }
285  else
286  {
287  // source length limited
288  if ( mNativeTypes[i].mMinLen > -1 && mNativeTypes[i].mMaxLen > -1 &&
289  ( field.length() < mNativeTypes[i].mMinLen || field.length() > mNativeTypes[i].mMaxLen ) )
290  {
291  // source length exceeds destination limits
292  continue;
293  }
294  }
295 
296  if ( field.precision() == -1 )
297  {
298  // source precision unlimited / n/a
299  if ( mNativeTypes[i].mMinPrec > -1 || mNativeTypes[i].mMaxPrec > -1 )
300  {
301  // destination limited
302  continue;
303  }
304  }
305  else
306  {
307  // source precision unlimited / n/a
308  if ( mNativeTypes[i].mMinPrec > -1 && mNativeTypes[i].mMaxPrec > -1 &&
309  ( field.precision() < mNativeTypes[i].mMinPrec || field.precision() > mNativeTypes[i].mMaxPrec ) )
310  {
311  // source precision exceeds destination limits
312  continue;
313  }
314  }
315 
316  QgsDebugMsg( "native type matches" );
317  return true;
318  }
319 
320  QgsDebugMsg( "no sufficient native type found" );
321  return false;
322 }
323 
325 {
326  if ( index < 0 || index >= fields().count() )
327  {
328  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
329  return QVariant();
330  }
331 
332  fillMinMaxCache();
333 
334  if ( !mCacheMinValues.contains( index ) )
335  return QVariant();
336 
337  return mCacheMinValues[index];
338 }
339 
341 {
342  if ( index < 0 || index >= fields().count() )
343  {
344  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
345  return QVariant();
346  }
347 
348  fillMinMaxCache();
349 
350  if ( !mCacheMaxValues.contains( index ) )
351  return QVariant();
352 
353  return mCacheMaxValues[index];
354 }
355 
357 {
358  QgsFeature f;
359  QgsAttributeList keys;
360  keys.append( index );
361  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
362 
363  QSet<QString> set;
364  values.clear();
365 
366  while ( fi.nextFeature( f ) )
367  {
368  if ( !set.contains( f.attribute( index ).toString() ) )
369  {
370  values.append( f.attribute( index ) );
371  set.insert( f.attribute( index ).toString() );
372  }
373 
374  if ( limit >= 0 && values.size() >= limit )
375  break;
376  }
377 }
378 
380 {
381  mCacheMinMaxDirty = true;
382 }
383 
385 {
386  if ( !mCacheMinMaxDirty )
387  return;
388 
389  const QgsFields& flds = fields();
390  for ( int i = 0; i < flds.count(); ++i )
391  {
392  if ( flds[i].type() == QVariant::Int )
393  {
394  mCacheMinValues[i] = QVariant( INT_MAX );
395  mCacheMaxValues[i] = QVariant( INT_MIN );
396  }
397  else if ( flds[i].type() == QVariant::LongLong )
398  {
401  }
402  else if ( flds[i].type() == QVariant::Double )
403  {
404  mCacheMinValues[i] = QVariant( DBL_MAX );
405  mCacheMaxValues[i] = QVariant( -DBL_MAX );
406  }
407  else
408  {
409  mCacheMinValues[i] = QVariant();
410  mCacheMaxValues[i] = QVariant();
411  }
412  }
413 
414  QgsFeature f;
416  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
417 
418  while ( fi.nextFeature( f ) )
419  {
420  QgsAttributes attrs = f.attributes();
421  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
422  {
423  const QVariant& varValue = attrs.at( *it );
424 
425  if ( varValue.isNull() )
426  continue;
427 
428  if ( flds[*it].type() == QVariant::Int )
429  {
430  int value = varValue.toInt();
431  if ( value < mCacheMinValues[*it].toInt() )
432  mCacheMinValues[*it] = value;
433  if ( value > mCacheMaxValues[*it].toInt() )
434  mCacheMaxValues[*it] = value;
435  }
436  else if ( flds[*it].type() == QVariant::LongLong )
437  {
438  qlonglong value = varValue.toLongLong();
439  if ( value < mCacheMinValues[*it].toLongLong() )
440  mCacheMinValues[*it] = value;
441  if ( value > mCacheMaxValues[*it].toLongLong() )
442  mCacheMaxValues[*it] = value;
443  }
444  else if ( flds[*it].type() == QVariant::Double )
445  {
446  double value = varValue.toDouble();
447  if ( value < mCacheMinValues[*it].toDouble() )
448  mCacheMinValues[*it] = value;
449  if ( value > mCacheMaxValues[*it].toDouble() )
450  mCacheMaxValues[*it] = value;
451  }
452  else
453  {
454  QString value = varValue.toString();
455  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
456  {
457  mCacheMinValues[*it] = value;
458  }
459  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
460  {
461  mCacheMaxValues[*it] = value;
462  }
463  }
464  }
465  }
466 
467  mCacheMinMaxDirty = false;
468 }
469 
470 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, const QString& value )
471 {
472  QVariant v( value );
473 
474  if ( !v.convert( type ) || value.isNull() )
475  v = QVariant( type );
476 
477  return v;
478 }
479 
480 static bool _compareEncodings( const QString& s1, const QString& s2 )
481 {
482  return s1.toLower() < s2.toLower();
483 }
484 
486 {
487  if ( smEncodings.isEmpty() )
488  {
489  Q_FOREACH ( const QString& codec, QTextCodec::availableCodecs() )
490  {
491  smEncodings << codec;
492  }
493 #if 0
494  smEncodings << "BIG5";
495  smEncodings << "BIG5-HKSCS";
496  smEncodings << "EUCJP";
497  smEncodings << "EUCKR";
498  smEncodings << "GB2312";
499  smEncodings << "GBK";
500  smEncodings << "GB18030";
501  smEncodings << "JIS7";
502  smEncodings << "SHIFT-JIS";
503  smEncodings << "TSCII";
504  smEncodings << "UTF-8";
505  smEncodings << "UTF-16";
506  smEncodings << "KOI8-R";
507  smEncodings << "KOI8-U";
508  smEncodings << "ISO8859-1";
509  smEncodings << "ISO8859-2";
510  smEncodings << "ISO8859-3";
511  smEncodings << "ISO8859-4";
512  smEncodings << "ISO8859-5";
513  smEncodings << "ISO8859-6";
514  smEncodings << "ISO8859-7";
515  smEncodings << "ISO8859-8";
516  smEncodings << "ISO8859-8-I";
517  smEncodings << "ISO8859-9";
518  smEncodings << "ISO8859-10";
519  smEncodings << "ISO8859-11";
520  smEncodings << "ISO8859-12";
521  smEncodings << "ISO8859-13";
522  smEncodings << "ISO8859-14";
523  smEncodings << "ISO8859-15";
524  smEncodings << "IBM 850";
525  smEncodings << "IBM 866";
526  smEncodings << "CP874";
527  smEncodings << "CP1250";
528  smEncodings << "CP1251";
529  smEncodings << "CP1252";
530  smEncodings << "CP1253";
531  smEncodings << "CP1254";
532  smEncodings << "CP1255";
533  smEncodings << "CP1256";
534  smEncodings << "CP1257";
535  smEncodings << "CP1258";
536  smEncodings << "Apple Roman";
537  smEncodings << "TIS-620";
538  smEncodings << "System";
539 #endif
540  }
541 
542  // Do case-insensitive sorting of encodings
543  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
544 
545  return smEncodings;
546 }
547 
549 {
550  mErrors.clear();
551 }
552 
554 {
555  return !mErrors.isEmpty();
556 }
557 
559 {
560  return mErrors;
561 }
562 
564 {
565  QgsDebugMsg( msg );
566  mErrors << msg;
567  emit raiseError( msg );
568 }
569 
571 {
572  return QSet<QString>();
573 }
574 
575 QStringList QgsVectorDataProvider::smEncodings;
virtual QSet< QString > layerDependencies() const
Get the list of layer ids on which this layer depends.
qlonglong toLongLong(bool *ok) const
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
static QVariant convertValue(QVariant::Type type, const QString &value)
bool contains(const Key &key) const
virtual QByteArray name() const =0
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:33
Supports simplification of geometries on provider side according to a distance tolerance.
int fieldNameIndex(const QString &fieldName) const
Look up field&#39;s index from name also looks up case-insensitive if there is no match otherwise...
Definition: qgsfield.cpp:534
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:104
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:187
QStringList errors()
Get recorded errors.
QMap< int, QVariant > mCacheMaxValues
Abstract base class for spatial data provider implementations.
Allows deletion of attributes (fields)
QString join(const QString &separator) const
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:187
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.
QString tr(const char *sourceText, const char *disambiguation, int n)
QTextCodec * codecForLocale()
virtual QString name() const =0
Return a provider name.
virtual bool createAttributeIndex(int field)
Create an attribute index on the datasource.
int size() const
bool isNull() const
static const QStringList & availableEncodings()
Returns a list of available encodings.
double ANALYSIS_EXPORT max(double x, double y)
Returns the maximum of two doubles or the first argument if both are equal.
QList< Key > keys() const
Allows creation of spatial index.
QString encoding() const
Get encoding which is used for accessing data.
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).
QString number(int n, int base)
void append(const T &value)
QTextCodec * mEncoding
Encoding.
bool supportedType(const QgsField &field) const
check if provider supports type of field
int toInt(bool *ok) const
bool isNull() const
Allows addition of new attributes (fields)
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:34
virtual QString dataComment() const
Return a short comment for the data that this provider is providing access to (e.g.
QgsAttributes attributes() const
Returns the feature&#39;s attributes.
Definition: qgsfeature.cpp:110
virtual int capabilities() const
Returns a bitmask containing the supported capabilities Note, some capabilities may change depending ...
bool hasErrors()
Provider has errors to report.
QString name() const
Gets the name of the field.
Definition: qgsfield.cpp:84
virtual bool changeAttributeValues(const QgsChangedAttributesMap &attr_map)
Changes attribute values of existing features.
bool isEmpty() const
virtual bool changeFeatures(const QgsChangedAttributesMap &attr_map, const QgsGeometryMap &geometry_map)
Changes attribute values and geometries of existing features.
const char * constData() const
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.
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
This class wraps a request for features to a vector layer (or directly its vector data provider)...
QList< NativeType > mNativeTypes
The names of the providers native types.
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.cpp:365
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:44
Fast access to features using their ID.
virtual bool changeGeometryValues(const QgsGeometryMap &geometry_map)
Changes geometries of existing features.
QMap< QString, int > fieldNameMap() const
Return a map where the key is the name of the field and the value is its index.
QgsVectorDataProvider(const QString &uri=QString())
Constructor of the vector provider.
iterator end()
QString toLower() const
QByteArray toLocal8Bit() const
void raiseError(const QString &msg)
Signals an error in this provider.
Supports joint updates for attributes and geometry Providers supporting this should still define Chan...
Supports topological simplification of geometries on provider side according to a distance tolerance...
const char * typeToName(Type typ)
const T & at(int i) const
QVariant value(const QString &key, const QVariant &defaultValue) const
QList< QByteArray > availableCodecs()
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:271
virtual QVariant defaultValue(int fieldId)
Returns the default value for field specified by fieldId.
virtual QVariant minimumValue(int index)
Returns the minimum value of an attribute.
QTextCodec * codecForName(const QByteArray &name)
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:99
virtual ~QgsVectorDataProvider()
Destructor.
virtual bool deleteAttributes(const QgsAttributeIds &attributes)
Deletes existing attributes.
double toDouble(bool *ok) const
iterator insert(const Key &key, const T &value)
void pushError(const QString &msg)
double ANALYSIS_EXPORT min(double x, double y)
Returns the minimum of two doubles or the first argument if both are equal.
bool nextFeature(QgsFeature &f)
Provider has no capabilities.
A vector of attributes.
Definition: qgsfeature.h:115
bool convert(Type t)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
QgsAttributeList allAttributesList() const
Utility function to get list of attribute indexes.
Definition: qgsfield.cpp:551
iterator begin()
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:89