QGIS API Documentation  2.14.0-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 : [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 
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 
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 
85 {
86  Q_UNUSED( fieldId );
87  return QVariant();
88 }
89 
91 {
92  Q_UNUSED( geometry_map );
93  return false;
94 }
95 
97  const QgsGeometryMap &geometry_map )
98 {
99  Q_UNUSED( attr_map );
100  Q_UNUSED( geometry_map );
101  return false;
102 }
103 
105 {
106  return false;
107 }
108 
110 {
111  Q_UNUSED( field );
112  return true;
113 }
114 
116 {
118 }
119 
120 
122 {
124  if ( ncodec )
125  {
126  mEncoding = ncodec;
127  }
128  else
129  {
130  QgsMessageLog::logMessage( tr( "Codec %1 not found. Falling back to system locale" ).arg( e ) );
131  mEncoding = QTextCodec::codecForName( "System" );
132 
133  if ( !mEncoding )
135 
136  Q_ASSERT( mEncoding );
137  }
138 }
139 
141 {
142  if ( mEncoding )
143  {
144  return mEncoding->name();
145  }
146 
147  return "";
148 }
149 
151 {
152  QStringList abilitiesList;
153 
154  int abilities = capabilities();
155 
156  if ( abilities & QgsVectorDataProvider::AddFeatures )
157  {
158  abilitiesList += tr( "Add Features" );
159  QgsDebugMsg( "Capability: Add Features" );
160  }
161 
162  if ( abilities & QgsVectorDataProvider::DeleteFeatures )
163  {
164  abilitiesList += tr( "Delete Features" );
165  QgsDebugMsg( "Capability: Delete Features" );
166  }
167 
169  {
170  abilitiesList += tr( "Change Attribute Values" );
171  QgsDebugMsg( "Capability: Change Attribute Values" );
172  }
173 
174  if ( abilities & QgsVectorDataProvider::AddAttributes )
175  {
176  abilitiesList += tr( "Add Attributes" );
177  QgsDebugMsg( "Capability: Add Attributes" );
178  }
179 
180  if ( abilities & QgsVectorDataProvider::DeleteAttributes )
181  {
182  abilitiesList += tr( "Delete Attributes" );
183  QgsDebugMsg( "Capability: Delete Attributes" );
184  }
185 
187  {
188  // TODO: Tighten up this test. See QgsOgrProvider for details.
189  abilitiesList += tr( "Create Spatial Index" );
190  QgsDebugMsg( "Capability: Create Spatial Index" );
191  }
192 
193  if ( abilities & QgsVectorDataProvider::SelectAtId )
194  {
195  abilitiesList += tr( "Fast Access to Features at ID" );
196  QgsDebugMsg( "Capability: Select at ID" );
197  }
198 
199  if ( abilities & QgsVectorDataProvider::ChangeGeometries )
200  {
201  abilitiesList += tr( "Change Geometries" );
202  QgsDebugMsg( "Capability: Change Geometries" );
203  }
204 
206  {
207  abilitiesList += tr( "Presimplify Geometries" );
208  QgsDebugMsg( "Capability: Simplify Geometries before fetching the feature" );
209  }
210 
212  {
213  abilitiesList += tr( "Presimplify Geometries with Validity Check" );
214  QgsDebugMsg( "Capability: Simplify Geometries before fetch the feature ensuring that the result is a valid geometry" );
215  }
216 
217  if ( abilities & QgsVectorDataProvider::ChangeFeatures )
218  {
219  abilitiesList += tr( "Simultaneous Geometry and Attribute Updates" );
220  QgsDebugMsg( "Capability: change both feature attributes and geometry at once" );
221  }
222 
223  return abilitiesList.join( ", " );
224 }
225 
226 
227 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
228 {
229  const QgsFields &theFields = fields();
230 
231  for ( int i = 0; i < theFields.count(); ++i )
232  {
233  if ( QString::compare( theFields[i].name(), fieldName, Qt::CaseInsensitive ) == 0 )
234  {
235  return i;
236  }
237  }
238  return -1;
239 }
240 
242 {
243  QMap<QString, int> resultMap;
244 
245  const QgsFields& theFields = fields();
246  for ( int i = 0; i < theFields.count(); ++i )
247  {
248  resultMap.insert( theFields[i].name(), i );
249  }
250 
251  return resultMap;
252 }
253 
255 {
256  return fields().allAttributesList();
257 }
258 
260 {
261  return mNativeTypes;
262 }
263 
265 {
266  int i;
267  QgsDebugMsgLevel( QString( "field name = %1 type = %2 length = %3 precision = %4" )
268  .arg( field.name(),
269  QVariant::typeToName( field.type() ) )
270  .arg( field.length() )
271  .arg( field.precision() ), 2 );
272  for ( i = 0; i < mNativeTypes.size(); i++ )
273  {
274  QgsDebugMsgLevel( QString( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" )
275  .arg( QVariant::typeToName( mNativeTypes[i].mType ) )
276  .arg( mNativeTypes[i].mMinLen )
277  .arg( mNativeTypes[i].mMaxLen )
278  .arg( mNativeTypes[i].mMinPrec )
279  .arg( mNativeTypes[i].mMaxPrec ), 2 );
280 
281  if ( field.type() != mNativeTypes[i].mType )
282  continue;
283 
284  if ( field.length() == -1 )
285  {
286  // source length unlimited
287  if ( mNativeTypes[i].mMinLen > -1 || mNativeTypes[i].mMaxLen > -1 )
288  {
289  // destination limited
290  continue;
291  }
292  }
293  else
294  {
295  // source length limited
296  if ( mNativeTypes[i].mMinLen > -1 && mNativeTypes[i].mMaxLen > -1 &&
297  ( field.length() < mNativeTypes[i].mMinLen || field.length() > mNativeTypes[i].mMaxLen ) )
298  {
299  // source length exceeds destination limits
300  continue;
301  }
302  }
303 
304  if ( field.precision() == -1 )
305  {
306  // source precision unlimited / n/a
307  if ( mNativeTypes[i].mMinPrec > -1 || mNativeTypes[i].mMaxPrec > -1 )
308  {
309  // destination limited
310  continue;
311  }
312  }
313  else
314  {
315  // source precision unlimited / n/a
316  if ( mNativeTypes[i].mMinPrec > -1 && mNativeTypes[i].mMaxPrec > -1 &&
317  ( field.precision() < mNativeTypes[i].mMinPrec || field.precision() > mNativeTypes[i].mMaxPrec ) )
318  {
319  // source precision exceeds destination limits
320  continue;
321  }
322  }
323 
324  QgsDebugMsg( "native type matches" );
325  return true;
326  }
327 
328  QgsDebugMsg( "no sufficient native type found" );
329  return false;
330 }
331 
333 {
334  if ( index < 0 || index >= fields().count() )
335  {
336  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
337  return QVariant();
338  }
339 
340  fillMinMaxCache();
341 
342  if ( !mCacheMinValues.contains( index ) )
343  return QVariant();
344 
345  return mCacheMinValues[index];
346 }
347 
349 {
350  if ( index < 0 || index >= fields().count() )
351  {
352  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
353  return QVariant();
354  }
355 
356  fillMinMaxCache();
357 
358  if ( !mCacheMaxValues.contains( index ) )
359  return QVariant();
360 
361  return mCacheMaxValues[index];
362 }
363 
365 {
366  QgsFeature f;
367  QgsAttributeList keys;
368  keys.append( index );
369  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
370 
371  QSet<QString> set;
372  values.clear();
373 
374  while ( fi.nextFeature( f ) )
375  {
376  if ( !set.contains( f.attribute( index ).toString() ) )
377  {
378  values.append( f.attribute( index ) );
379  set.insert( f.attribute( index ).toString() );
380  }
381 
382  if ( limit >= 0 && values.size() >= limit )
383  break;
384  }
385 }
386 
388 {
389  mCacheMinMaxDirty = true;
390 }
391 
393 {
394  if ( !mCacheMinMaxDirty )
395  return;
396 
397  const QgsFields& flds = fields();
398  for ( int i = 0; i < flds.count(); ++i )
399  {
400  if ( flds[i].type() == QVariant::Int )
401  {
402  mCacheMinValues[i] = QVariant( INT_MAX );
403  mCacheMaxValues[i] = QVariant( INT_MIN );
404  }
405  else if ( flds[i].type() == QVariant::Double )
406  {
407  mCacheMinValues[i] = QVariant( DBL_MAX );
408  mCacheMaxValues[i] = QVariant( -DBL_MAX );
409  }
410  else
411  {
412  mCacheMinValues[i] = QVariant();
413  mCacheMaxValues[i] = QVariant();
414  }
415  }
416 
417  QgsFeature f;
419  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
420 
421  while ( fi.nextFeature( f ) )
422  {
423  QgsAttributes attrs = f.attributes();
424  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
425  {
426  const QVariant& varValue = attrs.at( *it );
427 
428  if ( varValue.isNull() )
429  continue;
430 
431  if ( flds[*it].type() == QVariant::Int )
432  {
433  int value = varValue.toInt();
434  if ( value < mCacheMinValues[*it].toInt() )
435  mCacheMinValues[*it] = value;
436  if ( value > mCacheMaxValues[*it].toInt() )
437  mCacheMaxValues[*it] = value;
438  }
439  else if ( flds[*it].type() == QVariant::Double )
440  {
441  double value = varValue.toDouble();
442  if ( value < mCacheMinValues[*it].toDouble() )
443  mCacheMinValues[*it] = value;
444  if ( value > mCacheMaxValues[*it].toDouble() )
445  mCacheMaxValues[*it] = value;
446  }
447  else
448  {
449  QString value = varValue.toString();
450  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
451  {
452  mCacheMinValues[*it] = value;
453  }
454  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
455  {
456  mCacheMaxValues[*it] = value;
457  }
458  }
459  }
460  }
461 
462  mCacheMinMaxDirty = false;
463 }
464 
465 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, const QString& value )
466 {
467  QVariant v( value );
468 
469  if ( !v.convert( type ) || value.isNull() )
470  v = QVariant( type );
471 
472  return v;
473 }
474 
475 static bool _compareEncodings( const QString& s1, const QString& s2 )
476 {
477  return s1.toLower() < s2.toLower();
478 }
479 
481 {
482  if ( smEncodings.isEmpty() )
483  {
484  Q_FOREACH ( const QString& codec, QTextCodec::availableCodecs() )
485  {
486  smEncodings << codec;
487  }
488 #if 0
489  smEncodings << "BIG5";
490  smEncodings << "BIG5-HKSCS";
491  smEncodings << "EUCJP";
492  smEncodings << "EUCKR";
493  smEncodings << "GB2312";
494  smEncodings << "GBK";
495  smEncodings << "GB18030";
496  smEncodings << "JIS7";
497  smEncodings << "SHIFT-JIS";
498  smEncodings << "TSCII";
499  smEncodings << "UTF-8";
500  smEncodings << "UTF-16";
501  smEncodings << "KOI8-R";
502  smEncodings << "KOI8-U";
503  smEncodings << "ISO8859-1";
504  smEncodings << "ISO8859-2";
505  smEncodings << "ISO8859-3";
506  smEncodings << "ISO8859-4";
507  smEncodings << "ISO8859-5";
508  smEncodings << "ISO8859-6";
509  smEncodings << "ISO8859-7";
510  smEncodings << "ISO8859-8";
511  smEncodings << "ISO8859-8-I";
512  smEncodings << "ISO8859-9";
513  smEncodings << "ISO8859-10";
514  smEncodings << "ISO8859-11";
515  smEncodings << "ISO8859-12";
516  smEncodings << "ISO8859-13";
517  smEncodings << "ISO8859-14";
518  smEncodings << "ISO8859-15";
519  smEncodings << "IBM 850";
520  smEncodings << "IBM 866";
521  smEncodings << "CP874";
522  smEncodings << "CP1250";
523  smEncodings << "CP1251";
524  smEncodings << "CP1252";
525  smEncodings << "CP1253";
526  smEncodings << "CP1254";
527  smEncodings << "CP1255";
528  smEncodings << "CP1256";
529  smEncodings << "CP1257";
530  smEncodings << "CP1258";
531  smEncodings << "Apple Roman";
532  smEncodings << "TIS-620";
533  smEncodings << "System";
534 #endif
535  }
536 
537  // Do case-insensitive sorting of encodings
538  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
539 
540  return smEncodings;
541 }
542 
544 {
545  mErrors.clear();
546 }
547 
549 {
550  return !mErrors.isEmpty();
551 }
552 
554 {
555  return mErrors;
556 }
557 
559 {
560  QgsDebugMsg( msg );
561  mErrors << msg;
562  emit raiseError( msg );
563 }
564 
566 {
567  return QSet<QString>();
568 }
569 
570 QStringList QgsVectorDataProvider::smEncodings;
virtual QSet< QString > layerDependencies() const
Get the list of layer ids on which this layer depends.
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.
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)
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