QGIS API Documentation  2.14.5-Essen
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 #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  const QgsFields &theFields = fields();
231 
232  for ( int i = 0; i < theFields.count(); ++i )
233  {
234  if ( QString::compare( theFields[i].name(), fieldName, Qt::CaseInsensitive ) == 0 )
235  {
236  return i;
237  }
238  }
239  return -1;
240 }
241 
243 {
244  QMap<QString, int> resultMap;
245 
246  const QgsFields& theFields = fields();
247  for ( int i = 0; i < theFields.count(); ++i )
248  {
249  resultMap.insert( theFields[i].name(), i );
250  }
251 
252  return resultMap;
253 }
254 
256 {
257  return fields().allAttributesList();
258 }
259 
261 {
262  return mNativeTypes;
263 }
264 
266 {
267  int i;
268  QgsDebugMsgLevel( QString( "field name = %1 type = %2 length = %3 precision = %4" )
269  .arg( field.name(),
270  QVariant::typeToName( field.type() ) )
271  .arg( field.length() )
272  .arg( field.precision() ), 2 );
273  for ( i = 0; i < mNativeTypes.size(); i++ )
274  {
275  QgsDebugMsgLevel( QString( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" )
276  .arg( QVariant::typeToName( mNativeTypes[i].mType ) )
277  .arg( mNativeTypes[i].mMinLen )
278  .arg( mNativeTypes[i].mMaxLen )
279  .arg( mNativeTypes[i].mMinPrec )
280  .arg( mNativeTypes[i].mMaxPrec ), 2 );
281 
282  if ( field.type() != mNativeTypes[i].mType )
283  continue;
284 
285  if ( field.length() == -1 )
286  {
287  // source length unlimited
288  if ( mNativeTypes[i].mMinLen > -1 || mNativeTypes[i].mMaxLen > -1 )
289  {
290  // destination limited
291  continue;
292  }
293  }
294  else
295  {
296  // source length limited
297  if ( mNativeTypes[i].mMinLen > -1 && mNativeTypes[i].mMaxLen > -1 &&
298  ( field.length() < mNativeTypes[i].mMinLen || field.length() > mNativeTypes[i].mMaxLen ) )
299  {
300  // source length exceeds destination limits
301  continue;
302  }
303  }
304 
305  if ( field.precision() == -1 )
306  {
307  // source precision unlimited / n/a
308  if ( mNativeTypes[i].mMinPrec > -1 || mNativeTypes[i].mMaxPrec > -1 )
309  {
310  // destination limited
311  continue;
312  }
313  }
314  else
315  {
316  // source precision unlimited / n/a
317  if ( mNativeTypes[i].mMinPrec > -1 && mNativeTypes[i].mMaxPrec > -1 &&
318  ( field.precision() < mNativeTypes[i].mMinPrec || field.precision() > mNativeTypes[i].mMaxPrec ) )
319  {
320  // source precision exceeds destination limits
321  continue;
322  }
323  }
324 
325  QgsDebugMsg( "native type matches" );
326  return true;
327  }
328 
329  QgsDebugMsg( "no sufficient native type found" );
330  return false;
331 }
332 
334 {
335  if ( index < 0 || index >= fields().count() )
336  {
337  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
338  return QVariant();
339  }
340 
341  fillMinMaxCache();
342 
343  if ( !mCacheMinValues.contains( index ) )
344  return QVariant();
345 
346  return mCacheMinValues[index];
347 }
348 
350 {
351  if ( index < 0 || index >= fields().count() )
352  {
353  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
354  return QVariant();
355  }
356 
357  fillMinMaxCache();
358 
359  if ( !mCacheMaxValues.contains( index ) )
360  return QVariant();
361 
362  return mCacheMaxValues[index];
363 }
364 
366 {
367  QgsFeature f;
368  QgsAttributeList keys;
369  keys.append( index );
370  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
371 
372  QSet<QString> set;
373  values.clear();
374 
375  while ( fi.nextFeature( f ) )
376  {
377  if ( !set.contains( f.attribute( index ).toString() ) )
378  {
379  values.append( f.attribute( index ) );
380  set.insert( f.attribute( index ).toString() );
381  }
382 
383  if ( limit >= 0 && values.size() >= limit )
384  break;
385  }
386 }
387 
389 {
390  mCacheMinMaxDirty = true;
391 }
392 
394 {
395  if ( !mCacheMinMaxDirty )
396  return;
397 
398  const QgsFields& flds = fields();
399  for ( int i = 0; i < flds.count(); ++i )
400  {
401  if ( flds[i].type() == QVariant::Int )
402  {
403  mCacheMinValues[i] = QVariant( INT_MAX );
404  mCacheMaxValues[i] = QVariant( INT_MIN );
405  }
406  else if ( flds[i].type() == QVariant::LongLong )
407  {
410  }
411  else if ( flds[i].type() == QVariant::Double )
412  {
413  mCacheMinValues[i] = QVariant( DBL_MAX );
414  mCacheMaxValues[i] = QVariant( -DBL_MAX );
415  }
416  else
417  {
418  mCacheMinValues[i] = QVariant();
419  mCacheMaxValues[i] = QVariant();
420  }
421  }
422 
423  QgsFeature f;
425  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
426 
427  while ( fi.nextFeature( f ) )
428  {
429  QgsAttributes attrs = f.attributes();
430  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
431  {
432  const QVariant& varValue = attrs.at( *it );
433 
434  if ( varValue.isNull() )
435  continue;
436 
437  if ( flds[*it].type() == QVariant::Int )
438  {
439  int value = varValue.toInt();
440  if ( value < mCacheMinValues[*it].toInt() )
441  mCacheMinValues[*it] = value;
442  if ( value > mCacheMaxValues[*it].toInt() )
443  mCacheMaxValues[*it] = value;
444  }
445  else if ( flds[*it].type() == QVariant::LongLong )
446  {
447  qlonglong value = varValue.toLongLong();
448  if ( value < mCacheMinValues[*it].toLongLong() )
449  mCacheMinValues[*it] = value;
450  if ( value > mCacheMaxValues[*it].toLongLong() )
451  mCacheMaxValues[*it] = value;
452  }
453  else if ( flds[*it].type() == QVariant::Double )
454  {
455  double value = varValue.toDouble();
456  if ( value < mCacheMinValues[*it].toDouble() )
457  mCacheMinValues[*it] = value;
458  if ( value > mCacheMaxValues[*it].toDouble() )
459  mCacheMaxValues[*it] = value;
460  }
461  else
462  {
463  QString value = varValue.toString();
464  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
465  {
466  mCacheMinValues[*it] = value;
467  }
468  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
469  {
470  mCacheMaxValues[*it] = value;
471  }
472  }
473  }
474  }
475 
476  mCacheMinMaxDirty = false;
477 }
478 
479 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, const QString& value )
480 {
481  QVariant v( value );
482 
483  if ( !v.convert( type ) || value.isNull() )
484  v = QVariant( type );
485 
486  return v;
487 }
488 
489 static bool _compareEncodings( const QString& s1, const QString& s2 )
490 {
491  return s1.toLower() < s2.toLower();
492 }
493 
495 {
496  if ( smEncodings.isEmpty() )
497  {
498  Q_FOREACH ( const QString& codec, QTextCodec::availableCodecs() )
499  {
500  smEncodings << codec;
501  }
502 #if 0
503  smEncodings << "BIG5";
504  smEncodings << "BIG5-HKSCS";
505  smEncodings << "EUCJP";
506  smEncodings << "EUCKR";
507  smEncodings << "GB2312";
508  smEncodings << "GBK";
509  smEncodings << "GB18030";
510  smEncodings << "JIS7";
511  smEncodings << "SHIFT-JIS";
512  smEncodings << "TSCII";
513  smEncodings << "UTF-8";
514  smEncodings << "UTF-16";
515  smEncodings << "KOI8-R";
516  smEncodings << "KOI8-U";
517  smEncodings << "ISO8859-1";
518  smEncodings << "ISO8859-2";
519  smEncodings << "ISO8859-3";
520  smEncodings << "ISO8859-4";
521  smEncodings << "ISO8859-5";
522  smEncodings << "ISO8859-6";
523  smEncodings << "ISO8859-7";
524  smEncodings << "ISO8859-8";
525  smEncodings << "ISO8859-8-I";
526  smEncodings << "ISO8859-9";
527  smEncodings << "ISO8859-10";
528  smEncodings << "ISO8859-11";
529  smEncodings << "ISO8859-12";
530  smEncodings << "ISO8859-13";
531  smEncodings << "ISO8859-14";
532  smEncodings << "ISO8859-15";
533  smEncodings << "IBM 850";
534  smEncodings << "IBM 866";
535  smEncodings << "CP874";
536  smEncodings << "CP1250";
537  smEncodings << "CP1251";
538  smEncodings << "CP1252";
539  smEncodings << "CP1253";
540  smEncodings << "CP1254";
541  smEncodings << "CP1255";
542  smEncodings << "CP1256";
543  smEncodings << "CP1257";
544  smEncodings << "CP1258";
545  smEncodings << "Apple Roman";
546  smEncodings << "TIS-620";
547  smEncodings << "System";
548 #endif
549  }
550 
551  // Do case-insensitive sorting of encodings
552  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
553 
554  return smEncodings;
555 }
556 
558 {
559  mErrors.clear();
560 }
561 
563 {
564  return !mErrors.isEmpty();
565 }
566 
568 {
569  return mErrors;
570 }
571 
573 {
574  QgsDebugMsg( msg );
575  mErrors << msg;
576  emit raiseError( msg );
577 }
578 
580 {
581  return QSet<QString>();
582 }
583 
584 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.
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
int compare(const QString &other) const
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:520
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