QGIS API Documentation  2.0.1-Dufour
 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 
197  return abilitiesList.join( ", " );
198 
199 }
200 
201 
202 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
203 {
204  const QgsFields &theFields = fields();
205 
206  for ( int i = 0; i < theFields.count(); ++i )
207  {
208  if ( QString::compare( theFields[i].name(), fieldName, Qt::CaseInsensitive ) == 0 )
209  {
210  return i;
211  }
212  }
213  return -1;
214 }
215 
216 QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
217 {
218  QMap<QString, int> resultMap;
219 
220  const QgsFields& theFields = fields();
221  for ( int i = 0; i < theFields.count(); ++i )
222  {
223  resultMap.insert( theFields[i].name(), i );
224  }
225 
226  return resultMap;
227 }
228 
230 {
231  int count = fields().count();
232  QgsAttributeList list;
233 
234  for ( int i = 0; i < count; i++ )
235  list.append( i );
236 
237  return list;
238 }
239 
240 const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
241 {
242  return mNativeTypes;
243 }
244 
246 {
247  int i;
248  for ( i = 0; i < mNativeTypes.size(); i++ )
249  {
250  if ( field.type() == mNativeTypes[i].mType &&
251  field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
252  field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
253  {
254  return true;
255  }
256  }
257 
258  return false;
259 }
260 
262 {
263  if ( index < 0 || index >= fields().count() )
264  {
265  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
266  return QVariant();
267  }
268 
269  fillMinMaxCache();
270 
271  if ( !mCacheMinValues.contains( index ) )
272  return QVariant();
273 
274  return mCacheMinValues[index];
275 }
276 
278 {
279  if ( index < 0 || index >= fields().count() )
280  {
281  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
282  return QVariant();
283  }
284 
285  fillMinMaxCache();
286 
287  if ( !mCacheMaxValues.contains( index ) )
288  return QVariant();
289 
290  return mCacheMaxValues[index];
291 }
292 
293 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
294 {
295  QgsFeature f;
296  QgsAttributeList keys;
297  keys.append( index );
298  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
299 
300  QSet<QString> set;
301  values.clear();
302 
303  while ( fi.nextFeature( f ) )
304  {
305  if ( !set.contains( f.attribute( index ).toString() ) )
306  {
307  values.append( f.attribute( index ) );
308  set.insert( f.attribute( index ).toString() );
309  }
310 
311  if ( limit >= 0 && values.size() >= limit )
312  break;
313  }
314 }
315 
317 {
318  mCacheMinMaxDirty = true;
319 }
320 
322 {
323  if ( !mCacheMinMaxDirty )
324  return;
325 
326  const QgsFields& flds = fields();
327  for ( int i = 0; i < flds.count(); ++i )
328  {
329  if ( flds[i].type() == QVariant::Int )
330  {
331  mCacheMinValues[i] = QVariant( INT_MAX );
332  mCacheMaxValues[i] = QVariant( INT_MIN );
333  }
334  else if ( flds[i].type() == QVariant::Double )
335  {
336  mCacheMinValues[i] = QVariant( DBL_MAX );
337  mCacheMaxValues[i] = QVariant( -DBL_MAX );
338  }
339  else
340  {
341  mCacheMinValues[i] = QVariant();
342  mCacheMaxValues[i] = QVariant();
343  }
344  }
345 
346  QgsFeature f;
347  QgsAttributeList keys = mCacheMinValues.keys();
348  QgsFeatureIterator fi = getFeatures( QgsFeatureRequest().setSubsetOfAttributes( keys ) );
349 
350  while ( fi.nextFeature( f ) )
351  {
352  const QgsAttributes& attrs = f.attributes();
353  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
354  {
355  const QVariant& varValue = attrs[*it];
356 
357  if ( flds[*it].type() == QVariant::Int )
358  {
359  int value = varValue.toInt();
360  if ( value < mCacheMinValues[*it].toInt() )
361  mCacheMinValues[*it] = value;
362  if ( value > mCacheMaxValues[*it].toInt() )
363  mCacheMaxValues[*it] = value;
364  }
365  else if ( flds[*it].type() == QVariant::Double )
366  {
367  double value = varValue.toDouble();
368  if ( value < mCacheMinValues[*it].toDouble() )
369  mCacheMinValues[*it] = value;
370  if ( value > mCacheMaxValues[*it].toDouble() )
371  mCacheMaxValues[*it] = value;
372  }
373  else
374  {
375  QString value = varValue.toString();
376  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
377  {
378  mCacheMinValues[*it] = value;
379  }
380  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
381  {
382  mCacheMaxValues[*it] = value;
383  }
384  }
385  }
386  }
387 
388  mCacheMinMaxDirty = false;
389 }
390 
391 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
392 {
393  QVariant v( value );
394 
395  if ( !v.convert( type ) )
396  v = QVariant( QString::null );
397 
398  return v;
399 }
400 
401 static bool _compareEncodings( const QString& s1, const QString& s2 )
402 {
403  return s1.toLower() < s2.toLower();
404 }
405 
407 {
408  if ( smEncodings.isEmpty() )
409  {
410  foreach ( QString codec, QTextCodec::availableCodecs() )
411  {
412  smEncodings << codec;
413  }
414 #if 0
415  smEncodings << "BIG5";
416  smEncodings << "BIG5-HKSCS";
417  smEncodings << "EUCJP";
418  smEncodings << "EUCKR";
419  smEncodings << "GB2312";
420  smEncodings << "GBK";
421  smEncodings << "GB18030";
422  smEncodings << "JIS7";
423  smEncodings << "SHIFT-JIS";
424  smEncodings << "TSCII";
425  smEncodings << "UTF-8";
426  smEncodings << "UTF-16";
427  smEncodings << "KOI8-R";
428  smEncodings << "KOI8-U";
429  smEncodings << "ISO8859-1";
430  smEncodings << "ISO8859-2";
431  smEncodings << "ISO8859-3";
432  smEncodings << "ISO8859-4";
433  smEncodings << "ISO8859-5";
434  smEncodings << "ISO8859-6";
435  smEncodings << "ISO8859-7";
436  smEncodings << "ISO8859-8";
437  smEncodings << "ISO8859-8-I";
438  smEncodings << "ISO8859-9";
439  smEncodings << "ISO8859-10";
440  smEncodings << "ISO8859-11";
441  smEncodings << "ISO8859-12";
442  smEncodings << "ISO8859-13";
443  smEncodings << "ISO8859-14";
444  smEncodings << "ISO8859-15";
445  smEncodings << "IBM 850";
446  smEncodings << "IBM 866";
447  smEncodings << "CP874";
448  smEncodings << "CP1250";
449  smEncodings << "CP1251";
450  smEncodings << "CP1252";
451  smEncodings << "CP1253";
452  smEncodings << "CP1254";
453  smEncodings << "CP1255";
454  smEncodings << "CP1256";
455  smEncodings << "CP1257";
456  smEncodings << "CP1258";
457  smEncodings << "Apple Roman";
458  smEncodings << "TIS-620";
459  smEncodings << "System";
460 #endif
461  }
462 
463  // Do case-insensitive sorting of encodings
464  qSort( smEncodings.begin(), smEncodings.end(), _compareEncodings );
465 
466  return smEncodings;
467 }
468 
470 {
471  mErrors.clear();
472 }
473 
475 {
476  return !mErrors.isEmpty();
477 }
478 
480 {
481  return mErrors;
482 }
483 
485 {
486  mErrors << msg;
487 }
488