QGIS API Documentation  2.2.0-Valmiera
 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  int count = fields().count();
244  QgsAttributeList list;
245 
246  for ( int i = 0; i < count; i++ )
247  list.append( i );
248 
249  return list;
250 }
251 
252 const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
253 {
254  return mNativeTypes;
255 }
256 
258 {
259  int i;
260  QgsDebugMsgLevel( QString( "field name = %1 type = %2 length = %3 precision = %4" )
261  .arg( field.name() )
262  .arg( QVariant::typeToName( field.type() ) )
263  .arg( field.length() )
264  .arg( field.precision() ), 2 );
265  for ( i = 0; i < mNativeTypes.size(); i++ )
266  {
267  QgsDebugMsgLevel( QString( "native field type = %1 min length = %2 max length = %3 min precision = %4 max precision = %5" )
268  .arg( QVariant::typeToName( mNativeTypes[i].mType ) )
269  .arg( mNativeTypes[i].mMinLen )
270  .arg( mNativeTypes[i].mMaxLen )
271  .arg( mNativeTypes[i].mMinPrec )
272  .arg( mNativeTypes[i].mMaxPrec ), 2 );
273  if ( field.type() == mNativeTypes[i].mType &&
274  field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
275  field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
276  {
277  QgsDebugMsg( "native type matches" );
278  return true;
279  }
280  }
281 
282  QgsDebugMsg( "no sufficient native type found" );
283  return false;
284 }
285 
287 {
288  if ( index < 0 || index >= fields().count() )
289  {
290  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
291  return QVariant();
292  }
293 
294  fillMinMaxCache();
295 
296  if ( !mCacheMinValues.contains( index ) )
297  return QVariant();
298 
299  return mCacheMinValues[index];
300 }
301 
303 {
304  if ( index < 0 || index >= fields().count() )
305  {
306  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
307  return QVariant();
308  }
309 
310  fillMinMaxCache();
311 
312  if ( !mCacheMaxValues.contains( index ) )
313  return QVariant();
314 
315  return mCacheMaxValues[index];
316 }
317 
318 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
319 {
320  QgsFeature f;
321  QgsAttributeList keys;
322  keys.append( index );
323  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
324 
325  QSet<QString> set;
326  values.clear();
327 
328  while ( fi.nextFeature( f ) )
329  {
330  if ( !set.contains( f.attribute( index ).toString() ) )
331  {
332  values.append( f.attribute( index ) );
333  set.insert( f.attribute( index ).toString() );
334  }
335 
336  if ( limit >= 0 && values.size() >= limit )
337  break;
338  }
339 }
340 
342 {
343  mCacheMinMaxDirty = true;
344 }
345 
347 {
348  if ( !mCacheMinMaxDirty )
349  return;
350 
351  const QgsFields& flds = fields();
352  for ( int i = 0; i < flds.count(); ++i )
353  {
354  if ( flds[i].type() == QVariant::Int )
355  {
356  mCacheMinValues[i] = QVariant( INT_MAX );
357  mCacheMaxValues[i] = QVariant( INT_MIN );
358  }
359  else if ( flds[i].type() == QVariant::Double )
360  {
361  mCacheMinValues[i] = QVariant( DBL_MAX );
362  mCacheMaxValues[i] = QVariant( -DBL_MAX );
363  }
364  else
365  {
366  mCacheMinValues[i] = QVariant();
367  mCacheMaxValues[i] = QVariant();
368  }
369  }
370 
371  QgsFeature f;
372  QgsAttributeList keys = mCacheMinValues.keys();
373  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
374 
375  while ( fi.nextFeature( f ) )
376  {
377  const QgsAttributes& attrs = f.attributes();
378  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
379  {
380  const QVariant& varValue = attrs[*it];
381 
382  if ( flds[*it].type() == QVariant::Int )
383  {
384  int value = varValue.toInt();
385  if ( value < mCacheMinValues[*it].toInt() )
386  mCacheMinValues[*it] = value;
387  if ( value > mCacheMaxValues[*it].toInt() )
388  mCacheMaxValues[*it] = value;
389  }
390  else if ( flds[*it].type() == QVariant::Double )
391  {
392  double value = varValue.toDouble();
393  if ( value < mCacheMinValues[*it].toDouble() )
394  mCacheMinValues[*it] = value;
395  if ( value > mCacheMaxValues[*it].toDouble() )
396  mCacheMaxValues[*it] = value;
397  }
398  else
399  {
400  QString value = varValue.toString();
401  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
402  {
403  mCacheMinValues[*it] = value;
404  }
405  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
406  {
407  mCacheMaxValues[*it] = value;
408  }
409  }
410  }
411  }
412 
413  mCacheMinMaxDirty = false;
414 }
415 
416 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
417 {
418  QVariant v( value );
419 
420  if ( !v.convert( type ) || value.isNull() )
421  v = QVariant( type );
422 
423  return v;
424 }
425 
426 static bool _compareEncodings( const QString& s1, const QString& s2 )
427 {
428  return s1.toLower() < s2.toLower();
429 }
430 
432 {
433  if ( smEncodings.isEmpty() )
434  {
435  foreach ( QString codec, QTextCodec::availableCodecs() )
436  {
437  smEncodings << codec;
438  }
439 #if 0
440  smEncodings << "BIG5";
441  smEncodings << "BIG5-HKSCS";
442  smEncodings << "EUCJP";
443  smEncodings << "EUCKR";
444  smEncodings << "GB2312";
445  smEncodings << "GBK";
446  smEncodings << "GB18030";
447  smEncodings << "JIS7";
448  smEncodings << "SHIFT-JIS";
449  smEncodings << "TSCII";
450  smEncodings << "UTF-8";
451  smEncodings << "UTF-16";
452  smEncodings << "KOI8-R";
453  smEncodings << "KOI8-U";
454  smEncodings << "ISO8859-1";
455  smEncodings << "ISO8859-2";
456  smEncodings << "ISO8859-3";
457  smEncodings << "ISO8859-4";
458  smEncodings << "ISO8859-5";
459  smEncodings << "ISO8859-6";
460  smEncodings << "ISO8859-7";
461  smEncodings << "ISO8859-8";
462  smEncodings << "ISO8859-8-I";
463  smEncodings << "ISO8859-9";
464  smEncodings << "ISO8859-10";
465  smEncodings << "ISO8859-11";
466  smEncodings << "ISO8859-12";
467  smEncodings << "ISO8859-13";
468  smEncodings << "ISO8859-14";
469  smEncodings << "ISO8859-15";
470  smEncodings << "IBM 850";
471  smEncodings << "IBM 866";
472  smEncodings << "CP874";
473  smEncodings << "CP1250";
474  smEncodings << "CP1251";
475  smEncodings << "CP1252";
476  smEncodings << "CP1253";
477  smEncodings << "CP1254";
478  smEncodings << "CP1255";
479  smEncodings << "CP1256";
480  smEncodings << "CP1257";
481  smEncodings << "CP1258";
482  smEncodings << "Apple Roman";
483  smEncodings << "TIS-620";
484  smEncodings << "System";
485 #endif
486  }
487 
488  // Do case-insensitive sorting of encodings
489  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
490 
491  return smEncodings;
492 }
493 
495 {
496  mErrors.clear();
497 }
498 
500 {
501  return !mErrors.isEmpty();
502 }
503 
505 {
506  return mErrors;
507 }
508 
510 {
511  mErrors << msg;
512 }
513