QGIS API Documentation  2.5.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 
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 
351 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
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;
405  QgsAttributeList keys = mCacheMinValues.keys();
406  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
407 
408  while ( fi.nextFeature( f ) )
409  {
410  const 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 ( flds[*it].type() == QVariant::Int )
416  {
417  int value = varValue.toInt();
418  if ( value < mCacheMinValues[*it].toInt() )
419  mCacheMinValues[*it] = value;
420  if ( value > mCacheMaxValues[*it].toInt() )
421  mCacheMaxValues[*it] = value;
422  }
423  else if ( flds[*it].type() == QVariant::Double )
424  {
425  double value = varValue.toDouble();
426  if ( value < mCacheMinValues[*it].toDouble() )
427  mCacheMinValues[*it] = value;
428  if ( value > mCacheMaxValues[*it].toDouble() )
429  mCacheMaxValues[*it] = value;
430  }
431  else
432  {
433  QString value = varValue.toString();
434  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
435  {
436  mCacheMinValues[*it] = value;
437  }
438  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
439  {
440  mCacheMaxValues[*it] = value;
441  }
442  }
443  }
444  }
445 
446  mCacheMinMaxDirty = false;
447 }
448 
449 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
450 {
451  QVariant v( value );
452 
453  if ( !v.convert( type ) || value.isNull() )
454  v = QVariant( type );
455 
456  return v;
457 }
458 
459 static bool _compareEncodings( const QString& s1, const QString& s2 )
460 {
461  return s1.toLower() < s2.toLower();
462 }
463 
465 {
466  if ( smEncodings.isEmpty() )
467  {
468  foreach ( QString codec, QTextCodec::availableCodecs() )
469  {
470  smEncodings << codec;
471  }
472 #if 0
473  smEncodings << "BIG5";
474  smEncodings << "BIG5-HKSCS";
475  smEncodings << "EUCJP";
476  smEncodings << "EUCKR";
477  smEncodings << "GB2312";
478  smEncodings << "GBK";
479  smEncodings << "GB18030";
480  smEncodings << "JIS7";
481  smEncodings << "SHIFT-JIS";
482  smEncodings << "TSCII";
483  smEncodings << "UTF-8";
484  smEncodings << "UTF-16";
485  smEncodings << "KOI8-R";
486  smEncodings << "KOI8-U";
487  smEncodings << "ISO8859-1";
488  smEncodings << "ISO8859-2";
489  smEncodings << "ISO8859-3";
490  smEncodings << "ISO8859-4";
491  smEncodings << "ISO8859-5";
492  smEncodings << "ISO8859-6";
493  smEncodings << "ISO8859-7";
494  smEncodings << "ISO8859-8";
495  smEncodings << "ISO8859-8-I";
496  smEncodings << "ISO8859-9";
497  smEncodings << "ISO8859-10";
498  smEncodings << "ISO8859-11";
499  smEncodings << "ISO8859-12";
500  smEncodings << "ISO8859-13";
501  smEncodings << "ISO8859-14";
502  smEncodings << "ISO8859-15";
503  smEncodings << "IBM 850";
504  smEncodings << "IBM 866";
505  smEncodings << "CP874";
506  smEncodings << "CP1250";
507  smEncodings << "CP1251";
508  smEncodings << "CP1252";
509  smEncodings << "CP1253";
510  smEncodings << "CP1254";
511  smEncodings << "CP1255";
512  smEncodings << "CP1256";
513  smEncodings << "CP1257";
514  smEncodings << "CP1258";
515  smEncodings << "Apple Roman";
516  smEncodings << "TIS-620";
517  smEncodings << "System";
518 #endif
519  }
520 
521  // Do case-insensitive sorting of encodings
522  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
523 
524  return smEncodings;
525 }
526 
528 {
529  mErrors.clear();
530 }
531 
533 {
534  return !mErrors.isEmpty();
535 }
536 
538 {
539  return mErrors;
540 }
541 
543 {
544  mErrors << msg;
545 }
546 
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:58
Wrapper for iterator of features from vector data provider or vector layer.
QMap< QgsFeatureId, QgsGeometry > QgsGeometryMap
Definition: qgsfeature.h:323
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:325
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:330
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:78
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:161
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:113
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:142
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:195
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:320
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:73
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:187
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:63
#define tr(sourceText)