Quantum GIS API Documentation  1.7.5-Wroclaw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
qgsvectorfilewriter.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsvectorfilewriter.cpp
3  generic vector file writer
4  -------------------
5  begin : Sat Jun 16 2004
6  copyright : (C) 2004 by Tim Sutton
7  email : tim at linfiniti.com
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 /* $Id$ */
19 
20 #include "qgsapplication.h"
21 #include "qgsfield.h"
22 #include "qgsfeature.h"
23 #include "qgsgeometry.h"
24 #include "qgslogger.h"
26 #include "qgsvectorfilewriter.h"
27 
28 #include <QFile>
29 #include <QSettings>
30 #include <QFileInfo>
31 #include <QDir>
32 #include <QTextCodec>
33 #include <QTextStream>
34 #include <QSet>
35 #include <QMetaType>
36 
37 #include <cassert>
38 #include <cstdlib> // size_t
39 
40 #include <ogr_api.h>
41 #include <ogr_srs_api.h>
42 #include <cpl_error.h>
43 #include <cpl_conv.h>
44 
45 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1800
46 #define TO8(x) (x).toUtf8().constData()
47 #define TO8F(x) (x).toUtf8().constData()
48 #else
49 #define TO8(x) (x).toLocal8Bit().constData()
50 #define TO8F(x) QFile::encodeName( x ).constData()
51 #endif
52 
53 
55  const QString &theVectorFileName,
56  const QString &theFileEncoding,
57  const QgsFieldMap& fields,
58  QGis::WkbType geometryType,
60  const QString& driverName,
61  const QStringList &datasourceOptions,
62  const QStringList &layerOptions
63 )
64  : mDS( NULL )
65  , mLayer( NULL )
66  , mGeom( NULL )
67  , mError( NoError )
68 {
69  QString vectorFileName = theVectorFileName;
70  QString fileEncoding = theFileEncoding;
71 
72  // find driver in OGR
73  OGRSFDriverH poDriver;
75  poDriver = OGRGetDriverByName( driverName.toLocal8Bit().data() );
76 
77  if ( poDriver == NULL )
78  {
79  mErrorMessage = QObject::tr( "OGR driver for '%1' not found (OGR error: %2)" )
80  .arg( driverName )
81  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
83  return;
84  }
85 
86  if ( driverName == "ESRI Shapefile" )
87  {
88  if ( !vectorFileName.endsWith( ".shp", Qt::CaseInsensitive ) &&
89  !vectorFileName.endsWith( ".dbf", Qt::CaseInsensitive ) )
90  {
91  vectorFileName += ".shp";
92  }
93 
94 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM < 1700
95  // check for unique fieldnames
96  QSet<QString> fieldNames;
97  QgsFieldMap::const_iterator fldIt;
98  for ( fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
99  {
100  QString name = fldIt.value().name().left( 10 );
101  if ( fieldNames.contains( name ) )
102  {
103  mErrorMessage = QObject::tr( "trimming attribute name '%1' to ten significant characters produces duplicate column name." )
104  .arg( fldIt.value().name() );
106  return;
107  }
108  fieldNames << name;
109  }
110 #endif
111 
112  deleteShapeFile( vectorFileName );
113  }
114  else if ( driverName == "KML" )
115  {
116  if ( !vectorFileName.endsWith( ".kml", Qt::CaseInsensitive ) )
117  {
118  vectorFileName += ".kml";
119  }
120 
121  if ( fileEncoding.compare( "UTF-8", Qt::CaseInsensitive ) != 0 )
122  {
123  QgsDebugMsg( "forced UTF-8 encoding for KML" );
124  fileEncoding = "UTF-8";
125  }
126 
127  QFile::remove( vectorFileName );
128  }
129  else
130  {
131  QString longName;
132  QString trLongName;
133  QString glob;
134  QString exts;
135  if ( QgsVectorFileWriter::driverMetadata( driverName, longName, trLongName, glob, exts ) )
136  {
137  QStringList allExts = exts.split( " ", QString::SkipEmptyParts );
138  bool found = false;
139  foreach( QString ext, allExts )
140  {
141  if ( vectorFileName.endsWith( "." + ext, Qt::CaseInsensitive ) )
142  {
143  found = true;
144  break;
145  }
146  }
147 
148  if ( !found )
149  {
150  vectorFileName += "." + allExts[0];
151  }
152  }
153 
154  QFile::remove( vectorFileName );
155  }
156 
157  char **options = NULL;
158  if ( !datasourceOptions.isEmpty() )
159  {
160  options = new char *[ datasourceOptions.size()+1 ];
161  for ( int i = 0; i < datasourceOptions.size(); i++ )
162  {
163  options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().data() );
164  }
165  options[ datasourceOptions.size()] = NULL;
166  }
167 
168  // create the data source
169  mDS = OGR_Dr_CreateDataSource( poDriver, TO8( vectorFileName ), options );
170 
171  if ( options )
172  {
173  for ( int i = 0; i < datasourceOptions.size(); i++ )
174  CPLFree( options[i] );
175  delete [] options;
176  options = NULL;
177  }
178 
179  if ( mDS == NULL )
180  {
182  mErrorMessage = QObject::tr( "creation of data source failed (OGR error:%1)" )
183  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
184  return;
185  }
186 
187  QgsDebugMsg( "Created data source" );
188 
189  // use appropriate codec
190  mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().data() );
191  if ( !mCodec )
192  {
193  QSettings settings;
194  QString enc = settings.value( "/UI/encoding", QString( "System" ) ).toString();
195  QgsDebugMsg( "error finding QTextCodec for " + fileEncoding );
196  mCodec = QTextCodec::codecForName( enc.toLocal8Bit().data() );
197  if ( !mCodec )
198  {
199  QgsDebugMsg( "error finding QTextCodec for " + enc );
200  mCodec = QTextCodec::codecForLocale();
201  }
202  }
203 
204  // consider spatial reference system of the layer
205  OGRSpatialReferenceH ogrRef = NULL;
206  if ( srs )
207  {
208  QString srsWkt = srs->toWkt();
209  QgsDebugMsg( "WKT to save as is " + srsWkt );
210  ogrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().data() );
211  }
212 
213  // datasource created, now create the output layer
214  QString layerName = QFileInfo( vectorFileName ).baseName();
215  OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>( geometryType );
216 
217  if ( !layerOptions.isEmpty() )
218  {
219  options = new char *[ layerOptions.size()+1 ];
220  for ( int i = 0; i < layerOptions.size(); i++ )
221  {
222  options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().data() );
223  }
224  options[ layerOptions.size()] = NULL;
225  }
226 
227  mLayer = OGR_DS_CreateLayer( mDS, TO8F( layerName ), ogrRef, wkbType, options );
228 
229  if ( options )
230  {
231  for ( int i = 0; i < layerOptions.size(); i++ )
232  CPLFree( options[i] );
233  delete [] options;
234  options = NULL;
235  }
236 
237  if ( srs )
238  {
239  if ( driverName == "ESRI Shapefile" )
240  {
241  QString layerName = vectorFileName.left( vectorFileName.indexOf( ".shp", Qt::CaseInsensitive ) );
242  QFile prjFile( layerName + ".qpj" );
243  if ( prjFile.open( QIODevice::WriteOnly ) )
244  {
245  QTextStream prjStream( &prjFile );
246  prjStream << srs->toWkt().toLocal8Bit().data() << endl;
247  prjFile.close();
248  }
249  else
250  {
251  QgsDebugMsg( "Couldn't open file " + layerName + ".qpj" );
252  }
253  }
254 
255  OSRDestroySpatialReference( ogrRef );
256  }
257 
258  if ( mLayer == NULL )
259  {
260  mErrorMessage = QObject::tr( "creation of layer failed (OGR error:%1)" )
261  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
263  return;
264  }
265 
266  OGRFeatureDefnH defn = OGR_L_GetLayerDefn( mLayer );
267 
268  QgsDebugMsg( "created layer" );
269 
270  // create the fields
271  QgsDebugMsg( "creating " + QString::number( fields.size() ) + " fields" );
272 
273  mFields = fields;
274  mAttrIdxToOgrIdx.clear();
275 
276  QgsFieldMap::const_iterator fldIt;
277  for ( fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
278  {
279  const QgsField& attrField = fldIt.value();
280 
281  OGRFieldType ogrType = OFTString; //default to string
282  int ogrWidth = fldIt->length();
283  int ogrPrecision = fldIt->precision();
284  switch ( attrField.type() )
285  {
286  case QVariant::LongLong:
287  ogrType = OFTString;
288  ogrWidth = ogrWidth > 0 && ogrWidth <= 21 ? ogrWidth : 21;
289  ogrPrecision = -1;
290  break;
291 
292  case QVariant::String:
293  ogrType = OFTString;
294  if ( ogrWidth < 0 || ogrWidth > 255 )
295  ogrWidth = 255;
296  break;
297 
298  case QVariant::Int:
299  ogrType = OFTInteger;
300  ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
301  ogrPrecision = 0;
302  break;
303 
304  case QVariant::Double:
305  ogrType = OFTReal;
306  break;
307 
308  default:
309  //assert(0 && "invalid variant type!");
310  mErrorMessage = QObject::tr( "unsupported type for field %1" )
311  .arg( attrField.name() );
313  return;
314  }
315 
316  // create field definition
317  OGRFieldDefnH fld = OGR_Fld_Create( mCodec->fromUnicode( attrField.name() ), ogrType );
318  if ( ogrWidth > 0 )
319  {
320  OGR_Fld_SetWidth( fld, ogrWidth );
321  }
322 
323  if ( ogrPrecision >= 0 )
324  {
325  OGR_Fld_SetPrecision( fld, ogrPrecision );
326  }
327 
328  // create the field
329  QgsDebugMsg( "creating field " + attrField.name() +
330  " type " + QString( QVariant::typeToName( attrField.type() ) ) +
331  " width " + QString::number( ogrWidth ) +
332  " precision " + QString::number( ogrPrecision ) );
333  if ( OGR_L_CreateField( mLayer, fld, true ) != OGRERR_NONE )
334  {
335  QgsDebugMsg( "error creating field " + attrField.name() );
336  mErrorMessage = QObject::tr( "creation of field %1 failed (OGR error: %2)" )
337  .arg( attrField.name() )
338  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
340  return;
341  }
342 
343  int ogrIdx = OGR_FD_GetFieldIndex( defn, mCodec->fromUnicode( attrField.name() ) );
344  if ( ogrIdx < 0 )
345  {
346 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM < 1700
347  // if we didn't find our new column, assume it's name was truncated and
348  // it was the last one added (like for shape files)
349  int fieldCount = OGR_FD_GetFieldCount( defn );
350 
351  OGRFieldDefnH fdefn = OGR_FD_GetFieldDefn( defn, fieldCount - 1 );
352  if ( fdefn )
353  {
354  const char *fieldName = OGR_Fld_GetNameRef( fdefn );
355 
356  if ( attrField.name().left( strlen( fieldName ) ) == fieldName )
357  {
358  ogrIdx = fieldCount - 1;
359  }
360  }
361 #else
362  // GDAL 1.7 not just truncates, but launders more aggressivly.
363  ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
364 #endif
365 
366  if ( ogrIdx < 0 )
367  {
368  QgsDebugMsg( "error creating field " + attrField.name() );
369  mErrorMessage = QObject::tr( "created field %1 not found (OGR error: %2)" )
370  .arg( attrField.name() )
371  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
373  return;
374  }
375  }
376 
377  mAttrIdxToOgrIdx.insert( fldIt.key(), ogrIdx );
378  }
379 
380  QgsDebugMsg( "Done creating fields" );
381 
382  mWkbType = geometryType;
383  if ( mWkbType != QGis::WKBNoGeometry )
384  {
385  // create geometry which will be used for import
387  }
388 }
389 
391 {
392  return OGR_G_CreateGeometry(( OGRwkbGeometryType ) wkbType );
393 }
394 
395 
397 {
398  return mError;
399 }
400 
402 {
403  return mErrorMessage;
404 }
405 
407 {
408  QgsAttributeMap::const_iterator it;
409 
410  // create the feature
411  OGRFeatureH poFeature = OGR_F_Create( OGR_L_GetLayerDefn( mLayer ) );
412 
413  OGRErr err = OGR_F_SetFID( poFeature, feature.id() );
414  if ( err != OGRERR_NONE )
415  {
416  QgsDebugMsg( QString( "Failed to set feature id to %1: %2 (OGR error: %3)" )
417  .arg( feature.id() )
418  .arg( err ).arg( CPLGetLastErrorMsg() )
419  );
420  }
421 
422  // attribute handling
423  QgsFieldMap::const_iterator fldIt;
424  for ( fldIt = mFields.begin(); fldIt != mFields.end(); ++fldIt )
425  {
426  if ( !feature.attributeMap().contains( fldIt.key() ) )
427  {
428  QgsDebugMsg( QString( "no attribute for field %1" ).arg( fldIt.key() ) );
429  continue;
430  }
431 
432  if ( !mAttrIdxToOgrIdx.contains( fldIt.key() ) )
433  {
434  QgsDebugMsg( QString( "no ogr field for field %1" ).arg( fldIt.key() ) );
435  continue;
436  }
437 
438  const QVariant& attrValue = feature.attributeMap()[ fldIt.key()];
439  int ogrField = mAttrIdxToOgrIdx[ fldIt.key()];
440 
441  switch ( attrValue.type() )
442  {
443  case QVariant::Int:
444  OGR_F_SetFieldInteger( poFeature, ogrField, attrValue.toInt() );
445  break;
446  case QVariant::Double:
447  OGR_F_SetFieldDouble( poFeature, ogrField, attrValue.toDouble() );
448  break;
449  case QVariant::LongLong:
450  case QVariant::String:
451  OGR_F_SetFieldString( poFeature, ogrField, mCodec->fromUnicode( attrValue.toString() ).data() );
452  break;
453  case QVariant::Invalid:
454  break;
455  default:
456  mErrorMessage = QObject::tr( "Invalid variant type for field %1[%2]: received %3 with type %4" )
457  .arg( fldIt.value().name() )
458  .arg( ogrField )
459  .arg( QMetaType::typeName( attrValue.type() ) )
460  .arg( attrValue.toString() );
463  return false;
464  }
465  }
466 
467  if ( mWkbType != QGis::WKBNoGeometry )
468  {
469  // build geometry from WKB
470  QgsGeometry *geom = feature.geometry();
471  if ( geom && geom->wkbType() != mWkbType )
472  {
473  // there's a problem when layer type is set as wkbtype Polygon
474  // although there are also features of type MultiPolygon
475  // (at least in OGR provider)
476  // If the feature's wkbtype is different from the layer's wkbtype,
477  // try to export it too.
478  //
479  // Btw. OGRGeometry must be exactly of the type of the geometry which it will receive
480  // i.e. Polygons can't be imported to OGRMultiPolygon
481 
482  OGRGeometryH mGeom2 = createEmptyGeometry( geom->wkbType() );
483 
484  if ( !mGeom2 )
485  {
486  QgsDebugMsg( QString( "Failed to create empty geometry for type %1 (OGR error: %2)" ).arg( geom->wkbType() ).arg( CPLGetLastErrorMsg() ) );
487  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
488  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
490  OGR_F_Destroy( poFeature );
491  return false;
492  }
493 
494  OGRErr err = OGR_G_ImportFromWkb( mGeom2, geom->asWkb(), geom->wkbSize() );
495  if ( err != OGRERR_NONE )
496  {
497  QgsDebugMsg( QString( "Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
498  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
499  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
501  OGR_F_Destroy( poFeature );
502  return false;
503  }
504 
505  // pass ownership to geometry
506  OGR_F_SetGeometryDirectly( poFeature, mGeom2 );
507  }
508  else if ( geom )
509  {
510  OGRErr err = OGR_G_ImportFromWkb( mGeom, geom->asWkb(), geom->wkbSize() );
511  if ( err != OGRERR_NONE )
512  {
513  QgsDebugMsg( QString( "Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
514  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
515  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
517  OGR_F_Destroy( poFeature );
518  return false;
519  }
520 
521  // set geometry (ownership is not passed to OGR)
522  OGR_F_SetGeometry( poFeature, mGeom );
523  }
524  }
525 
526  // put the created feature to layer
527  if ( OGR_L_CreateFeature( mLayer, poFeature ) != OGRERR_NONE )
528  {
529  mErrorMessage = QObject::tr( "Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
531 
533  OGR_F_Destroy( poFeature );
534  return false;
535  }
536 
537  OGR_F_Destroy( poFeature );
538 
539  return true;
540 }
541 
543 {
544  if ( mGeom )
545  {
546  OGR_G_DestroyGeometry( mGeom );
547  }
548 
549  if ( mDS )
550  {
551  OGR_DS_Destroy( mDS );
552  }
553 }
554 
555 
556 
557 
560  const QString& shapefileName,
561  const QString& fileEncoding,
562  const QgsCoordinateReferenceSystem* destCRS,
563  bool onlySelected,
564  QString *errorMessage,
565  const QStringList &datasourceOptions,
566  const QStringList &layerOptions )
567 {
568  return writeAsVectorFormat( layer, shapefileName, fileEncoding, destCRS, "ESRI Shapefile", onlySelected, errorMessage, datasourceOptions, layerOptions );
569 }
570 
573  const QString& fileName,
574  const QString& fileEncoding,
575  const QgsCoordinateReferenceSystem *destCRS,
576  const QString& driverName,
577  bool onlySelected,
578  QString *errorMessage,
579  const QStringList &datasourceOptions,
580  const QStringList &layerOptions,
581  bool skipAttributeCreation )
582 {
583  const QgsCoordinateReferenceSystem* outputCRS;
584  QgsCoordinateTransform* ct = 0;
585  int shallTransform = false;
586 
587  if ( destCRS && destCRS->isValid() )
588  {
589  // This means we should transform
590  outputCRS = destCRS;
591  shallTransform = true;
592  }
593  else
594  {
595  // This means we shouldn't transform, use source CRS as output (if defined)
596  outputCRS = &layer->crs();
597  }
598  QgsVectorFileWriter* writer =
599  new QgsVectorFileWriter( fileName, fileEncoding, skipAttributeCreation ? QgsFieldMap() : layer->pendingFields(), layer->wkbType(), outputCRS, driverName, datasourceOptions, layerOptions );
600 
601  // check whether file creation was successful
602  WriterError err = writer->hasError();
603  if ( err != NoError )
604  {
605  if ( errorMessage )
606  *errorMessage = writer->errorMessage();
607  delete writer;
608  return err;
609  }
610 
611  if ( errorMessage )
612  {
613  errorMessage->clear();
614  }
615 
616  QgsAttributeList allAttr = skipAttributeCreation ? QgsAttributeList() : layer->pendingAllAttributesList();
617  QgsFeature fet;
618 
619  layer->select( allAttr, QgsRectangle(), layer->wkbType() != QGis::WKBNoGeometry );
620 
621  const QgsFeatureIds& ids = layer->selectedFeaturesIds();
622 
623  // Create our transform
624  if ( destCRS )
625  {
626  ct = new QgsCoordinateTransform( layer->crs(), *destCRS );
627  }
628 
629  // Check for failure
630  if ( ct == NULL )
631  {
632  shallTransform = false;
633  }
634 
635  int n = 0, errors = 0;
636 
637  // write all features
638  while ( layer->nextFeature( fet ) )
639  {
640  if ( onlySelected && !ids.contains( fet.id() ) )
641  continue;
642 
643  if ( shallTransform )
644  {
645  try
646  {
647  if ( fet.geometry() )
648  {
649  fet.geometry()->transform( *ct );
650  }
651  }
652  catch ( QgsCsException &e )
653  {
654  delete ct;
655  delete writer;
656 
657  QString msg = QObject::tr( "Failed to transform a point while drawing a feature of type '%1'. Writing stopped. (Exception: %2)" )
658  .arg( fet.typeName() ).arg( e.what() );
659  QgsLogger::warning( msg );
660  if ( errorMessage )
661  *errorMessage = msg;
662 
663  return ErrProjection;
664  }
665  }
666  if ( skipAttributeCreation )
667  {
668  fet.clearAttributeMap();
669  }
670  if ( !writer->addFeature( fet ) )
671  {
672  WriterError err = writer->hasError();
673  if ( err != NoError && errorMessage )
674  {
675  if ( errorMessage->isEmpty() )
676  {
677  *errorMessage = QObject::tr( "Feature write errors:" );
678  }
679  *errorMessage += "\n" + writer->errorMessage();
680  }
681  errors++;
682 
683  if ( errors > 1000 )
684  {
685  if ( errorMessage )
686  {
687  *errorMessage += QObject::tr( "Stopping after %1 errors" ).arg( errors );
688  }
689 
690  n = -1;
691  break;
692  }
693  }
694  n++;
695  }
696 
697  delete writer;
698 
699  if ( shallTransform )
700  {
701  delete ct;
702  }
703 
704  if ( errors > 0 && errorMessage && n > 0 )
705  {
706  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
707  }
708 
709  return errors == 0 ? NoError : ErrFeatureWriteFailed;
710 }
711 
712 
713 bool QgsVectorFileWriter::deleteShapeFile( QString theFileName )
714 {
715  QFileInfo fi( theFileName );
716  QDir dir = fi.dir();
717 
718  QStringList filter;
719  const char *suffixes[] = { ".shp", ".shx", ".dbf", ".prj", ".qix", ".qpj" };
720  for ( std::size_t i = 0; i < sizeof( suffixes ) / sizeof( *suffixes ); i++ )
721  {
722  filter << fi.completeBaseName() + suffixes[i];
723  }
724 
725  bool ok = true;
726  foreach( QString file, dir.entryList( filter ) )
727  {
728  if ( !QFile::remove( dir.canonicalPath() + "/" + file ) )
729  {
730  QgsDebugMsg( "Removing file failed : " + file );
731  ok = false;
732  }
733  }
734 
735  return ok;
736 }
737 
739 {
740  QMap<QString, QString> resultMap;
741 
743  int const drvCount = OGRGetDriverCount();
744 
745  for ( int i = 0; i < drvCount; ++i )
746  {
747  OGRSFDriverH drv = OGRGetDriver( i );
748  if ( drv )
749  {
750  QString drvName = OGR_Dr_GetName( drv );
751  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
752  {
753  QString filterString = filterForDriver( drvName );
754  if ( filterString.isEmpty() )
755  continue;
756 
757  resultMap.insert( filterString, drvName );
758  }
759  }
760  }
761 
762  return resultMap;
763 }
764 
765 QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
766 {
767  QMap<QString, QString> resultMap;
768 
770  int const drvCount = OGRGetDriverCount();
771 
772  for ( int i = 0; i < drvCount; ++i )
773  {
774  OGRSFDriverH drv = OGRGetDriver( i );
775  if ( drv )
776  {
777  QString drvName = OGR_Dr_GetName( drv );
778  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
779  {
780  QString longName;
781  QString trLongName;
782  QString glob;
783  QString exts;
784  if ( QgsVectorFileWriter::driverMetadata( drvName, longName, trLongName, glob, exts ) && !trLongName.isEmpty() )
785  {
786  resultMap.insert( trLongName, drvName );
787  }
788  }
789  }
790  }
791 
792  return resultMap;
793 }
794 
796 {
797  QString filterString;
798  QMap< QString, QString> driverFormatMap = supportedFiltersAndFormats();
799  QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
800  for ( ; it != driverFormatMap.constEnd(); ++it )
801  {
802  if ( filterString.isEmpty() )
803  filterString += ";;";
804 
805  filterString += it.key();
806  }
807  return filterString;
808 }
809 
810 QString QgsVectorFileWriter::filterForDriver( const QString& driverName )
811 {
812  QString longName;
813  QString trLongName;
814  QString glob;
815  QString exts;
816  if ( !driverMetadata( driverName, longName, trLongName, glob, exts ) || trLongName.isEmpty() || glob.isEmpty() )
817  return "";
818 
819  return trLongName + " [OGR] (" + glob.toLower() + " " + glob.toUpper() + ")";
820 }
821 
822 bool QgsVectorFileWriter::driverMetadata( QString driverName, QString &longName, QString &trLongName, QString &glob, QString &ext )
823 {
824  if ( driverName.startsWith( "AVCE00" ) )
825  {
826  longName = "Arc/Info ASCII Coverage";
827  trLongName = QObject::tr( "Arc/Info ASCII Coverage" );
828  glob = "*.e00";
829  ext = "e00";
830  }
831  else if ( driverName.startsWith( "BNA" ) )
832  {
833  longName = "Atlas BNA";
834  trLongName = QObject::tr( "Atlas BNA" );
835  glob = "*.bna";
836  ext = "bna";
837  }
838  else if ( driverName.startsWith( "CSV" ) )
839  {
840  longName = "Comma Separated Value";
841  trLongName = QObject::tr( "Comma Separated Value" );
842  glob = "*.csv";
843  ext = "csv";
844  }
845  else if ( driverName.startsWith( "ESRI" ) )
846  {
847  longName = "ESRI Shapefile";
848  trLongName = QObject::tr( "ESRI Shapefile" );
849  glob = "*.shp";
850  ext = "shp";
851  }
852  else if ( driverName.startsWith( "FMEObjects Gateway" ) )
853  {
854  longName = "FMEObjects Gateway";
855  trLongName = QObject::tr( "FMEObjects Gateway" );
856  glob = "*.fdd";
857  ext = "fdd";
858  }
859  else if ( driverName.startsWith( "GeoJSON" ) )
860  {
861  longName = "GeoJSON";
862  trLongName = QObject::tr( "GeoJSON" );
863  glob = "*.geojson";
864  ext = "geojson";
865  }
866  else if ( driverName.startsWith( "GeoRSS" ) )
867  {
868  longName = "GeoRSS";
869  trLongName = QObject::tr( "GeoRSS" );
870  glob = "*.xml";
871  ext = "xml";
872  }
873  else if ( driverName.startsWith( "GML" ) )
874  {
875  longName = "Geography Markup Language [GML]";
876  trLongName = QObject::tr( "Geography Markup Language [GML]" );
877  glob = "*.gml";
878  ext = "gml";
879  }
880  else if ( driverName.startsWith( "GMT" ) )
881  {
882  longName = "Generic Mapping Tools [GMT]";
883  trLongName = QObject::tr( "Generic Mapping Tools [GMT]" );
884  glob = "*.gmt";
885  ext = "gmt";
886  }
887  else if ( driverName.startsWith( "GPX" ) )
888  {
889  longName = "GPS eXchange Format [GPX]";
890  trLongName = QObject::tr( "GPS eXchange Format [GPX]" );
891  glob = "*.gpx";
892  ext = "gpx";
893  }
894  else if ( driverName.startsWith( "Interlis 1" ) )
895  {
896  longName = "INTERLIS 1";
897  trLongName = QObject::tr( "INTERLIS 1" );
898  glob = "*.itf *.xml *.ili";
899  ext = "ili";
900  }
901  else if ( driverName.startsWith( "Interlis 2" ) )
902  {
903  longName = "INTERLIS 2";
904  trLongName = QObject::tr( "INTERLIS 2" );
905  glob = "*.itf *.xml *.ili";
906  ext = "ili";
907  }
908  else if ( driverName.startsWith( "KML" ) )
909  {
910  longName = "Keyhole Markup Language [KML]";
911  trLongName = QObject::tr( "Keyhole Markup Language [KML]" );
912  glob = "*.kml" ;
913  ext = "kml" ;
914  }
915  else if ( driverName.startsWith( "MapInfo File" ) )
916  {
917  longName = "Mapinfo File";
918  trLongName = QObject::tr( "Mapinfo File" );
919  glob = "*.mif *.tab";
920  ext = "mif tab";
921  }
922  else if ( driverName.startsWith( "DGN" ) )
923  {
924  longName = "Microstation DGN";
925  trLongName = QObject::tr( "Microstation DGN" );
926  glob = "*.dgn";
927  ext = "dgn";
928  }
929  else if ( driverName.startsWith( "S57" ) )
930  {
931  longName = "S-57 Base file";
932  trLongName = QObject::tr( "S-57 Base file" );
933  glob = "*.000";
934  ext = "000";
935  }
936  else if ( driverName.startsWith( "SDTS" ) )
937  {
938  longName = "Spatial Data Transfer Standard [SDTS]";
939  trLongName = QObject::tr( "Spatial Data Transfer Standard [SDTS]" );
940  glob = "*catd.ddf";
941  ext = "ddf";
942  }
943  else if ( driverName.startsWith( "SQLite" ) )
944  {
945  longName = "SQLite";
946  trLongName = QObject::tr( "SQLite" );
947  glob = "*.sqlite";
948  ext = "sqlite";
949  }
950  else if ( driverName.startsWith( "DXF" ) )
951  {
952  longName = "AutoCAD DXF";
953  trLongName = QObject::tr( "AutoCAD DXF" );
954  glob = "*.dxf";
955  ext = "dxf";
956  }
957  else if ( driverName.startsWith( "Geoconcept" ) )
958  {
959  longName = "Geoconcept";
960  trLongName = QObject::tr( "Geoconcept" );
961  glob = "*.gxt *.txt";
962  ext = "gxt";
963  }
964  else
965  {
966  return false;
967  }
968 
969  return true;
970 }