Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator 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 /* $Id$ */
16 
17 #include <QSettings>
18 #include <QTextCodec>
19 
20 #include <cfloat> // for DBL_MAX
21 #include <climits>
22 
23 #include "qgsvectordataprovider.h"
24 #include "qgsfeature.h"
25 #include "qgsfield.h"
26 #include "qgslogger.h"
27 
29  : QgsDataProvider( uri )
30  , mCacheMinMaxDirty( true )
31  , mFetchFeaturesWithoutGeom( true )
32 {
33  QSettings settings;
34  setEncoding( settings.value( "/UI/encoding", QString( "System" ) ).toString() );
35 }
36 
37 
39 {
40 }
41 
43 {
44  return "Generic vector file";
45 }
46 
48 {
49  return -1;
50 }
51 
53  QgsFeature& feature,
54  bool fetchGeometry,
55  QgsAttributeList fetchAttributes )
56 {
57  select( fetchAttributes, QgsRectangle(), fetchGeometry );
58 
59  while ( nextFeature( feature ) )
60  {
61  if ( feature.id() == featureId )
62  return true;
63  }
64 
65  return false;
66 }
67 
69 {
70  return QString();
71 }
72 
74 {
75  return false;
76 }
77 
79 {
80  return false;
81 }
82 
83 bool QgsVectorDataProvider::addAttributes( const QList<QgsField> & attributes )
84 {
85  return false;
86 }
87 
88 bool QgsVectorDataProvider::addAttributes( const QMap<QString, QString> &attributes )
89 {
90  const QList< NativeType > &types = nativeTypes();
91  QList< QgsField > list;
92 
93  for ( QMap<QString, QString>::const_iterator it = attributes.constBegin(); it != attributes.constEnd(); it++ )
94  {
95  int i;
96  for ( i = 0; i < types.size() && types[i].mTypeName != it.value(); i++ )
97  ;
98 
99  if ( i == types.size() )
100  return false;
101 
102  list << QgsField( it.key(), types[i].mType, it.value() );
103  }
104 
105  return addAttributes( list );
106 }
107 
109 {
110  return false;
111 }
112 
114 {
115  return false;
116 }
117 
118 QVariant QgsVectorDataProvider::defaultValue( int fieldId )
119 {
120  return QVariant();
121 }
122 
124 {
125  return false;
126 }
127 
129 {
130  return false;
131 }
132 
134 {
135  return true;
136 }
137 
139 {
141 }
142 
143 
144 void QgsVectorDataProvider::setEncoding( const QString& e )
145 {
146  QTextCodec* ncodec = QTextCodec::codecForName( e.toLocal8Bit().data() );
147  if ( ncodec )
148  {
149  mEncoding = ncodec;
150  }
151  else
152  {
153  QgsDebugMsg( "error finding QTextCodec for " + e );
154  }
155 }
156 
158 {
159  if ( mEncoding )
160  {
161  return mEncoding->name();
162  }
163 
164  return "";
165 }
166 
168 {
169  QStringList abilitiesList;
170 
171  int abilities = capabilities();
172 
173  if ( abilities & QgsVectorDataProvider::AddFeatures )
174  {
175  abilitiesList += tr( "Add Features" );
176  QgsDebugMsg( "Capability: Add Features" );
177  }
178 
179  if ( abilities & QgsVectorDataProvider::DeleteFeatures )
180  {
181  abilitiesList += tr( "Delete Features" );
182  QgsDebugMsg( "Capability: Delete Features" );
183  }
184 
186  {
187  abilitiesList += tr( "Change Attribute Values" );
188  QgsDebugMsg( "Capability: Change Attribute Values" );
189  }
190 
191  if ( abilities & QgsVectorDataProvider::AddAttributes )
192  {
193  abilitiesList += tr( "Add Attributes" );
194  QgsDebugMsg( "Capability: Add Attributes" );
195  }
196 
197  if ( abilities & QgsVectorDataProvider::DeleteAttributes )
198  {
199  abilitiesList += tr( "Delete Attributes" );
200  QgsDebugMsg( "Capability: Delete Attributes" );
201  }
202 
204  {
205  // TODO: Tighten up this test. See QgsOgrProvider for details.
206  abilitiesList += tr( "Create Spatial Index" );
207  QgsDebugMsg( "Capability: Create Spatial Index" );
208  }
209 
210  if ( abilities & QgsVectorDataProvider::SelectAtId )
211  {
212  abilitiesList += tr( "Fast Access to Features at ID" );
213  QgsDebugMsg( "Capability: Select at ID" );
214  }
215 
216  if ( abilities & QgsVectorDataProvider::ChangeGeometries )
217  {
218  abilitiesList += tr( "Change Geometries" );
219  QgsDebugMsg( "Capability: Change Geometries" );
220  }
221 
222  return abilitiesList.join( ", " );
223 
224 }
225 
226 
227 int QgsVectorDataProvider::fieldNameIndex( const QString& fieldName ) const
228 {
229  const QgsFieldMap &theFields = fields();
230 
231  for ( QgsFieldMap::const_iterator it = theFields.constBegin(); it != theFields.constEnd(); ++it )
232  {
233  if ( QString::compare( it->name(), fieldName, Qt::CaseInsensitive ) == 0 )
234  {
235  return it.key();
236  }
237  }
238  return -1;
239 }
240 
241 QMap<QString, int> QgsVectorDataProvider::fieldNameMap() const
242 {
243  QMap<QString, int> resultMap;
244 
245  const QgsFieldMap& theFields = fields();
246  QgsFieldMap::const_iterator field_it = theFields.constBegin();
247  for ( ; field_it != theFields.constEnd(); ++field_it )
248  {
249  resultMap.insert( field_it.value().name(), field_it.key() );
250  }
251 
252  return resultMap;
253 }
254 
256 {
257  uint count = fieldCount();
258  QgsAttributeList list;
259 
260  for ( uint i = 0; i < count; i++ )
261  list.append( i );
262 
263  return list;
264 }
265 
267 {
269 }
270 
271 const QList< QgsVectorDataProvider::NativeType > &QgsVectorDataProvider::nativeTypes() const
272 {
273  return mNativeTypes;
274 }
275 
276 const QMap<QString, QVariant::Type> &QgsVectorDataProvider::supportedNativeTypes() const
277 {
278  if ( mOldTypeList.size() > 0 )
279  return mOldTypeList;
280 
282 
283  const QList< QgsVectorDataProvider::NativeType > &types = nativeTypes();
284 
285  for ( QList< QgsVectorDataProvider::NativeType >::const_iterator it = types.constBegin(); it != types.constEnd(); it++ )
286  {
287  p->mOldTypeList.insert( it->mTypeName, it->mType );
288  }
289 
290  return p->mOldTypeList;
291 }
292 
294 {
295  int i;
296  for ( i = 0; i < mNativeTypes.size(); i++ )
297  {
298  if ( field.type() == mNativeTypes[i].mType &&
299  field.length() >= mNativeTypes[i].mMinLen && field.length() <= mNativeTypes[i].mMaxLen &&
300  field.precision() >= mNativeTypes[i].mMinPrec && field.precision() <= mNativeTypes[i].mMaxPrec )
301  {
302  break;
303  }
304  }
305 
306  return i < mNativeTypes.size();
307 }
308 
310 {
311  if ( !fields().contains( index ) )
312  {
313  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
314  return QVariant();
315  }
316 
317  fillMinMaxCache();
318 
319  if ( !mCacheMinValues.contains( index ) )
320  return QVariant();
321 
322  return mCacheMinValues[index];
323 }
324 
326 {
327  if ( !fields().contains( index ) )
328  {
329  QgsDebugMsg( "Warning: access requested to invalid field index: " + QString::number( index ) );
330  return QVariant();
331  }
332 
333  fillMinMaxCache();
334 
335  if ( !mCacheMaxValues.contains( index ) )
336  return QVariant();
337 
338  return mCacheMaxValues[index];
339 }
340 
341 void QgsVectorDataProvider::uniqueValues( int index, QList<QVariant> &values, int limit )
342 {
343  QgsFeature f;
344  QgsAttributeList keys;
345  keys.append( index );
346  select( keys, QgsRectangle(), false );
347 
348  QSet<QString> set;
349  values.clear();
350 
351  while ( nextFeature( f ) )
352  {
353  if ( !set.contains( f.attributeMap()[index].toString() ) )
354  {
355  values.append( f.attributeMap()[index] );
356  set.insert( f.attributeMap()[index].toString() );
357  }
358 
359  if ( limit >= 0 && values.size() >= limit )
360  break;
361  }
362 }
363 
365 {
366  mCacheMinMaxDirty = true;
367 }
368 
370 {
371  if ( !mCacheMinMaxDirty )
372  return;
373 
374  const QgsFieldMap& flds = fields();
375  for ( QgsFieldMap::const_iterator it = flds.begin(); it != flds.end(); ++it )
376  {
377  if ( it->type() == QVariant::Int )
378  {
379  mCacheMinValues[it.key()] = QVariant( INT_MAX );
380  mCacheMaxValues[it.key()] = QVariant( INT_MIN );
381  }
382  else if ( it->type() == QVariant::Double )
383  {
384  mCacheMinValues[it.key()] = QVariant( DBL_MAX );
385  mCacheMaxValues[it.key()] = QVariant( -DBL_MAX );
386  }
387  else
388  {
389  mCacheMinValues[it.key()] = QVariant();
390  mCacheMaxValues[it.key()] = QVariant();
391  }
392  }
393 
394  QgsFeature f;
395  QgsAttributeList keys = mCacheMinValues.keys();
396  select( keys, QgsRectangle(), false );
397 
398  while ( nextFeature( f ) )
399  {
400  QgsAttributeMap attrMap = f.attributeMap();
401  for ( QgsAttributeList::const_iterator it = keys.begin(); it != keys.end(); ++it )
402  {
403  const QVariant& varValue = attrMap[*it];
404 
405  if ( flds[*it].type() == QVariant::Int )
406  {
407  int value = varValue.toInt();
408  if ( value < mCacheMinValues[*it].toInt() )
409  mCacheMinValues[*it] = value;
410  if ( value > mCacheMaxValues[*it].toInt() )
411  mCacheMaxValues[*it] = value;
412  }
413  else if ( flds[*it].type() == QVariant::Double )
414  {
415  double value = varValue.toDouble();
416  if ( value < mCacheMinValues[*it].toDouble() )
417  mCacheMinValues[*it] = value;
418  if ( value > mCacheMaxValues[*it].toDouble() )
419  mCacheMaxValues[*it] = value;
420  }
421  else
422  {
423  QString value = varValue.toString();
424  if ( mCacheMinValues[*it].isNull() || value < mCacheMinValues[*it].toString() )
425  {
426  mCacheMinValues[*it] = value;
427  }
428  if ( mCacheMaxValues[*it].isNull() || value > mCacheMaxValues[*it].toString() )
429  {
430  mCacheMaxValues[*it] = value;
431  }
432  }
433  }
434  }
435 
436  mCacheMinMaxDirty = false;
437 }
438 
439 QVariant QgsVectorDataProvider::convertValue( QVariant::Type type, QString value )
440 {
441  QVariant v( value );
442 
443  if ( !v.convert( type ) )
444  v = QVariant( QString::null );
445 
446  return v;
447 }
448 
450 {
451  if ( smEncodings.isEmpty() )
452  {
453  smEncodings << "BIG5";
454  smEncodings << "BIG5-HKSCS";
455  smEncodings << "EUCJP";
456  smEncodings << "EUCKR";
457  smEncodings << "GB2312";
458  smEncodings << "GBK";
459  smEncodings << "GB18030";
460  smEncodings << "JIS7";
461  smEncodings << "SHIFT-JIS";
462  smEncodings << "TSCII";
463  smEncodings << "UTF-8";
464  smEncodings << "UTF-16";
465  smEncodings << "KOI8-R";
466  smEncodings << "KOI8-U";
467  smEncodings << "ISO8859-1";
468  smEncodings << "ISO8859-2";
469  smEncodings << "ISO8859-3";
470  smEncodings << "ISO8859-4";
471  smEncodings << "ISO8859-5";
472  smEncodings << "ISO8859-6";
473  smEncodings << "ISO8859-7";
474  smEncodings << "ISO8859-8";
475  smEncodings << "ISO8859-8-I";
476  smEncodings << "ISO8859-9";
477  smEncodings << "ISO8859-10";
478  smEncodings << "ISO8859-11";
479  smEncodings << "ISO8859-12";
480  smEncodings << "ISO8859-13";
481  smEncodings << "ISO8859-14";
482  smEncodings << "ISO8859-15";
483  smEncodings << "IBM 850";
484  smEncodings << "IBM 866";
485  smEncodings << "CP874";
486  smEncodings << "CP1250";
487  smEncodings << "CP1251";
488  smEncodings << "CP1252";
489  smEncodings << "CP1253";
490  smEncodings << "CP1254";
491  smEncodings << "CP1255";
492  smEncodings << "CP1256";
493  smEncodings << "CP1257";
494  smEncodings << "CP1258";
495  smEncodings << "Apple Roman";
496  smEncodings << "TIS-620";
497  smEncodings << "System";
498  }
499 
500  return smEncodings;
501 }
502 
504 {
505  mErrors.clear();
506 }
507 
509 {
510  return !mErrors.isEmpty();
511 }
512 
514 {
515  return mErrors;
516 }
517 
519 {
520  mErrors << msg;
521 }
522