QGIS API Documentation  2.11.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 
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 {
98  return false;
99 }
100 
102 {
103  Q_UNUSED( field );
104  return true;
105 }
106 
108 {
110 }
111 
112 
114 {
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 )
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 
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 
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 
268  if ( field.type() != mNativeTypes[i].mType )
269  continue;
270 
271  if ( field.length() == -1 )
272  {
273  // source length unlimited
274  if ( mNativeTypes[i].mMinLen > -1 || mNativeTypes[i].mMaxLen > -1 )
275  {
276  // destination limited
277  continue;
278  }
279  }
280  else
281  {
282  // source length limited
283  if ( mNativeTypes[i].mMinLen > -1 && mNativeTypes[i].mMaxLen > -1 &&
284  ( field.length() < mNativeTypes[i].mMinLen || field.length() > mNativeTypes[i].mMaxLen ) )
285  {
286  // source length exceeds destination limits
287  continue;
288  }
289  }
290 
291  if ( field.precision() == -1 )
292  {
293  // source precision unlimited / n/a
294  if ( mNativeTypes[i].mMinPrec > -1 || mNativeTypes[i].mMaxPrec > -1 )
295  {
296  // destination limited
297  continue;
298  }
299  }
300  else
301  {
302  // source precision unlimited / n/a
303  if ( mNativeTypes[i].mMinPrec > -1 && mNativeTypes[i].mMaxPrec > -1 &&
304  ( field.precision() < mNativeTypes[i].mMinPrec || field.precision() > mNativeTypes[i].mMaxPrec ) )
305  {
306  // source precision exceeds destination limits
307  continue;
308  }
309  }
310 
311  QgsDebugMsg( "native type matches" );
312  return true;
313  }
314 
315  QgsDebugMsg( "no sufficient native type found" );
316  return false;
317 }
318 
320 {
321  if ( index < 0 || index >= fields().count() )
322  {
323  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
324  return QVariant();
325  }
326 
327  fillMinMaxCache();
328 
329  if ( !mCacheMinValues.contains( index ) )
330  return QVariant();
331 
332  return mCacheMinValues[index];
333 }
334 
336 {
337  if ( index < 0 || index >= fields().count() )
338  {
339  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
340  return QVariant();
341  }
342 
343  fillMinMaxCache();
344 
345  if ( !mCacheMaxValues.contains( index ) )
346  return QVariant();
347 
348  return mCacheMaxValues[index];
349 }
350 
352 {
353  QgsFeature f;
354  QgsAttributeList keys;
355  keys.append( index );
356  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
357 
358  QSet<QString> set;
359  values.clear();
360 
361  while ( fi.nextFeature( f ) )
362  {
363  if ( !set.contains( f.attribute( index ).toString() ) )
364  {
365  values.append( f.attribute( index ) );
366  set.insert( f.attribute( index ).toString() );
367  }
368 
369  if ( limit >= 0 && values.size() >= limit )
370  break;
371  }
372 }
373 
375 {
376  mCacheMinMaxDirty = true;
377 }
378 
380 {
381  if ( !mCacheMinMaxDirty )
382  return;
383 
384  const QgsFields& flds = fields();
385  for ( int i = 0; i < flds.count(); ++i )
386  {
387  if ( flds[i].type() == QVariant::Int )
388  {
389  mCacheMinValues[i] = QVariant( INT_MAX );
390  mCacheMaxValues[i] = QVariant( INT_MIN );
391  }
392  else if ( flds[i].type() == QVariant::Double )
393  {
394  mCacheMinValues[i] = QVariant( DBL_MAX );
395  mCacheMaxValues[i] = QVariant( -DBL_MAX );
396  }
397  else
398  {
399  mCacheMinValues[i] = QVariant();
400  mCacheMaxValues[i] = QVariant();
401  }
402  }
403 
404  QgsFeature f;
406  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
407 
408  while ( fi.nextFeature( f ) )
409  {
410  QgsAttributes attrs = f.attributes();
411  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
412  {
413  const QVariant& varValue = attrs[*it];
414 
415  if ( varValue.isNull() )
416  continue;
417 
418  if ( flds[*it].type() == QVariant::Int )
419  {
420  int value = varValue.toInt();
421  if ( value < mCacheMinValues[*it].toInt() )
422  mCacheMinValues[*it] = value;
423  if ( value > mCacheMaxValues[*it].toInt() )
424  mCacheMaxValues[*it] = value;
425  }
426  else if ( flds[*it].type() == QVariant::Double )
427  {
428  double value = varValue.toDouble();
429  if ( value < mCacheMinValues[*it].toDouble() )
430  mCacheMinValues[*it] = value;
431  if ( value > mCacheMaxValues[*it].toDouble() )
432  mCacheMaxValues[*it] = value;
433  }
434  else
435  {
436  QString value = varValue.toString();
437  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
438  {
439  mCacheMinValues[*it] = value;
440  }
441  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
442  {
443  mCacheMaxValues[*it] = value;
444  }
445  }
446  }
447  }
448 
449  mCacheMinMaxDirty = false;
450 }
451 
453 {
454  QVariant v( value );
455 
456  if ( !v.convert( type ) || value.isNull() )
457  v = QVariant( type );
458 
459  return v;
460 }
461 
462 static bool _compareEncodings( const QString& s1, const QString& s2 )
463 {
464  return s1.toLower() < s2.toLower();
465 }
466 
468 {
469  if ( smEncodings.isEmpty() )
470  {
471  foreach ( QString codec, QTextCodec::availableCodecs() )
472  {
473  smEncodings << codec;
474  }
475 #if 0
476  smEncodings << "BIG5";
477  smEncodings << "BIG5-HKSCS";
478  smEncodings << "EUCJP";
479  smEncodings << "EUCKR";
480  smEncodings << "GB2312";
481  smEncodings << "GBK";
482  smEncodings << "GB18030";
483  smEncodings << "JIS7";
484  smEncodings << "SHIFT-JIS";
485  smEncodings << "TSCII";
486  smEncodings << "UTF-8";
487  smEncodings << "UTF-16";
488  smEncodings << "KOI8-R";
489  smEncodings << "KOI8-U";
490  smEncodings << "ISO8859-1";
491  smEncodings << "ISO8859-2";
492  smEncodings << "ISO8859-3";
493  smEncodings << "ISO8859-4";
494  smEncodings << "ISO8859-5";
495  smEncodings << "ISO8859-6";
496  smEncodings << "ISO8859-7";
497  smEncodings << "ISO8859-8";
498  smEncodings << "ISO8859-8-I";
499  smEncodings << "ISO8859-9";
500  smEncodings << "ISO8859-10";
501  smEncodings << "ISO8859-11";
502  smEncodings << "ISO8859-12";
503  smEncodings << "ISO8859-13";
504  smEncodings << "ISO8859-14";
505  smEncodings << "ISO8859-15";
506  smEncodings << "IBM 850";
507  smEncodings << "IBM 866";
508  smEncodings << "CP874";
509  smEncodings << "CP1250";
510  smEncodings << "CP1251";
511  smEncodings << "CP1252";
512  smEncodings << "CP1253";
513  smEncodings << "CP1254";
514  smEncodings << "CP1255";
515  smEncodings << "CP1256";
516  smEncodings << "CP1257";
517  smEncodings << "CP1258";
518  smEncodings << "Apple Roman";
519  smEncodings << "TIS-620";
520  smEncodings << "System";
521 #endif
522  }
523 
524  // Do case-insensitive sorting of encodings
525  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
526 
527  return smEncodings;
528 }
529 
531 {
532  mErrors.clear();
533 }
534 
536 {
537  return !mErrors.isEmpty();
538 }
539 
541 {
542  return mErrors;
543 }
544 
546 {
547  mErrors << msg;
548 }
549 
550 QStringList QgsVectorDataProvider::smEncodings;
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:69
void clear()
Wrapper for iterator of features from vector data provider or vector layer.
static unsigned index
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:89
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:173
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)
QString join(const QString &separator) const
const_iterator insert(const T &value)
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:162
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
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
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's attributes.
Definition: qgsfeature.cpp:90
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.
bool isEmpty() const
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.
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:283
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:38
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.
iterator end()
QString toLower() const
QByteArray toLocal8Bit() const
virtual bool changeGeometryValues(QgsGeometryMap &geometry_map)
Changes geometries of existing features.
bool contains(const T &value) const
supports topological simplification of geometries on provider side according to a distance tolerance ...
const char * typeToName(Type typ)
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:236
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:84
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)
bool nextFeature(QgsFeature &f)
A vector of attributes.
Definition: qgsfeature.h:109
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:366
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:74