QGIS API Documentation  2.8.2-Wien
 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 : [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 
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 ( 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 
452 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
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;