QGIS API Documentation  2.7.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules 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 
19 #include "qgsapplication.h"
20 #include "qgsfield.h"
21 #include "qgsfeature.h"
22 #include "qgsgeometry.h"
23 #include "qgslogger.h"
24 #include "qgsmessagelog.h"
26 #include "qgsvectorfilewriter.h"
27 #include "qgsrendererv2.h"
28 #include "qgssymbollayerv2.h"
29 #include "qgsvectordataprovider.h"
30 
31 #include <QFile>
32 #include <QSettings>
33 #include <QFileInfo>
34 #include <QDir>
35 #include <QTextCodec>
36 #include <QTextStream>
37 #include <QSet>
38 #include <QMetaType>
39 
40 #include <cassert>
41 #include <cstdlib> // size_t
42 #include <limits> // std::numeric_limits
43 
44 #include <ogr_srs_api.h>
45 #include <cpl_error.h>
46 #include <cpl_conv.h>
47 
48 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1800
49 #define TO8(x) (x).toUtf8().constData()
50 #define TO8F(x) (x).toUtf8().constData()
51 #else
52 #define TO8(x) (x).toLocal8Bit().constData()
53 #define TO8F(x) QFile::encodeName( x ).constData()
54 #endif
55 
56 
58  const QString &theVectorFileName,
59  const QString &theFileEncoding,
60  const QgsFields& fields,
61  QGis::WkbType geometryType,
63  const QString& driverName,
64  const QStringList &datasourceOptions,
65  const QStringList &layerOptions,
66  QString *newFilename,
67  SymbologyExport symbologyExport
68 )
69  : mDS( NULL )
70  , mLayer( NULL )
71  , mGeom( NULL )
72  , mError( NoError )
73  , mSymbologyExport( symbologyExport )
74 {
75  QString vectorFileName = theVectorFileName;
76  QString fileEncoding = theFileEncoding;
77  QStringList layOptions = layerOptions;
78  QStringList dsOptions = datasourceOptions;
79 
80  if ( theVectorFileName.isEmpty() )
81  {
82  mErrorMessage = QObject::tr( "Empty filename given" );
84  return;
85  }
86 
87  QString ogrDriverName;
88  if ( driverName == "MapInfo MIF" )
89  {
90  ogrDriverName = "MapInfo File";
91  }
92  else if ( driverName == "SpatiaLite" )
93  {
94  ogrDriverName = "SQLite";
95  if ( !dsOptions.contains( "SPATIALITE=YES" ) )
96  {
97  dsOptions.append( "SPATIALITE=YES" );
98  }
99  }
100  else if ( driverName == "DBF file" )
101  {
102  ogrDriverName = "ESRI Shapefile";
103  if ( !layOptions.contains( "SHPT=NULL" ) )
104  {
105  layOptions.append( "SHPT=NULL" );
106  }
107  srs = 0;
108  }
109  else
110  {
111  ogrDriverName = driverName;
112  }
113 
114  // find driver in OGR
115  OGRSFDriverH poDriver;
117 
118  poDriver = OGRGetDriverByName( ogrDriverName.toLocal8Bit().data() );
119 
120  if ( !poDriver )
121  {
122  mErrorMessage = QObject::tr( "OGR driver for '%1' not found (OGR error: %2)" )
123  .arg( driverName )
124  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
126  return;
127  }
128 
129  if ( ogrDriverName == "ESRI Shapefile" )
130  {
131  if ( layOptions.join( "" ).toUpper().indexOf( "ENCODING=" ) == -1 )
132  {
133  layOptions.append( "ENCODING=" + convertCodecNameForEncodingOption( fileEncoding ) );
134  }
135 
136  if ( driverName == "ESRI Shapefile" && !vectorFileName.endsWith( ".shp", Qt::CaseInsensitive ) )
137  {
138  vectorFileName += ".shp";
139  }
140  else if ( driverName == "DBF file" && !vectorFileName.endsWith( ".dbf", Qt::CaseInsensitive ) )
141  {
142  vectorFileName += ".dbf";
143  }
144 
145 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM < 1700
146  // check for unique fieldnames
147  QSet<QString> fieldNames;
148  for ( int i = 0; i < fields.count(); ++i )
149  {
150  QString name = fields[i].name().left( 10 );
151  if ( fieldNames.contains( name ) )
152  {
153  mErrorMessage = QObject::tr( "trimming attribute name '%1' to ten significant characters produces duplicate column name." )
154  .arg( fields[i].name() );
156  return;
157  }
158  fieldNames << name;
159  }
160 #endif
161 
162  deleteShapeFile( vectorFileName );
163  }
164  else if ( driverName == "KML" )
165  {
166  if ( !vectorFileName.endsWith( ".kml", Qt::CaseInsensitive ) )
167  {
168  vectorFileName += ".kml";
169  }
170 
171  if ( fileEncoding.compare( "UTF-8", Qt::CaseInsensitive ) != 0 )
172  {
173  QgsDebugMsg( "forced UTF-8 encoding for KML" );
174  fileEncoding = "UTF-8";
175  }
176 
177  QFile::remove( vectorFileName );
178  }
179  else
180  {
181  QString longName;
182  QString trLongName;
183  QString glob;
184  QString exts;
185  if ( QgsVectorFileWriter::driverMetadata( driverName, longName, trLongName, glob, exts ) )
186  {
187  QStringList allExts = exts.split( " ", QString::SkipEmptyParts );
188  bool found = false;
189  foreach ( QString ext, allExts )
190  {
191  if ( vectorFileName.endsWith( "." + ext, Qt::CaseInsensitive ) )
192  {
193  found = true;
194  break;
195  }
196  }
197 
198  if ( !found )
199  {
200  vectorFileName += "." + allExts[0];
201  }
202  }
203 
204  QFile::remove( vectorFileName );
205  }
206 
207  char **options = NULL;
208  if ( !dsOptions.isEmpty() )
209  {
210  options = new char *[ dsOptions.size()+1 ];
211  for ( int i = 0; i < dsOptions.size(); i++ )
212  {
213  options[i] = CPLStrdup( dsOptions[i].toLocal8Bit().data() );
214  }
215  options[ dsOptions.size()] = NULL;
216  }
217 
218  // create the data source
219  mDS = OGR_Dr_CreateDataSource( poDriver, TO8F( vectorFileName ), options );
220 
221  if ( options )
222  {
223  for ( int i = 0; i < dsOptions.size(); i++ )
224  CPLFree( options[i] );
225  delete [] options;
226  options = NULL;
227  }
228 
229  if ( mDS == NULL )
230  {
232  mErrorMessage = QObject::tr( "creation of data source failed (OGR error:%1)" )
233  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
234  return;
235  }
236 
237  QgsDebugMsg( "Created data source" );
238 
239  // use appropriate codec
240  mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
241  if ( !mCodec )
242  {
243  QgsDebugMsg( "error finding QTextCodec for " + fileEncoding );
244 
245  QSettings settings;
246  QString enc = settings.value( "/UI/encoding", "System" ).toString();
247  mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
248  if ( !mCodec )
249  {
250  QgsDebugMsg( "error finding QTextCodec for " + enc );
251  mCodec = QTextCodec::codecForLocale();
252  Q_ASSERT( mCodec );
253  }
254  }
255 
256  // consider spatial reference system of the layer
257  OGRSpatialReferenceH ogrRef = NULL;
258  if ( srs )
259  {
260  QString srsWkt = srs->toWkt();
261  QgsDebugMsg( "WKT to save as is " + srsWkt );
262  ogrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().data() );
263  }
264 
265  // datasource created, now create the output layer
266  QString layerName = QFileInfo( vectorFileName ).baseName();
267  OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>( geometryType );
268 
269  if ( !layOptions.isEmpty() )
270  {
271  options = new char *[ layOptions.size()+1 ];
272  for ( int i = 0; i < layOptions.size(); i++ )
273  {
274  options[i] = CPLStrdup( layOptions[i].toLocal8Bit().data() );
275  }
276  options[ layOptions.size()] = NULL;
277  }
278 
279  // disable encoding conversion of OGR Shapefile layer
280  CPLSetConfigOption( "SHAPE_ENCODING", "" );
281 
282  mLayer = OGR_DS_CreateLayer( mDS, TO8F( layerName ), ogrRef, wkbType, options );
283 
284  if ( options )
285  {
286  for ( int i = 0; i < layOptions.size(); i++ )
287  CPLFree( options[i] );
288  delete [] options;
289  options = NULL;
290  }
291 
292  QSettings settings;
293  if ( !settings.value( "/qgis/ignoreShapeEncoding", true ).toBool() )
294  {
295  CPLSetConfigOption( "SHAPE_ENCODING", 0 );
296  }
297 
298  if ( srs )
299  {
300  if ( ogrDriverName == "ESRI Shapefile" )
301  {
302  QString layerName = vectorFileName.left( vectorFileName.indexOf( ".shp", Qt::CaseInsensitive ) );
303  QFile prjFile( layerName + ".qpj" );
304  if ( prjFile.open( QIODevice::WriteOnly ) )
305  {
306  QTextStream prjStream( &prjFile );
307  prjStream << srs->toWkt().toLocal8Bit().data() << endl;
308  prjFile.close();
309  }
310  else
311  {
312  QgsDebugMsg( "Couldn't open file " + layerName + ".qpj" );
313  }
314  }
315 
316  OSRDestroySpatialReference( ogrRef );
317  }
318 
319  if ( mLayer == NULL )
320  {
321  mErrorMessage = QObject::tr( "creation of layer failed (OGR error:%1)" )
322  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
324  return;
325  }
326 
327  OGRFeatureDefnH defn = OGR_L_GetLayerDefn( mLayer );
328 
329  QgsDebugMsg( "created layer" );
330 
331  // create the fields
332  QgsDebugMsg( "creating " + QString::number( fields.size() ) + " fields" );
333 
334  mFields = fields;
335  mAttrIdxToOgrIdx.clear();
336 
337  for ( int fldIdx = 0; fldIdx < fields.count(); ++fldIdx )
338  {
339  const QgsField& attrField = fields[fldIdx];
340 
341  OGRFieldType ogrType = OFTString; //default to string
342  int ogrWidth = attrField.length();
343  int ogrPrecision = attrField.precision();
344  switch ( attrField.type() )
345  {
346  case QVariant::LongLong:
347  ogrType = OFTString;
348  ogrWidth = ogrWidth > 0 && ogrWidth <= 21 ? ogrWidth : 21;
349  ogrPrecision = -1;
350  break;
351 
352  case QVariant::String:
353  ogrType = OFTString;
354  if ( ogrWidth <= 0 || ogrWidth > 255 )
355  ogrWidth = 255;
356  break;
357 
358  case QVariant::Int:
359  ogrType = OFTInteger;
360  ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
361  ogrPrecision = 0;
362  break;
363 
364  case QVariant::Double:
365  ogrType = OFTReal;
366  break;
367 
368  case QVariant::Date:
369  ogrType = OFTDate;
370  break;
371 
372  case QVariant::DateTime:
373  ogrType = OFTDateTime;
374  break;
375 
376  default:
377  //assert(0 && "invalid variant type!");
378  mErrorMessage = QObject::tr( "unsupported type for field %1" )
379  .arg( attrField.name() );
381  return;
382  }
383 
384  QString name( attrField.name() );
385 
386  if ( ogrDriverName == "SQLite" && name.compare( "ogc_fid", Qt::CaseInsensitive ) == 0 )
387  {
388  int i;
389  for ( i = 0; i < 10; i++ )
390  {
391  name = QString( "ogc_fid%1" ).arg( i );
392 
393  int j;
394  for ( j = 0; j < fields.size() && name.compare( fields[j].name(), Qt::CaseInsensitive ) != 0; j++ )
395  ;
396 
397  if ( j == fields.size() )
398  break;
399  }
400 
401  if ( i == 10 )
402  {
403  mErrorMessage = QObject::tr( "no available replacement for internal fieldname ogc_fid found" ).arg( attrField.name() );
405  return;
406  }
407 
408  QgsMessageLog::logMessage( QObject::tr( "Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr( "OGR" ) );
409  }
410 
411  // create field definition
412  OGRFieldDefnH fld = OGR_Fld_Create( mCodec->fromUnicode( name ), ogrType );
413  if ( ogrWidth > 0 )
414  {
415  OGR_Fld_SetWidth( fld, ogrWidth );
416  }
417 
418  if ( ogrPrecision >= 0 )
419  {
420  OGR_Fld_SetPrecision( fld, ogrPrecision );
421  }
422 
423  // create the field
424  QgsDebugMsg( "creating field " + attrField.name() +
425  " type " + QString( QVariant::typeToName( attrField.type() ) ) +
426  " width " + QString::number( ogrWidth ) +
427  " precision " + QString::number( ogrPrecision ) );
428  if ( OGR_L_CreateField( mLayer, fld, true ) != OGRERR_NONE )
429  {
430  QgsDebugMsg( "error creating field " + attrField.name() );
431  mErrorMessage = QObject::tr( "creation of field %1 failed (OGR error: %2)" )
432  .arg( attrField.name() )
433  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
435  OGR_Fld_Destroy( fld );
436  return;
437  }
438  OGR_Fld_Destroy( fld );
439 
440  int ogrIdx = OGR_FD_GetFieldIndex( defn, mCodec->fromUnicode( name ) );
441  if ( ogrIdx < 0 )
442  {
443 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM < 1700
444  // if we didn't find our new column, assume it's name was truncated and
445  // it was the last one added (like for shape files)
446  int fieldCount = OGR_FD_GetFieldCount( defn );
447 
448  OGRFieldDefnH fdefn = OGR_FD_GetFieldDefn( defn, fieldCount - 1 );
449  if ( fdefn )
450  {
451  const char *fieldName = OGR_Fld_GetNameRef( fdefn );
452 
453  if ( attrField.name().left( strlen( fieldName ) ) == fieldName )
454  {
455  ogrIdx = fieldCount - 1;
456  }
457  }
458 #else
459  // GDAL 1.7 not just truncates, but launders more aggressivly.
460  ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
461 #endif
462 
463  if ( ogrIdx < 0 )
464  {
465  QgsDebugMsg( "error creating field " + attrField.name() );
466  mErrorMessage = QObject::tr( "created field %1 not found (OGR error: %2)" )
467  .arg( attrField.name() )
468  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
470  return;
471  }
472  }
473 
474  mAttrIdxToOgrIdx.insert( fldIdx, ogrIdx );
475  }
476 
477  QgsDebugMsg( "Done creating fields" );
478 
479  mWkbType = geometryType;
480  if ( mWkbType != QGis::WKBNoGeometry )
481  {
482  // create geometry which will be used for import
484  }
485 
486  if ( newFilename )
487  *newFilename = vectorFileName;
488 }
489 
491 {
492  return OGR_G_CreateGeometry(( OGRwkbGeometryType ) wkbType );
493 }
494 
495 QMap<QString, QgsVectorFileWriter::MetaData> QgsVectorFileWriter::initMetaData()
496 {
497  QMap<QString, MetaData> driverMetadata;
498 
499  QMap<QString, Option*> datasetOptions;
500  QMap<QString, Option*> layerOptions;
501 
502  // Arc/Info ASCII Coverage
503  datasetOptions.clear();
504  layerOptions.clear();
505 
506  driverMetadata.insert( "AVCE00",
507  MetaData(
508  "Arc/Info ASCII Coverage",
509  QObject::tr( "Arc/Info ASCII Coverage" ),
510  "*.e00",
511  "e00",
512  datasetOptions,
513  layerOptions
514  )
515  );
516 
517  // Atlas BNA
518  datasetOptions.clear();
519  layerOptions.clear();
520 
521  datasetOptions.insert( "LINEFORMAT", new SetOption(
522  QObject::tr( "New BNA files are created by the "
523  "systems default line termination conventions. "
524  "This may be overridden here." ),
525  QStringList()
526  << "CRLF"
527  << "LF",
528  "", // Default value
529  true // Allow None
530  ) );
531 
532  datasetOptions.insert( "MULTILINE", new BoolOption(
533  QObject::tr( "By default, BNA files are created in multi-line format. "
534  "For each record, the first line contains the identifiers and the "
535  "type/number of coordinates to follow. Each following line contains "
536  "a pair of coordinates." ),
537  true // Default value
538  ) );
539 
540  datasetOptions.insert( "NB_IDS", new SetOption(
541  QObject::tr( "BNA records may contain from 2 to 4 identifiers per record. "
542  "Some software packages only support a precise number of identifiers. "
543  "You can override the default value (2) by a precise value" ),
544  QStringList()
545  << "2"
546  << "3"
547  << "4"
548  << "NB_SOURCE_FIELDS",
549  "2" // Default value
550  ) );
551 
552  datasetOptions.insert( "ELLIPSES_AS_ELLIPSES", new BoolOption(
553  QObject::tr( "The BNA writer will try to recognize ellipses and circles when writing a polygon. "
554  "This will only work if the feature has previously been read from a BNA file. "
555  "As some software packages do not support ellipses/circles in BNA data file, "
556  "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
557  "to export them as such, but keep them as polygons." ),
558  true // Default value
559  ) );
560 
561  datasetOptions.insert( "NB_PAIRS_PER_LINE", new IntOption(
562  QObject::tr( "Limit the number of coordinate pairs per line in multiline format." ),
563  2 // Default value
564  ) );
565 
566  datasetOptions.insert( "COORDINATE_PRECISION", new IntOption(
567  QObject::tr( "Set the number of decimal for coordinates. Default value is 10." ),
568  10 // Default value
569  ) );
570 
571  driverMetadata.insert( "BNA",
572  MetaData(
573  "Atlas BNA",
574  QObject::tr( "Atlas BNA" ),
575  "*.bna",
576  "bna",
577  datasetOptions,
578  layerOptions
579  )
580  );
581 
582  // Comma Separated Value
583  datasetOptions.clear();
584  layerOptions.clear();
585 
586  layerOptions.insert( "LINEFORMAT", new SetOption(
587  QObject::tr( "By default when creating new .csv files they "
588  "are created with the line termination conventions "
589  "of the local platform (CR/LF on Win32 or LF on all other systems). "
590  "This may be overridden through the use of the LINEFORMAT option." ),
591  QStringList()
592  << "CRLF"
593  << "LF",
594  "", // Default value
595  true // Allow None
596  ) );
597 
598  layerOptions.insert( "GEOMETRY", new SetOption(
599  QObject::tr( "By default, the geometry of a feature written to a .csv file is discarded. "
600  "It is possible to export the geometry in its WKT representation by "
601  "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
602  "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
603  "or GEOMETRY=AS_YX." ),
604  QStringList()
605  << "AS_WKT"
606  << "AS_XYZ"
607  << "AS_XY"
608  << "AS_YX",
609  "AS_XY", // Default value
610  true // Allow None
611  ) );
612 
613  layerOptions.insert( "CREATE_CSVT", new BoolOption(
614  QObject::tr( "Create the associated .csvt file to describe the type of each "
615  "column of the layer and its optional width and precision." ),
616  false // Default value
617  ) );
618 
619  layerOptions.insert( "SEPARATOR", new SetOption(
620  QObject::tr( "Field separator character." ),
621  QStringList()
622  << "COMMA"
623  << "SEMICOLON"
624  << "TAB",
625  "COMMA" // Default value
626  ) );
627 
628  layerOptions.insert( "WRITE_BOM", new BoolOption(
629  QObject::tr( "Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
630  false // Default value
631  ) );
632 
633  driverMetadata.insert( "CSV",
634  MetaData(
635  "Comma Separated Value [CSV]",
636  QObject::tr( "Comma Separated Value [CSV]" ),
637  "*.csv",
638  "csv",
639  datasetOptions,
640  layerOptions
641  )
642  );
643 
644  // ESRI Shapefile
645  datasetOptions.clear();
646  layerOptions.clear();
647 
648  layerOptions.insert( "SHPT", new SetOption(
649  QObject::tr( "Override the type of shapefile created. "
650  "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
651  "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
652  "MULTIPOINTZ for 3D. Shapefiles with measure values are not supported, "
653  "nor are MULTIPATCH files." ),
654  QStringList()
655  << "NULL"
656  << "POINT"
657  << "ARC"
658  << "POLYGON"
659  << "MULTIPOINT"
660  << "POINTZ"
661  << "ARCZ"
662  << "POLYGONZ"
663  << "MULTIPOINTZ",
664  "NULL" // Default value
665  ) );
666 
667  layerOptions.insert( "ENCODING", new SetOption(
668  QObject::tr( "set the encoding value in the DBF file. "
669  "The default value is LDID/87. It is not clear "
670  "what other values may be appropriate." ),
671  QStringList()
672  << "LDID/87",
673  "LDID/87" // Default value
674  ) );
675 
676  layerOptions.insert( "RESIZE", new BoolOption(
677  QObject::tr( "Set to YES to resize fields to their optimal size." ),
678  false // Default value
679  ) );
680 
681  driverMetadata.insert( "ESRI",
682  MetaData(
683  "ESRI Shapefile",
684  QObject::tr( "ESRI Shapefile" ),
685  "*.shp",
686  "shp",
687  datasetOptions,
688  layerOptions
689  )
690  );
691 
692  // DBF File
693  datasetOptions.clear();
694  layerOptions.clear();
695 
696  driverMetadata.insert( "DBF File",
697  MetaData(
698  "DBF File",
699  QObject::tr( "DBF File" ),
700  "*.dbf",
701  "dbf",
702  datasetOptions,
703  layerOptions
704  )
705  );
706 
707  // FMEObjects Gateway
708  datasetOptions.clear();
709  layerOptions.clear();
710 
711  driverMetadata.insert( "FMEObjects Gateway",
712  MetaData(
713  "FMEObjects Gateway",
714  QObject::tr( "FMEObjects Gateway" ),
715  "*.fdd",
716  "fdd",
717  datasetOptions,
718  layerOptions
719  )
720  );
721 
722  // GeoJSON
723  datasetOptions.clear();
724  layerOptions.clear();
725 
726  layerOptions.insert( "WRITE_BBOX", new BoolOption(
727  QObject::tr( "Set to YES to write a bbox property with the bounding box "
728  "of the geometries at the feature and feature collection level." ),
729  false // Default value
730  ) );
731 
732  layerOptions.insert( "COORDINATE_PRECISION", new IntOption(
733  QObject::tr( "Maximum number of figures after decimal separator to write in coordinates. "
734  "Default to 15. Truncation will occur to remove trailing zeros." ),
735  15 // Default value
736  ) );
737 
738  driverMetadata.insert( "GeoJSON",
739  MetaData(
740  "GeoJSON",
741  QObject::tr( "GeoJSON" ),
742  "*.geojson",
743  "geojson",
744  datasetOptions,
745  layerOptions
746  )
747  );
748 
749  // GeoRSS
750  datasetOptions.clear();
751  layerOptions.clear();
752 
753  datasetOptions.insert( "FORMAT", new SetOption(
754  QObject::tr( "whether the document must be in RSS 2.0 or Atom 1.0 format. "
755  "Default value : RSS" ),
756  QStringList()
757  << "RSS"
758  << "ATOM",
759  "RSS" // Default value
760  ) );
761 
762  datasetOptions.insert( "GEOM_DIALECT", new SetOption(
763  QObject::tr( "The encoding of location information. Default value : SIMPLE. "
764  "W3C_GEO only supports point geometries. "
765  "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
766  QStringList()
767  << "SIMPLE"
768  << "GML"
769  << "W3C_GEO",
770  "SIMPLE" // Default value
771  ) );
772 
773  datasetOptions.insert( "USE_EXTENSIONS", new BoolOption(
774  QObject::tr( "If defined to YES, extension fields will be written. "
775  "If the field name not found in the base schema matches "
776  "the foo_bar pattern, foo will be considered as the namespace "
777  "of the element, and a <foo:bar> element will be written. "
778  "Otherwise, elements will be written in the <ogr:> namespace." ),
779  true // Default value
780  ) );
781 
782  datasetOptions.insert( "WRITE_HEADER_AND_FOOTER", new BoolOption(
783  QObject::tr( "If defined to NO, only <entry> or <item> elements will be written. "
784  "The user will have to provide the appropriate header and footer of the document." ),
785  true // Default value
786  ) );
787 
788  datasetOptions.insert( "HEADER", new StringOption(
789  QObject::tr( "XML content that will be put between the <channel> element and the "
790  "first <item> element for a RSS document, or between the xml tag and "
791  "the first <entry> element for an Atom document. " ),
792  "" // Default value
793  ) );
794 
795  datasetOptions.insert( "TITLE", new StringOption(
796  QObject::tr( "Value put inside the <title> element in the header. "
797  "If not provided, a dummy value will be used as that element is compulsory." ),
798  "" // Default value
799  ) );
800 
801  datasetOptions.insert( "DESCRIPTION", new StringOption(
802  QObject::tr( "Value put inside the <description> element in the header. "
803  "If not provided, a dummy value will be used as that element is compulsory." ),
804  "" // Default value
805  ) );
806 
807  datasetOptions.insert( "LINK", new StringOption(
808  QObject::tr( "Value put inside the <link> element in the header. "
809  "If not provided, a dummy value will be used as that element is compulsory." ),
810  "" // Default value
811  ) );
812 
813  datasetOptions.insert( "UPDATED", new StringOption(
814  QObject::tr( "Value put inside the <updated> element in the header. "
815  "Should be formatted as a XML datetime. "
816  "If not provided, a dummy value will be used as that element is compulsory." ),
817  "" // Default value
818  ) );
819 
820  datasetOptions.insert( "AUTHOR_NAME", new StringOption(
821  QObject::tr( "Value put inside the <author><name> element in the header. "
822  "If not provided, a dummy value will be used as that element is compulsory." ),
823  "" // Default value
824  ) );
825 
826  datasetOptions.insert( "ID", new StringOption(
827  QObject::tr( "Value put inside the <id> element in the header. "
828  "If not provided, a dummy value will be used as that element is compulsory." ),
829  "" // Default value
830  ) );
831 
832  driverMetadata.insert( "GeoRSS",
833  MetaData(
834  "GeoRSS",
835  QObject::tr( "GeoRSS" ),
836  "*.xml",
837  "xml",
838  datasetOptions,
839  layerOptions
840  )
841  );
842 
843  // Geography Markup Language [GML]
844  datasetOptions.clear();
845  layerOptions.clear();
846 
847  datasetOptions.insert( "XSISCHEMAURI", new StringOption(
848  QObject::tr( "If provided, this URI will be inserted as the schema location. "
849  "Note that the schema file isn't actually accessed by OGR, so it "
850  "is up to the user to ensure it will match the schema of the OGR "
851  "produced GML data file." ),
852  "" // Default value
853  ) );
854 
855  datasetOptions.insert( "XSISCHEMA", new SetOption(
856  QObject::tr( "This writes a GML application schema file to a corresponding "
857  ".xsd file (with the same basename). If INTERNAL is used the "
858  "schema is written within the GML file, but this is experimental "
859  "and almost certainly not valid XML. "
860  "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
861  QStringList()
862  << "EXTERNAL"
863  << "INTERNAL"
864  << "OFF",
865  "EXTERNAL" // Default value
866  ) );
867 
868  datasetOptions.insert( "PREFIX", new StringOption(
869  QObject::tr( "This is the prefix for the application target namespace." ),
870  "ogr" // Default value
871  ) );
872 
873  datasetOptions.insert( "STRIP_PREFIX", new BoolOption(
874  QObject::tr( "Can be set to TRUE to avoid writing the prefix of the "
875  "application target namespace in the GML file." ),
876  false // Default value
877  ) );
878 
879  datasetOptions.insert( "TARGET_NAMESPACE", new StringOption(
880  QObject::tr( "Defaults to 'http://ogr.maptools.org/'. "
881  "This is the application target namespace." ),
882  "http://ogr.maptools.org/" // Default value
883  ) );
884 
885  datasetOptions.insert( "FORMAT", new SetOption(
886  QObject::tr( "If not specified, GML2 will be used." ),
887  QStringList()
888  << "GML3"
889  << "GML3Deegree"
890  << "GML3.2",
891  "", // Default value
892  true // Allow None
893  ) );
894 
895  datasetOptions.insert( "GML3_LONGSRS", new BoolOption(
896  QObject::tr( "only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
897  "If YES, SRS with EPSG authority will be written with the "
898  "'urn:ogc:def:crs:EPSG::' prefix. In the case, if the SRS is a "
899  "geographic SRS without explicit AXIS order, but that the same "
900  "SRS authority code imported with ImportFromEPSGA() should be "
901  "treated as lat/long, then the function will take care of coordinate "
902  "order swapping. If set to NO, SRS with EPSG authority will be "
903  "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
904  true // Default value
905  ) );
906 
907  datasetOptions.insert( "WRITE_FEATURE_BOUNDED_BY", new BoolOption(
908  QObject::tr( "only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
909  "If set to NO, the <gml:boundedBy> element will not be written for "
910  "each feature." ),
911  true // Default value
912  ) );
913 
914  datasetOptions.insert( "SPACE_INDENTATION", new BoolOption(
915  QObject::tr( "Default to YES. If YES, the output will be indented with spaces "
916  "for more readability, but at the expense of file size." ),
917  true // Default value
918  ) );
919 
920 
921  driverMetadata.insert( "GML",
922  MetaData(
923  "Geography Markup Language [GML]",
924  QObject::tr( "Geography Markup Language [GML]" ),
925  "*.gml",
926  "gml",
927  datasetOptions,
928  layerOptions
929  )
930  );
931 
932  // Generic Mapping Tools [GMT]
933  datasetOptions.clear();
934  layerOptions.clear();
935 
936  driverMetadata.insert( "GMT",
937  MetaData(
938  "Generic Mapping Tools [GMT]",
939  QObject::tr( "Generic Mapping Tools [GMT]" ),
940  "*.gmt",
941  "gmt",
942  datasetOptions,
943  layerOptions
944  )
945  );
946 
947  // GPS eXchange Format [GPX]
948  datasetOptions.clear();
949  layerOptions.clear();
950 
951  layerOptions.insert( "FORCE_GPX_TRACK", new BoolOption(
952  QObject::tr( "By default when writing a layer whose features are of "
953  "type wkbLineString, the GPX driver chooses to write "
954  "them as routes. If FORCE_GPX_TRACK=YES is specified, "
955  "they will be written as tracks." ),
956  false // Default value
957  ) );
958 
959  layerOptions.insert( "FORCE_GPX_ROUTE", new BoolOption(
960  QObject::tr( "By default when writing a layer whose features are of "
961  "type wkbMultiLineString, the GPX driver chooses to write "
962  "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
963  "they will be written as routes, provided that the multilines "
964  "are composed of only one single line." ),
965  false // Default value
966  ) );
967 
968  datasetOptions.insert( "GPX_USE_EXTENSIONS", new BoolOption(
969  QObject::tr( "If GPX_USE_EXTENSIONS=YES is specified, "
970  "extra fields will be written inside the <extensions> tag." ),
971  true // Default value
972  ) );
973 
974  datasetOptions.insert( "GPX_EXTENSIONS_NS", new StringOption(
975  QObject::tr( "Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
976  "is set. The namespace value used for extension tags. By default, 'ogr'." ),
977  "ogr" // Default value
978  ) );
979 
980  datasetOptions.insert( "GPX_EXTENSIONS_NS_URL", new StringOption(
981  QObject::tr( "Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
982  "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
983  "http://osgeo.org/gdal" // Default value
984  ) );
985 
986  datasetOptions.insert( "LINEFORMAT", new SetOption(
987  QObject::tr( "By default files are created with the line termination "
988  "conventions of the local platform (CR/LF on win32 or LF "
989  "on all other systems). This may be overridden through use "
990  "of the LINEFORMAT layer creation option which may have a value "
991  "of CRLF (DOS format) or LF (Unix format)." ),
992  QStringList()
993  << "CRLF"
994  << "LF",
995  "", // Default value
996  true // Allow None
997  ) );
998 
999  driverMetadata.insert( "GPX",
1000  MetaData(
1001  "GPS eXchange Format [GPX]",
1002  QObject::tr( "GPS eXchange Format [GPX]" ),
1003  "*.gpx",
1004  "gpx",
1005  datasetOptions,
1006  layerOptions
1007  )
1008  );
1009 
1010  // INTERLIS 1
1011  datasetOptions.clear();
1012  layerOptions.clear();
1013 
1014  driverMetadata.insert( "Interlis 1",
1015  MetaData(
1016  "INTERLIS 1",
1017  QObject::tr( "INTERLIS 1" ),
1018  "*.itf *.xml *.ili",
1019  "ili",
1020  datasetOptions,
1021  layerOptions
1022  )
1023  );
1024 
1025  // INTERLIS 2
1026  datasetOptions.clear();
1027  layerOptions.clear();
1028 
1029  driverMetadata.insert( "Interlis 2",
1030  MetaData(
1031  "INTERLIS 2",
1032  QObject::tr( "INTERLIS 2" ),
1033  "*.itf *.xml *.ili",
1034  "ili",
1035  datasetOptions,
1036  layerOptions
1037  )
1038  );
1039 
1040  // Keyhole Markup Language [KML]
1041  datasetOptions.clear();
1042  layerOptions.clear();
1043 
1044  datasetOptions.insert( "NameField", new StringOption(
1045  QObject::tr( "Allows you to specify the field to use for the KML <name> element. " ),
1046  "Name" // Default value
1047  ) );
1048 
1049  datasetOptions.insert( "DescriptionField", new StringOption(
1050  QObject::tr( "Allows you to specify the field to use for the KML <description> element." ),
1051  "Description" // Default value
1052  ) );
1053 
1054  datasetOptions.insert( "AltitudeMode", new SetOption(
1055  QObject::tr( "Allows you to specify the AltitudeMode to use for KML geometries. "
1056  "This will only affect 3D geometries and must be one of the valid KML options." ),
1057  QStringList()
1058  << "relativeToGround"
1059  << "clampToGround"
1060  << "absolute",
1061  "relativeToGround" // Default value
1062  ) );
1063 
1064  driverMetadata.insert( "KML",
1065  MetaData(
1066  "Keyhole Markup Language [KML]",
1067  QObject::tr( "Keyhole Markup Language [KML]" ),
1068  "*.kml",
1069  "kml",
1070  datasetOptions,
1071  layerOptions
1072  )
1073  );
1074 
1075  // Mapinfo
1076  datasetOptions.clear();
1077  layerOptions.clear();
1078 
1079  layerOptions.insert( "SPATIAL_INDEX_MODE", new SetOption(
1080  QObject::tr( "Use this to turn on 'quick spatial index mode'. "
1081  "In this mode writing files can be about 5 times faster, "
1082  "but spatial queries can be up to 30 times slower." ),
1083  QStringList()
1084  << "QUICK",
1085  "", // Default value
1086  true // Allow None
1087  ) );
1088 
1089  driverMetadata.insert( "MapInfo File",
1090  MetaData(
1091  "Mapinfo",
1092  QObject::tr( "Mapinfo TAB" ),
1093  "*.tab",
1094  "tab",
1095  datasetOptions,
1096  layerOptions
1097  )
1098  );
1099 
1100  // QGIS internal alias for MIF files
1101  driverMetadata.insert( "MapInfo MIF",
1102  MetaData(
1103  "Mapinfo",
1104  QObject::tr( "Mapinfo MIF" ),
1105  "*.mif",
1106  "mif",
1107  datasetOptions,
1108  layerOptions
1109  )
1110  );
1111 
1112  // Microstation DGN
1113  datasetOptions.clear();
1114  layerOptions.clear();
1115 
1116  datasetOptions.insert( "3D", new BoolOption(
1117  QObject::tr( "Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1118  "seed file should be used. This option is ignored if the SEED option is provided." ),
1119  false // Default value
1120  ) );
1121 
1122  datasetOptions.insert( "SEED", new StringOption(
1123  QObject::tr( "Override the seed file to use." ),
1124  "" // Default value
1125  ) );
1126 
1127  datasetOptions.insert( "COPY_WHOLE_SEED_FILE", new BoolOption(
1128  QObject::tr( "Indicate whether the whole seed file should be copied. "
1129  "If not, only the first three elements will be copied." ),
1130  false // Default value
1131  ) );
1132 
1133  datasetOptions.insert( "COPY_SEED_FILE_COLOR_TABLEE", new BoolOption(
1134  QObject::tr( "Indicates whether the color table should be copied from the seed file." ),
1135  false // Default value
1136  ) );
1137 
1138  datasetOptions.insert( "MASTER_UNIT_NAME", new StringOption(
1139  QObject::tr( "Override the master unit name from the seed file with "
1140  "the provided one or two character unit name." ),
1141  "" // Default value
1142  ) );
1143 
1144  datasetOptions.insert( "SUB_UNIT_NAME", new StringOption(
1145  QObject::tr( "Override the sub unit name from the seed file with the provided "
1146  "one or two character unit name." ),
1147  "" // Default value
1148  ) );
1149 
1150  datasetOptions.insert( "SUB_UNITS_PER_MASTER_UNIT", new IntOption(
1151  QObject::tr( "Override the number of subunits per master unit. "
1152  "By default the seed file value is used." ),
1153  0 // Default value
1154  ) );
1155 
1156  datasetOptions.insert( "UOR_PER_SUB_UNIT", new IntOption(
1157  QObject::tr( "Override the number of UORs (Units of Resolution) "
1158  "per sub unit. By default the seed file value is used." ),
1159  0 // Default value
1160  ) );
1161 
1162  datasetOptions.insert( "ORIGIN", new StringOption(
1163  QObject::tr( "ORIGIN=x,y,z: Override the origin of the design plane. "
1164  "By default the origin from the seed file is used." ),
1165  "" // Default value
1166  ) );
1167 
1168  driverMetadata.insert( "DGN",
1169  MetaData(
1170  "Microstation DGN",
1171  QObject::tr( "Microstation DGN" ),
1172  "*.dgn",
1173  "dgn",
1174  datasetOptions,
1175  layerOptions
1176  )
1177  );
1178 
1179  // Microstation DGN
1180  datasetOptions.clear();
1181  layerOptions.clear();
1182 
1183  driverMetadata.insert( "DGN",
1184  MetaData(
1185  "Microstation DGN",
1186  QObject::tr( "Microstation DGN" ),
1187  "*.dgn",
1188  "dgn",
1189  datasetOptions,
1190  layerOptions
1191  )
1192  );
1193 
1194  // S-57 Base file
1195  datasetOptions.clear();
1196  layerOptions.clear();
1197 
1198  datasetOptions.insert( "UPDATES", new SetOption(
1199  QObject::tr( "Should update files be incorporated into the base data on the fly. " ),
1200  QStringList()
1201  << "APPLY"
1202  << "IGNORE",
1203  "APPLY" // Default value
1204  ) );
1205 
1206  datasetOptions.insert( "SPLIT_MULTIPOINT", new BoolOption(
1207  QObject::tr( "Should multipoint soundings be split into many single point sounding features. "
1208  "Multipoint geometries are not well handled by many formats, "
1209  "so it can be convenient to split single sounding features with many points "
1210  "into many single point features." ),
1211  false // Default value
1212  ) );
1213 
1214  datasetOptions.insert( "ADD_SOUNDG_DEPTH", new BoolOption(
1215  QObject::tr( "Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1216  "of the sounding. This should only be enabled with SPLIT_MULTIPOINT is "
1217  "also enabled." ),
1218  false // Default value
1219  ) );
1220 
1221  datasetOptions.insert( "RETURN_PRIMITIVES", new BoolOption(
1222  QObject::tr( "Should all the low level geometry primitives be returned as special "
1223  "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1224  true // Default value
1225  ) );
1226 
1227  datasetOptions.insert( "PRESERVE_EMPTY_NUMBERS", new BoolOption(
1228  QObject::tr( "If enabled, numeric attributes assigned an empty string as a value will "
1229  "be preserved as a special numeric value. This option should not generally "
1230  "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1231  false // Default value
1232  ) );
1233 
1234  datasetOptions.insert( "LNAM_REFS", new BoolOption(
1235  QObject::tr( "Should LNAM and LNAM_REFS fields be attached to features capturing "
1236  "the feature to feature relationships in the FFPT group of the S-57 file." ),
1237  true // Default value
1238  ) );
1239 
1240  datasetOptions.insert( "RETURN_LINKAGES", new BoolOption(
1241  QObject::tr( "Should additional attributes relating features to their underlying "
1242  "geometric primitives be attached. These are the values of the FSPT group, "
1243  "and are primarily needed when doing S-57 to S-57 translations." ),
1244  true // Default value
1245  ) );
1246 
1247  datasetOptions.insert( "RECODE_BY_DSSI", new BoolOption(
1248  QObject::tr( "Should attribute values be recoded to UTF-8 from the character encoding "
1249  "specified in the S57 DSSI record." ),
1250  false // Default value
1251  ) );
1252 
1253  // set OGR_S57_OPTIONS = "RETURN_PRIMITIVES=ON,RETURN_LINKAGES=ON,LNAM_REFS=ON"
1254 
1255  driverMetadata.insert( "S57",
1256  MetaData(
1257  "S-57 Base file",
1258  QObject::tr( "S-57 Base file" ),
1259  "*.000",
1260  "000",
1261  datasetOptions,
1262  layerOptions
1263  )
1264  );
1265 
1266  // Spatial Data Transfer Standard [SDTS]
1267  datasetOptions.clear();
1268  layerOptions.clear();
1269 
1270  driverMetadata.insert( "SDTS",
1271  MetaData(
1272  "Spatial Data Transfer Standard [SDTS]",
1273  QObject::tr( "Spatial Data Transfer Standard [SDTS]" ),
1274  "*catd.ddf",
1275  "ddf",
1276  datasetOptions,
1277  layerOptions
1278  )
1279  );
1280 
1281  // SQLite
1282  datasetOptions.clear();
1283  layerOptions.clear();
1284 
1285  datasetOptions.insert( "METADATA", new BoolOption(
1286  QObject::tr( "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1287  "tables in a new database. By default these metadata tables are created "
1288  "when a new database is created." ),
1289  true // Default value
1290  ) );
1291 
1292  // Will handle the spatialite alias
1293  datasetOptions.insert( "SPATIALITE", new HiddenOption(
1294  "NO"
1295  ) );
1296 
1297 
1298  datasetOptions.insert( "INIT_WITH_EPSG", new HiddenOption(
1299  "NO"
1300  ) );
1301 
1302  layerOptions.insert( "FORMAT", new SetOption(
1303  QObject::tr( "Controls the format used for the geometry column. Defaults to WKB."
1304  "This is generally more space and processing efficient, but harder "
1305  "to inspect or use in simple applications than WKT (Well Known Text)." ),
1306  QStringList()
1307  << "WKB"
1308  << "WKT",
1309  "WKB" // Default value
1310  ) );
1311 
1312  layerOptions.insert( "LAUNDER", new BoolOption(
1313  QObject::tr( "Controls whether layer and field names will be laundered for easier use "
1314  "in SQLite. Laundered names will be converted to lower case and some special "
1315  "characters(' - #) will be changed to underscores." ),
1316  true // Default value
1317  ) );
1318 
1319  layerOptions.insert( "SPATIAL_INDEX", new HiddenOption(
1320  "NO"
1321  ) );
1322 
1323  layerOptions.insert( "COMPRESS_GEOM", new HiddenOption(
1324  "NO"
1325  ) );
1326 
1327  layerOptions.insert( "SRID", new HiddenOption(
1328  ""
1329  ) );
1330 
1331  layerOptions.insert( "COMPRESS_COLUMNS", new StringOption(
1332  QObject::tr( "column_name1[,column_name2, ...] A list of (String) columns that "
1333  "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1334  "for databases that have big string blobs. However, use with care, since "
1335  "the value of such columns will be seen as compressed binary content with "
1336  "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1337  "modifying or queryings compressed columns, compression/decompression is "
1338  "done transparently. However, such columns cannot be (easily) queried with "
1339  "an attribute filter or WHERE clause. Note: in table definition, such columns "
1340  "have the 'VARCHAR_deflate' declaration type." ),
1341  "" // Default value
1342  ) );
1343 
1344  driverMetadata.insert( "SQLite",
1345  MetaData(
1346  "SQLite",
1347  QObject::tr( "SQLite" ),
1348  "*.sqlite",
1349  "sqlite",
1350  datasetOptions,
1351  layerOptions
1352  )
1353  );
1354 
1355  // SpatiaLite
1356  datasetOptions.clear();
1357  layerOptions.clear();
1358 
1359  datasetOptions.insert( "METADATA", new BoolOption(
1360  QObject::tr( "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1361  "tables in a new database. By default these metadata tables are created "
1362  "when a new database is created." ),
1363  true // Default value
1364  ) );
1365 
1366  datasetOptions.insert( "SPATIALITE", new HiddenOption(
1367  "YES"
1368  ) );
1369 
1370  datasetOptions.insert( "INIT_WITH_EPSG", new BoolOption(
1371  QObject::tr( "Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1372  "Set to NO for regular SQLite databases." ),
1373  true // Default value
1374  ) );
1375 
1376  layerOptions.insert( "FORMAT", new HiddenOption(
1377  "SPATIALITE"
1378  ) );
1379 
1380  layerOptions.insert( "LAUNDER", new BoolOption(
1381  QObject::tr( "Controls whether layer and field names will be laundered for easier use "
1382  "in SQLite. Laundered names will be convered to lower case and some special "
1383  "characters(' - #) will be changed to underscores." ),
1384  true // Default value
1385  ) );
1386 
1387  layerOptions.insert( "SPATIAL_INDEX", new BoolOption(
1388  QObject::tr( "If the database is of the SpatiaLite flavour, and if OGR is linked "
1389  "against libspatialite, this option can be used to control if a spatial "
1390  "index must be created." ),
1391  true // Default value
1392  ) );
1393 
1394  layerOptions.insert( "COMPRESS_GEOM", new BoolOption(
1395  QObject::tr( "If the format of the geometry BLOB is of the SpatiaLite flavour, "
1396  "this option can be used to control if the compressed format for "
1397  "geometries (LINESTRINGs, POLYGONs) must be used" ),
1398  false // Default value
1399  ) );
1400 
1401  layerOptions.insert( "SRID", new StringOption(
1402  QObject::tr( "Used to force the SRID number of the SRS associated with the layer. "
1403  "When this option isn't specified and that a SRS is associated with the "
1404  "layer, a search is made in the spatial_ref_sys to find a match for the "
1405  "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1406  "the spatial_ref_sys table. When the SRID option is specified, this "
1407  "search (and the eventual insertion of a new entry) will not be done: "
1408  "the specified SRID is used as such." ),
1409  "" // Default value
1410  ) );
1411 
1412  layerOptions.insert( "COMPRESS_COLUMNS", new StringOption(
1413  QObject::tr( "column_name1[,column_name2, ...] A list of (String) columns that "
1414  "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1415  "for databases that have big string blobs. However, use with care, since "
1416  "the value of such columns will be seen as compressed binary content with "
1417  "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1418  "modifying or queryings compressed columns, compression/decompression is "
1419  "done transparently. However, such columns cannot be (easily) queried with "
1420  "an attribute filter or WHERE clause. Note: in table definition, such columns "
1421  "have the 'VARCHAR_deflate' declaration type." ),
1422  "" // Default value
1423  ) );
1424 
1425  driverMetadata.insert( "SpatiaLite",
1426  MetaData(
1427  "SpatiaLite",
1428  QObject::tr( "SpatiaLite" ),
1429  "*.sqlite",
1430  "sqlite",
1431  datasetOptions,
1432  layerOptions
1433  )
1434  );
1435  // AutoCAD DXF
1436  datasetOptions.clear();
1437  layerOptions.clear();
1438 
1439 #if 0
1440 // datasetOptions.insert( "HEADER", new StringOption(
1441  QObject::tr( "Override the header file used - in place of header.dxf." ),
1442  "" // Default value
1443  ) );
1444 
1445  datasetOptions.insert( "TRAILER", new StringOption(
1446  QObject::tr( "Override the trailer file used - in place of trailer.dxf." ),
1447  "" // Default value
1448  ) );
1449 #endif
1450 
1451  driverMetadata.insert( "DXF",
1452  MetaData(
1453  "AutoCAD DXF",
1454  QObject::tr( "AutoCAD DXF" ),
1455  "*.dxf",
1456  "dxf",
1457  datasetOptions,
1458  layerOptions
1459  )
1460  );
1461 
1462  // Geoconcept
1463  datasetOptions.clear();
1464  layerOptions.clear();
1465 
1466  datasetOptions.insert( "EXTENSION", new SetOption(
1467  QObject::tr( "Indicates the GeoConcept export file extension. "
1468  "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
1469  QStringList()
1470  << "GXT"
1471  << "TXT",
1472  "GXT" // Default value
1473  ) );
1474 
1475 #if 0
1476  datasetOptions.insert( "CONFIG", new StringOption(
1477  QObject::tr( "path to the GCT : the GCT file describe the GeoConcept types definitions: "
1478  "In this file, every line must start with //# followed by a keyword. "
1479  "Lines starting with // are comments." ),
1480  "" // Default value
1481  ) );
1482 #endif
1483 
1484  driverMetadata.insert( "Geoconcept",
1485  MetaData(
1486  "Geoconcept",
1487  QObject::tr( "Geoconcept" ),
1488  "*.gxt *.txt",
1489  "gxt",
1490  datasetOptions,
1491  layerOptions
1492  )
1493  );
1494 
1495  // ESRI FileGDB
1496  datasetOptions.clear();
1497  layerOptions.clear();
1498 
1499  layerOptions.insert( "FEATURE_DATASET", new StringOption(
1500  QObject::tr( "When this option is set, the new layer will be created inside the named "
1501  "FeatureDataset folder. If the folder does not already exist, it will be created." ),
1502  "" // Default value
1503  ) );
1504 
1505  layerOptions.insert( "GEOMETRY_NAME", new StringOption(
1506  QObject::tr( "Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
1507  "SHAPE" // Default value
1508  ) );
1509 
1510  layerOptions.insert( "OID_NAME", new StringOption(
1511  QObject::tr( "Name of the OID column to create. Defaults to 'OBJECTID'." ),
1512  "OBJECTID" // Default value
1513  ) );
1514 
1515  driverMetadata.insert( "FileGDB",
1516  MetaData(
1517  "ESRI FileGDB",
1518  QObject::tr( "ESRI FileGDB" ),
1519  "*.gdb",
1520  "gdb",
1521  datasetOptions,
1522  layerOptions
1523  )
1524  );
1525  return driverMetadata;
1526  }
1527 
1528  bool QgsVectorFileWriter::driverMetadata( const QString& driverName, QgsVectorFileWriter::MetaData& driverMetadata )
1529 {
1530  static const QMap<QString, MetaData> sDriverMetadata = initMetaData();
1531 
1532  QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.constBegin();
1533 
1534  for ( ; it != sDriverMetadata.constEnd(); ++it )
1535  {
1536  if ( it.key().startsWith( driverName ) )
1537  {
1538  driverMetadata = it.value();
1539  return true;
1540  }
1541  }
1542 
1543  return false;
1544 }
1545 
1546 
1548 {
1549  return mError;
1550 }
1551 
1553 {
1554  return mErrorMessage;
1555 }
1556 
1558 {
1559  // create the feature
1560  OGRFeatureH poFeature = createFeature( feature );
1561  if ( !poFeature )
1562  return false;
1563 
1564  //add OGR feature style type
1565  if ( mSymbologyExport != NoSymbology && renderer )
1566  {
1567  //SymbolLayerSymbology: concatenate ogr styles of all symbollayers
1568  QgsSymbolV2List symbols = renderer->symbolsForFeature( feature );
1569  QString styleString;
1570  QString currentStyle;
1571 
1572  QgsSymbolV2List::const_iterator symbolIt = symbols.constBegin();
1573  for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
1574  {
1575  int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
1576  for ( int i = 0; i < nSymbolLayers; ++i )
1577  {
1578 #if 0
1579  QMap< QgsSymbolLayerV2*, QString >::const_iterator it = mSymbolLayerTable.find(( *symbolIt )->symbolLayer( i ) );
1580  if ( it == mSymbolLayerTable.constEnd() )
1581  {
1582  continue;
1583  }
1584 #endif
1585  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
1586  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
1587 
1588  currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );//"@" + it.value();
1589 
1591  {
1592  if ( symbolIt != symbols.constBegin() || i != 0 )
1593  {
1594  styleString.append( ";" );
1595  }
1596  styleString.append( currentStyle );
1597  }
1598  else if ( mSymbologyExport == SymbolLayerSymbology )
1599  {
1600  OGR_F_SetStyleString( poFeature, currentStyle.toLocal8Bit().data() );
1601  if ( !writeFeature( mLayer, poFeature ) )
1602  {
1603  return false;
1604  }
1605  }
1606  }
1607  }
1608  OGR_F_SetStyleString( poFeature, styleString.toLocal8Bit().data() );
1609  }
1610 
1612  {
1613  if ( !writeFeature( mLayer, poFeature ) )
1614  {
1615  return false;
1616  }
1617  }
1618 
1619  OGR_F_Destroy( poFeature );
1620  return true;
1621 }
1622 
1623 OGRFeatureH QgsVectorFileWriter::createFeature( QgsFeature& feature )
1624 {
1625  OGRFeatureH poFeature = OGR_F_Create( OGR_L_GetLayerDefn( mLayer ) );
1626 
1627  qint64 fid = FID_TO_NUMBER( feature.id() );
1628  if ( fid > std::numeric_limits<int>::max() )
1629  {
1630  QgsDebugMsg( QString( "feature id %1 too large." ).arg( fid ) );
1631  OGRErr err = OGR_F_SetFID( poFeature, static_cast<long>( fid ) );
1632  if ( err != OGRERR_NONE )
1633  {
1634  QgsDebugMsg( QString( "Failed to set feature id to %1: %2 (OGR error: %3)" )
1635  .arg( feature.id() )
1636  .arg( err ).arg( CPLGetLastErrorMsg() )
1637  );
1638  }
1639  }
1640 
1641  // attribute handling
1642  for ( int fldIdx = 0; fldIdx < mFields.count(); ++fldIdx )
1643  {
1644  if ( !mAttrIdxToOgrIdx.contains( fldIdx ) )
1645  {
1646  QgsDebugMsg( QString( "no ogr field for field %1" ).arg( fldIdx ) );
1647  continue;
1648  }
1649 
1650  const QVariant& attrValue = feature.attribute( fldIdx );
1651  int ogrField = mAttrIdxToOgrIdx[ fldIdx ];
1652 
1653  if ( !attrValue.isValid() || attrValue.isNull() )
1654  continue;
1655 
1656  switch ( attrValue.type() )
1657  {
1658  case QVariant::Int:
1659  OGR_F_SetFieldInteger( poFeature, ogrField, attrValue.toInt() );
1660  break;
1661  case QVariant::Double:
1662  OGR_F_SetFieldDouble( poFeature, ogrField, attrValue.toDouble() );
1663  break;
1664  case QVariant::LongLong:
1665  case QVariant::String:
1666  OGR_F_SetFieldString( poFeature, ogrField, mCodec->fromUnicode( attrValue.toString() ).data() );
1667  break;
1668  case QVariant::Date:
1669  OGR_F_SetFieldDateTime( poFeature, ogrField,
1670  attrValue.toDate().year(),
1671  attrValue.toDate().month(),
1672  attrValue.toDate().day(),
1673  0, 0, 0, 0 );
1674  break;
1675  case QVariant::DateTime:
1676  OGR_F_SetFieldDateTime( poFeature, ogrField,
1677  attrValue.toDateTime().date().year(),
1678  attrValue.toDateTime().date().month(),
1679  attrValue.toDateTime().date().day(),
1680  attrValue.toDateTime().time().hour(),
1681  attrValue.toDateTime().time().minute(),
1682  attrValue.toDateTime().time().second(),
1683  0 );
1684  break;
1685  case QVariant::Invalid:
1686  break;
1687  default:
1688  mErrorMessage = QObject::tr( "Invalid variant type for field %1[%2]: received %3 with type %4" )
1689  .arg( mFields[fldIdx].name() )
1690  .arg( ogrField )
1691  .arg( QMetaType::typeName( attrValue.type() ) )
1692  .arg( attrValue.toString() );
1695  return 0;
1696  }
1697  }
1698 
1699  if ( mWkbType != QGis::WKBNoGeometry )
1700  {
1701  // build geometry from WKB
1702  QgsGeometry *geom = feature.geometry();
1703 
1704  // turn single geoemetry to multi geometry if needed
1705  if ( geom && geom->wkbType() != mWkbType && geom->wkbType() == QGis::singleType( mWkbType ) )
1706  {
1707  geom->convertToMultiType();
1708  }
1709 
1710  if ( geom && geom->wkbType() != mWkbType )
1711  {
1712  // there's a problem when layer type is set as wkbtype Polygon
1713  // although there are also features of type MultiPolygon
1714  // (at least in OGR provider)
1715  // If the feature's wkbtype is different from the layer's wkbtype,
1716  // try to export it too.
1717  //
1718  // Btw. OGRGeometry must be exactly of the type of the geometry which it will receive
1719  // i.e. Polygons can't be imported to OGRMultiPolygon
1720 
1721  OGRGeometryH mGeom2 = createEmptyGeometry( geom->wkbType() );
1722 
1723  if ( !mGeom2 )
1724  {
1725  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1726  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1729  OGR_F_Destroy( poFeature );
1730  return 0;
1731  }
1732 
1733  OGRErr err = OGR_G_ImportFromWkb( mGeom2, const_cast<unsigned char *>( geom->asWkb() ), ( int ) geom->wkbSize() );
1734  if ( err != OGRERR_NONE )
1735  {
1736  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1737  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1740  OGR_F_Destroy( poFeature );
1741  return 0;
1742  }
1743 
1744  // pass ownership to geometry
1745  OGR_F_SetGeometryDirectly( poFeature, mGeom2 );
1746  }
1747  else if ( geom )
1748  {
1749  OGRErr err = OGR_G_ImportFromWkb( mGeom, const_cast<unsigned char *>( geom->asWkb() ), ( int ) geom->wkbSize() );
1750  if ( err != OGRERR_NONE )
1751  {
1752  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1753  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1756  OGR_F_Destroy( poFeature );
1757  return 0;
1758  }
1759 
1760  // set geometry (ownership is not passed to OGR)
1761  OGR_F_SetGeometry( poFeature, mGeom );
1762  }
1763  }
1764  return poFeature;
1765 }
1766 
1767 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
1768 {
1769  if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
1770  {
1771  mErrorMessage = QObject::tr( "Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1774  OGR_F_Destroy( feature );
1775  return false;
1776  }
1777  return true;
1778 }
1779 
1781 {
1782  if ( mGeom )
1783  {
1784  OGR_G_DestroyGeometry( mGeom );
1785  }
1786 
1787  if ( mDS )
1788  {
1789  OGR_DS_Destroy( mDS );
1790  }
1791 }
1792 
1795  const QString& fileName,
1796  const QString& fileEncoding,
1797  const QgsCoordinateReferenceSystem *destCRS,
1798  const QString& driverName,
1799  bool onlySelected,
1800  QString *errorMessage,
1801  const QStringList &datasourceOptions,
1802  const QStringList &layerOptions,
1803  bool skipAttributeCreation,
1804  QString *newFilename,
1805  SymbologyExport symbologyExport,
1806  double symbologyScale,
1807  const QgsRectangle* filterExtent )
1808 {
1809  QgsCoordinateTransform* ct = 0;
1810  if ( destCRS && layer )
1811  {
1812  ct = new QgsCoordinateTransform( layer->crs(), *destCRS );
1813  }
1814 
1815  QgsVectorFileWriter::WriterError error = writeAsVectorFormat( layer, fileName, fileEncoding, ct, driverName, onlySelected,
1816  errorMessage, datasourceOptions, layerOptions, skipAttributeCreation, newFilename, symbologyExport, symbologyScale, filterExtent );
1817  delete ct;
1818  return error;
1819 }
1820 
1822  const QString& fileName,
1823  const QString& fileEncoding,
1824  const QgsCoordinateTransform* ct,
1825  const QString& driverName,
1826  bool onlySelected,
1827  QString *errorMessage,
1828  const QStringList &datasourceOptions,
1829  const QStringList &layerOptions,
1830  bool skipAttributeCreation,
1831  QString *newFilename,
1832  SymbologyExport symbologyExport,
1833  double symbologyScale,
1834  const QgsRectangle* filterExtent )
1835 {
1836  if ( !layer )
1837  {
1838  return ErrInvalidLayer;
1839  }
1840 
1841  bool shallTransform = false;
1842  const QgsCoordinateReferenceSystem* outputCRS = 0;
1843  if ( ct )
1844  {
1845  // This means we should transform
1846  outputCRS = &( ct->destCRS() );
1847  shallTransform = true;
1848  }
1849  else
1850  {
1851  // This means we shouldn't transform, use source CRS as output (if defined)
1852  outputCRS = &layer->crs();
1853  }
1854 
1855  QGis::WkbType wkbType = layer->wkbType();
1856 
1857  if ( layer->providerType() == "ogr" )
1858  {
1859  QStringList theURIParts = layer->dataProvider()->dataSourceUri().split( "|" );
1860  QString srcFileName = theURIParts[0];
1861 
1862  if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
1863  {
1864  if ( errorMessage )
1865  *errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
1866  return ErrCreateDataSource;
1867  }
1868 
1869  // Shapefiles might contain multi types although wkbType() only reports singles
1870  if ( layer->storageType() == "ESRI Shapefile" )
1871  {
1872  const QgsFeatureIds &ids = layer->selectedFeaturesIds();
1873  QgsFeatureIterator fit = layer->getFeatures();
1874  QgsFeature fet;
1875  while ( fit.nextFeature( fet ) )
1876  {
1877  if ( onlySelected && !ids.contains( fet.id() ) )
1878  continue;
1879 
1880  if ( fet.geometry() && fet.geometry()->wkbType() == QGis::multiType( wkbType ) )
1881  {
1882  wkbType = QGis::multiType( wkbType );
1883  break;
1884  }
1885  }
1886  }
1887  }
1888 
1889  QgsVectorFileWriter* writer =
1890  new QgsVectorFileWriter( fileName, fileEncoding, skipAttributeCreation ? QgsFields() : layer->pendingFields(), wkbType, outputCRS, driverName, datasourceOptions, layerOptions, newFilename, symbologyExport );
1891  writer->setSymbologyScaleDenominator( symbologyScale );
1892 
1893  if ( newFilename )
1894  {
1895  QgsDebugMsg( "newFilename = " + *newFilename );
1896  }
1897 
1898  // check whether file creation was successful
1899  WriterError err = writer->hasError();
1900  if ( err != NoError )
1901  {
1902  if ( errorMessage )
1903  *errorMessage = writer->errorMessage();
1904  delete writer;
1905  return err;
1906  }
1907 
1908  if ( errorMessage )
1909  {
1910  errorMessage->clear();
1911  }
1912 
1913  QgsAttributeList allAttr = skipAttributeCreation ? QgsAttributeList() : layer->pendingAllAttributesList();
1914  QgsFeature fet;
1915 
1916  //add possible attributes needed by renderer
1917  writer->addRendererAttributes( layer, allAttr );
1918 
1919  QgsFeatureRequest req;
1920  if ( layer->wkbType() == QGis::WKBNoGeometry )
1921  {
1923  }
1924  req.setSubsetOfAttributes( allAttr );
1925  QgsFeatureIterator fit = layer->getFeatures( req );
1926 
1927  const QgsFeatureIds& ids = layer->selectedFeaturesIds();
1928 
1929  //create symbol table if needed
1930  if ( writer->symbologyExport() != NoSymbology )
1931  {
1932  //writer->createSymbolLayerTable( layer, writer->mDS );
1933  }
1934 
1935  if ( writer->symbologyExport() == SymbolLayerSymbology )
1936  {
1937  QgsFeatureRendererV2* r = layer->rendererV2();
1939  && r->usingSymbolLevels() )
1940  {
1941  QgsVectorFileWriter::WriterError error = writer->exportFeaturesSymbolLevels( layer, fit, ct, errorMessage );
1942  delete writer;
1943  return ( error == NoError ) ? NoError : ErrFeatureWriteFailed;
1944  }
1945  }
1946 
1947  int n = 0, errors = 0;
1948 
1949  //unit type
1950  QGis::UnitType mapUnits = layer->crs().mapUnits();
1951  if ( ct )
1952  {
1953  mapUnits = ct->destCRS().mapUnits();
1954  }
1955 
1956  writer->startRender( layer );
1957 
1958  // enabling transaction on databases that support it
1959  bool transactionsEnabled = true;
1960 
1961  if ( OGRERR_NONE != OGR_L_StartTransaction( writer->mLayer ) )
1962  {
1963  QgsDebugMsg( "Error when trying to enable transactions on OGRLayer." );
1964  transactionsEnabled = false;
1965  }
1966 
1967  // write all features
1968  while ( fit.nextFeature( fet ) )
1969  {
1970  if ( onlySelected && !ids.contains( fet.id() ) )
1971  continue;
1972 
1973  if ( shallTransform )
1974  {
1975  try
1976  {
1977  if ( fet.geometry() )
1978  {
1979  fet.geometry()->transform( *ct );
1980  }
1981  }
1982  catch ( QgsCsException &e )
1983  {
1984  delete writer;
1985 
1986  QString msg = QObject::tr( "Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
1987  .arg( fet.id() ).arg( e.what() );
1988  QgsLogger::warning( msg );
1989  if ( errorMessage )
1990  *errorMessage = msg;
1991 
1992  return ErrProjection;
1993  }
1994  }
1995 
1996  if ( fet.geometry() && filterExtent && !fet.geometry()->intersects( *filterExtent ) )
1997  continue;
1998 
1999  if ( allAttr.size() < 1 && skipAttributeCreation )
2000  {
2001  fet.initAttributes( 0 );
2002  }
2003 
2004  if ( !writer->addFeature( fet, layer->rendererV2(), mapUnits ) )
2005  {
2006  WriterError err = writer->hasError();
2007  if ( err != NoError && errorMessage )
2008  {
2009  if ( errorMessage->isEmpty() )
2010  {
2011  *errorMessage = QObject::tr( "Feature write errors:" );
2012  }
2013  *errorMessage += "\n" + writer->errorMessage();
2014  }
2015  errors++;
2016 
2017  if ( errors > 1000 )
2018  {
2019  if ( errorMessage )
2020  {
2021  *errorMessage += QObject::tr( "Stopping after %1 errors" ).arg( errors );
2022  }
2023 
2024  n = -1;
2025  break;
2026  }
2027  }
2028  n++;
2029  }
2030 
2031  if ( transactionsEnabled )
2032  {
2033  if ( OGRERR_NONE != OGR_L_CommitTransaction( writer->mLayer ) )
2034  {
2035  QgsDebugMsg( "Error while committing transaction on OGRLayer." );
2036  }
2037  }
2038 
2039  writer->stopRender( layer );
2040  delete writer;
2041 
2042  if ( errors > 0 && errorMessage && n > 0 )
2043  {
2044  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
2045  }
2046 
2047  return errors == 0 ? NoError : ErrFeatureWriteFailed;
2048 }
2049 
2050 
2051 bool QgsVectorFileWriter::deleteShapeFile( QString theFileName )
2052 {
2053  QFileInfo fi( theFileName );
2054  QDir dir = fi.dir();
2055 
2056  QStringList filter;
2057  const char *suffixes[] = { ".shp", ".shx", ".dbf", ".prj", ".qix", ".qpj" };
2058  for ( std::size_t i = 0; i < sizeof( suffixes ) / sizeof( *suffixes ); i++ )
2059  {
2060  filter << fi.completeBaseName() + suffixes[i];
2061  }
2062 
2063  bool ok = true;
2064  foreach ( QString file, dir.entryList( filter ) )
2065  {
2066  if ( !QFile::remove( dir.canonicalPath() + "/" + file ) )
2067  {
2068  QgsDebugMsg( "Removing file failed : " + file );
2069  ok = false;
2070  }
2071  }
2072 
2073  return ok;
2074 }
2075 
2077 {
2078  QMap<QString, QString> resultMap;
2079 
2081  int const drvCount = OGRGetDriverCount();
2082 
2083  for ( int i = 0; i < drvCount; ++i )
2084  {
2085  OGRSFDriverH drv = OGRGetDriver( i );
2086  if ( drv )
2087  {
2088  QString drvName = OGR_Dr_GetName( drv );
2089  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
2090  {
2091  QString filterString = filterForDriver( drvName );
2092  if ( filterString.isEmpty() )
2093  continue;
2094 
2095  resultMap.insert( filterString, drvName );
2096  }
2097  }
2098  }
2099 
2100  return resultMap;
2101 }
2102 
2103 QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
2104 {
2105  QMap<QString, QString> resultMap;
2106 
2108  int const drvCount = OGRGetDriverCount();
2109 
2110  QStringList writableDrivers;
2111  for ( int i = 0; i < drvCount; ++i )
2112  {
2113  OGRSFDriverH drv = OGRGetDriver( i );
2114  if ( drv )
2115  {
2116  QString drvName = OGR_Dr_GetName( drv );
2117  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
2118  {
2119  // Add separate format for Mapinfo MIF (MITAB is OGR default)
2120  if ( drvName == "MapInfo File" )
2121  {
2122  writableDrivers << "MapInfo MIF";
2123  }
2124  else if ( drvName == "SQLite" )
2125  {
2126  // Unfortunately it seems that there is no simple way to detect if
2127  // OGR SQLite driver is compiled with SpatiaLite support.
2128  // We have HAVE_SPATIALITE in QGIS, but that may differ from OGR
2129  // http://lists.osgeo.org/pipermail/gdal-dev/2012-November/034580.html
2130  // -> test if creation failes
2131  QString option = "SPATIALITE=YES";
2132  char **options = new char *[2];
2133  options[0] = CPLStrdup( option.toLocal8Bit().data() );
2134  options[1] = NULL;
2135  OGRSFDriverH poDriver;
2137  poDriver = OGRGetDriverByName( drvName.toLocal8Bit().data() );
2138  if ( poDriver )
2139  {
2140  OGRDataSourceH ds = OGR_Dr_CreateDataSource( poDriver, TO8F( QString( "/vsimem/spatialitetest.sqlite" ) ), options );
2141  if ( ds )
2142  {
2143  writableDrivers << "SpatiaLite";
2144  OGR_Dr_DeleteDataSource( poDriver, TO8F( QString( "/vsimem/spatialitetest.sqlite" ) ) );
2145  OGR_DS_Destroy( ds );
2146  }
2147  }
2148  CPLFree( options[0] );
2149  delete [] options;
2150  }
2151  else if ( drvName == "ESRI Shapefile" )
2152  {
2153  writableDrivers << "DBF file";
2154  }
2155  writableDrivers << drvName;
2156  }
2157  }
2158  }
2159 
2160  foreach ( QString drvName, writableDrivers )
2161  {
2162  QString longName;
2163  QString trLongName;
2164  QString glob;
2165  QString exts;
2166  if ( QgsVectorFileWriter::driverMetadata( drvName, longName, trLongName, glob, exts ) && !trLongName.isEmpty() )
2167  {
2168  resultMap.insert( trLongName, drvName );
2169  }
2170  }
2171 
2172  return resultMap;
2173 }
2174 
2176 {
2177  QString filterString;
2178  QMap< QString, QString> driverFormatMap = supportedFiltersAndFormats();
2179  QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
2180  for ( ; it != driverFormatMap.constEnd(); ++it )
2181  {
2182  if ( !filterString.isEmpty() )
2183  filterString += ";;";
2184 
2185  filterString += it.key();
2186  }
2187  return filterString;
2188 }
2189 
2190 QString QgsVectorFileWriter::filterForDriver( const QString& driverName )
2191 {
2192  QString longName;
2193  QString trLongName;
2194  QString glob;
2195  QString exts;
2196  if ( !driverMetadata( driverName, longName, trLongName, glob, exts ) || trLongName.isEmpty() || glob.isEmpty() )
2197  return "";
2198 
2199  return trLongName + " [OGR] (" + glob.toLower() + " " + glob.toUpper() + ")";
2200 }
2201 
2203 {
2204  if ( codecName == "System" )
2205  return QString( "LDID/0" );
2206 
2207  QRegExp re = QRegExp( QString( "(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
2208  if ( re.exactMatch( codecName ) )
2209  {
2210  QString c = re.cap( 2 ).replace( "-", "" );
2211  bool isNumber;
2212  c.toInt( &isNumber );
2213  if ( isNumber )
2214  return c;
2215  }
2216  return codecName;
2217 }
2218 
2219 bool QgsVectorFileWriter::driverMetadata( QString driverName, QString &longName, QString &trLongName, QString &glob, QString &ext )
2220 {
2221  if ( driverName.startsWith( "AVCE00" ) )
2222  {
2223  longName = "Arc/Info ASCII Coverage";
2224  trLongName = QObject::tr( "Arc/Info ASCII Coverage" );
2225  glob = "*.e00";
2226  ext = "e00";
2227  }
2228  else if ( driverName.startsWith( "BNA" ) )
2229  {
2230  longName = "Atlas BNA";
2231  trLongName = QObject::tr( "Atlas BNA" );
2232  glob = "*.bna";
2233  ext = "bna";
2234  }
2235  else if ( driverName.startsWith( "CSV" ) )
2236  {
2237  longName = "Comma Separated Value [CSV]";
2238  trLongName = QObject::tr( "Comma Separated Value [CSV]" );
2239  glob = "*.csv";
2240  ext = "csv";
2241  }
2242  else if ( driverName.startsWith( "ESRI" ) )
2243  {
2244  longName = "ESRI Shapefile";
2245  trLongName = QObject::tr( "ESRI Shapefile" );
2246  glob = "*.shp";
2247  ext = "shp";
2248  }
2249  else if ( driverName.startsWith( "DBF file" ) )
2250  {
2251  longName = "DBF File";
2252  trLongName = QObject::tr( "DBF file" );
2253  glob = "*.dbf";
2254  ext = "dbf";
2255  }
2256  else if ( driverName.startsWith( "FMEObjects Gateway" ) )
2257  {
2258  longName = "FMEObjects Gateway";
2259  trLongName = QObject::tr( "FMEObjects Gateway" );
2260  glob = "*.fdd";
2261  ext = "fdd";
2262  }
2263  else if ( driverName.startsWith( "GeoJSON" ) )
2264  {
2265  longName = "GeoJSON";
2266  trLongName = QObject::tr( "GeoJSON" );
2267  glob = "*.geojson";
2268  ext = "geojson";
2269  }
2270  else if ( driverName.startsWith( "GeoRSS" ) )
2271  {
2272  longName = "GeoRSS";
2273  trLongName = QObject::tr( "GeoRSS" );
2274  glob = "*.xml";
2275  ext = "xml";
2276  }
2277  else if ( driverName.startsWith( "GML" ) )
2278  {
2279  longName = "Geography Markup Language [GML]";
2280  trLongName = QObject::tr( "Geography Markup Language [GML]" );
2281  glob = "*.gml";
2282  ext = "gml";
2283  }
2284  else if ( driverName.startsWith( "GMT" ) )
2285  {
2286  longName = "Generic Mapping Tools [GMT]";
2287  trLongName = QObject::tr( "Generic Mapping Tools [GMT]" );
2288  glob = "*.gmt";
2289  ext = "gmt";
2290  }
2291  else if ( driverName.startsWith( "GPX" ) )
2292  {
2293  longName = "GPS eXchange Format [GPX]";
2294  trLongName = QObject::tr( "GPS eXchange Format [GPX]" );
2295  glob = "*.gpx";
2296  ext = "gpx";
2297  }
2298  else if ( driverName.startsWith( "Interlis 1" ) )
2299  {
2300  longName = "INTERLIS 1";
2301  trLongName = QObject::tr( "INTERLIS 1" );
2302  glob = "*.itf *.xml *.ili";
2303  ext = "ili";
2304  }
2305  else if ( driverName.startsWith( "Interlis 2" ) )
2306  {
2307  longName = "INTERLIS 2";
2308  trLongName = QObject::tr( "INTERLIS 2" );
2309  glob = "*.itf *.xml *.ili";
2310  ext = "ili";
2311  }
2312  else if ( driverName.startsWith( "KML" ) )
2313  {
2314  longName = "Keyhole Markup Language [KML]";
2315  trLongName = QObject::tr( "Keyhole Markup Language [KML]" );
2316  glob = "*.kml";
2317  ext = "kml";
2318  }
2319  else if ( driverName.startsWith( "MapInfo File" ) )
2320  {
2321  longName = "Mapinfo TAB";
2322  trLongName = QObject::tr( "Mapinfo TAB" );
2323  glob = "*.tab";
2324  ext = "tab";
2325  }
2326  // 'MapInfo MIF' is internal QGIS addition to distinguish between MITAB and MIF
2327  else if ( driverName.startsWith( "MapInfo MIF" ) )
2328  {
2329  longName = "Mapinfo MIF";
2330  trLongName = QObject::tr( "Mapinfo MIF" );
2331  glob = "*.mif";
2332  ext = "mif";
2333  }
2334  else if ( driverName.startsWith( "DGN" ) )
2335  {
2336  longName = "Microstation DGN";
2337  trLongName = QObject::tr( "Microstation DGN" );
2338  glob = "*.dgn";
2339  ext = "dgn";
2340  }
2341  else if ( driverName.startsWith( "S57" ) )
2342  {
2343  longName = "S-57 Base file";
2344  trLongName = QObject::tr( "S-57 Base file" );
2345  glob = "*.000";
2346  ext = "000";
2347  }
2348  else if ( driverName.startsWith( "SDTS" ) )
2349  {
2350  longName = "Spatial Data Transfer Standard [SDTS]";
2351  trLongName = QObject::tr( "Spatial Data Transfer Standard [SDTS]" );
2352  glob = "*catd.ddf";
2353  ext = "ddf";
2354  }
2355  else if ( driverName.startsWith( "SQLite" ) )
2356  {
2357  longName = "SQLite";
2358  trLongName = QObject::tr( "SQLite" );
2359  glob = "*.sqlite";
2360  ext = "sqlite";
2361  }
2362  // QGIS internal addition for SpatialLite
2363  else if ( driverName.startsWith( "SpatiaLite" ) )
2364  {
2365  longName = "SpatiaLite";
2366  trLongName = QObject::tr( "SpatiaLite" );
2367  glob = "*.sqlite";
2368  ext = "sqlite";
2369  }
2370  else if ( driverName.startsWith( "DXF" ) )
2371  {
2372  longName = "AutoCAD DXF";
2373  trLongName = QObject::tr( "AutoCAD DXF" );
2374  glob = "*.dxf";
2375  ext = "dxf";
2376  }
2377  else if ( driverName.startsWith( "Geoconcept" ) )
2378  {
2379  longName = "Geoconcept";
2380  trLongName = QObject::tr( "Geoconcept" );
2381  glob = "*.gxt *.txt";
2382  ext = "gxt";
2383  }
2384  else if ( driverName.startsWith( "FileGDB" ) )
2385  {
2386  longName = "ESRI FileGDB";
2387  trLongName = QObject::tr( "ESRI FileGDB" );
2388  glob = "*.gdb";
2389  ext = "gdb";
2390  }
2391  else
2392  {
2393  return false;
2394  }
2395 
2396  return true;
2397 }
2398 
2399 void QgsVectorFileWriter::createSymbolLayerTable( QgsVectorLayer* vl, const QgsCoordinateTransform* ct, OGRDataSourceH ds )
2400 {
2401  if ( !vl || !ds )
2402  {
2403  return;
2404  }
2405 
2406  QgsFeatureRendererV2* renderer = vl->rendererV2();
2407  if ( !renderer )
2408  {
2409  return;
2410  }
2411 
2412  //unit type
2413  QGis::UnitType mapUnits = vl->crs().mapUnits();
2414  if ( ct )
2415  {
2416  mapUnits = ct->destCRS().mapUnits();
2417  }
2418 
2419 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1700
2420  mSymbolLayerTable.clear();
2421  OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
2422  OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
2423 
2424  //get symbols
2425  int nTotalLevels = 0;
2426  QgsSymbolV2List symbolList = renderer->symbols();
2427  QgsSymbolV2List::iterator symbolIt = symbolList.begin();
2428  for ( ; symbolIt != symbolList.end(); ++symbolIt )
2429  {
2430  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits );
2431  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits );
2432 
2433  int nLevels = ( *symbolIt )->symbolLayerCount();
2434  for ( int i = 0; i < nLevels; ++i )
2435  {
2436  mSymbolLayerTable.insert(( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
2437  OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
2438  ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
2439  ++nTotalLevels;
2440  }
2441  }
2442  OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
2443 #endif
2444 }
2445 
2446 QgsVectorFileWriter::WriterError QgsVectorFileWriter::exportFeaturesSymbolLevels( QgsVectorLayer* layer, QgsFeatureIterator& fit,
2447  const QgsCoordinateTransform* ct, QString* errorMessage )
2448 {
2449  if ( !layer )
2450  {
2451  //return error
2452  }
2453  QgsFeatureRendererV2* renderer = layer->rendererV2();
2454  if ( !renderer )
2455  {
2456  //return error
2457  }
2458  QHash< QgsSymbolV2*, QList<QgsFeature> > features;
2459 
2460  //unit type
2461  QGis::UnitType mapUnits = layer->crs().mapUnits();
2462  if ( ct )
2463  {
2464  mapUnits = ct->destCRS().mapUnits();
2465  }
2466 
2467  startRender( layer );
2468 
2469  //fetch features
2470  QgsFeature fet;
2471  QgsSymbolV2* featureSymbol = 0;
2472  while ( fit.nextFeature( fet ) )
2473  {
2474  if ( ct )
2475  {
2476  try
2477  {
2478  if ( fet.geometry() )
2479  {
2480  fet.geometry()->transform( *ct );
2481  }
2482  }
2483  catch ( QgsCsException &e )
2484  {
2485  QString msg = QObject::tr( "Failed to transform, writing stopped. (Exception: %1)" )
2486  .arg( e.what() );
2487  QgsLogger::warning( msg );
2488  if ( errorMessage )
2489  *errorMessage = msg;
2490 
2491  return ErrProjection;
2492  }
2493  }
2494 
2495  featureSymbol = renderer->symbolForFeature( fet );
2496  if ( !featureSymbol )
2497  {
2498  continue;
2499  }
2500 
2501  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
2502  if ( it == features.end() )
2503  {
2504  it = features.insert( featureSymbol, QList<QgsFeature>() );
2505  }
2506  it.value().append( fet );
2507  }
2508 
2509  //find out order
2510  QgsSymbolV2LevelOrder levels;
2511  QgsSymbolV2List symbols = renderer->symbols();
2512  for ( int i = 0; i < symbols.count(); i++ )
2513  {
2514  QgsSymbolV2* sym = symbols[i];
2515  for ( int j = 0; j < sym->symbolLayerCount(); j++ )
2516  {
2517  int level = sym->symbolLayer( j )->renderingPass();
2518  if ( level < 0 || level >= 1000 ) // ignore invalid levels
2519  continue;
2520  QgsSymbolV2LevelItem item( sym, j );
2521  while ( level >= levels.count() ) // append new empty levels
2522  levels.append( QgsSymbolV2Level() );
2523  levels[level].append( item );
2524  }
2525  }
2526 
2527  int nErrors = 0;
2528  int nTotalFeatures = 0;
2529 
2530  //export symbol layers and symbology
2531  for ( int l = 0; l < levels.count(); l++ )
2532  {
2533  QgsSymbolV2Level& level = levels[l];
2534  for ( int i = 0; i < level.count(); i++ )
2535  {
2536  QgsSymbolV2LevelItem& item = level[i];
2537  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
2538  if ( levelIt == features.end() )
2539  {
2540  ++nErrors;
2541  continue;
2542  }
2543 
2544  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(), mapUnits );
2545  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(), mapUnits );
2546 
2547  int llayer = item.layer();
2548  QList<QgsFeature>& featureList = levelIt.value();
2549  QList<QgsFeature>::iterator featureIt = featureList.begin();
2550  for ( ; featureIt != featureList.end(); ++featureIt )
2551  {
2552  ++nTotalFeatures;
2553  OGRFeatureH ogrFeature = createFeature( *featureIt );
2554  if ( !ogrFeature )
2555  {
2556  ++nErrors;
2557  continue;
2558  }
2559 
2560  QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
2561  if ( !styleString.isEmpty() )
2562  {
2563  OGR_F_SetStyleString( ogrFeature, styleString.toLocal8Bit().data() );
2564  if ( ! writeFeature( mLayer, ogrFeature ) )
2565  {
2566  ++nErrors;
2567  }
2568  }
2569  OGR_F_Destroy( ogrFeature );
2570  }
2571  }
2572  }
2573 
2574  stopRender( layer );
2575 
2576  if ( nErrors > 0 && errorMessage )
2577  {
2578  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
2579  }
2580 
2582 }
2583 
2584 double QgsVectorFileWriter::mmScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
2585 {
2586  if ( symbolUnits == QgsSymbolV2::MM )
2587  {
2588  return 1.0;
2589  }
2590  else
2591  {
2592  //conversion factor map units -> mm
2593  if ( mapUnits == QGis::Meters )
2594  {
2595  return 1000 / scaleDenominator;
2596  }
2597 
2598  }
2599  return 1.0; //todo: map units
2600 }
2601 
2602 double QgsVectorFileWriter::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
2603 {
2604  if ( symbolUnits == QgsSymbolV2::MapUnit )
2605  {
2606  return 1.0;
2607  }
2608  else
2609  {
2610  if ( symbolUnits == QgsSymbolV2::MM && mapUnits == QGis::Meters )
2611  {
2612  return scaleDenominator / 1000;
2613  }
2614  }
2615  return 1.0;
2616 }
2617 
2618 QgsRenderContext QgsVectorFileWriter::renderContext() const
2619 {
2620  QgsRenderContext context;
2622  return context;
2623 }
2624 
2625 void QgsVectorFileWriter::startRender( QgsVectorLayer* vl ) const
2626 {
2627  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2628  if ( !renderer )
2629  {
2630  return;
2631  }
2632 
2633  QgsRenderContext ctx = renderContext();
2634  renderer->startRender( ctx, vl->pendingFields() );
2635 }
2636 
2637 void QgsVectorFileWriter::stopRender( QgsVectorLayer* vl ) const
2638 {
2639  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2640  if ( !renderer )
2641  {
2642  return;
2643  }
2644 
2645  QgsRenderContext ctx = renderContext();
2646  renderer->stopRender( ctx );
2647 }
2648 
2649 QgsFeatureRendererV2* QgsVectorFileWriter::symbologyRenderer( QgsVectorLayer* vl ) const
2650 {
2651  if ( mSymbologyExport == NoSymbology )
2652  {
2653  return 0;
2654  }
2655  if ( !vl )
2656  {
2657  return 0;
2658  }
2659 
2660  return vl->rendererV2();
2661 }
2662 
2663 void QgsVectorFileWriter::addRendererAttributes( QgsVectorLayer* vl, QgsAttributeList& attList )
2664 {
2665  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2666  if ( renderer )
2667  {
2668  QList<QString> rendererAttributes = renderer->usedAttributes();
2669  for ( int i = 0; i < rendererAttributes.size(); ++i )
2670  {
2671  int index = vl->fieldNameIndex( rendererAttributes.at( i ) );
2672  if ( index != -1 )
2673  {
2674  attList.push_back( vl->fieldNameIndex( rendererAttributes.at( i ) ) );
2675  }
2676  }
2677  }
2678 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:100
static WkbType singleType(WkbType type)
Definition: qgis.h:71
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:59
Wrapper for iterator of features from vector data provider or vector layer.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
static unsigned index
A rectangle specified with double values.
Definition: qgsrectangle.h:35
static QMap< QString, QString > supportedFiltersAndFormats()
Returns map with format filter string as key and OGR format key as value.
SymbologyExport symbologyExport() const
QList< QgsSymbolV2 * > QgsSymbolV2List
Definition: qgsrendererv2.h:37
WriterError mError
contains error value if construction was not successful
static QString fileFilterString()
Returns filter string that can be used for dialogs.
#define QgsDebugMsg(str)
Definition: qgslogger.h:33
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:317
UnitType
Map units that qgis supports.
Definition: qgis.h:229
SymbologyExport mSymbologyExport
double mSymbologyScaleDenominator
Scale for symbology export (e.g.
static void warning(const QString &msg)
Goes to qWarning.
Definition: qgslogger.cpp:124
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest())
Query the provider for features specified in request.
QgsGeometry * geometry() const
Get the geometry object associated with this feature.
Definition: qgsfeature.cpp:112
void setRendererScale(double scale)
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:79
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
static bool deleteShapeFile(QString theFileName)
Delete a shapefile (and its accompanying shx / dbf / prf)
Container of fields for a vector layer.
Definition: qgsfield.h:172
virtual QList< QString > usedAttributes()=0
WkbType
Used for symbology operations.
Definition: qgis.h:53
A convenience class for writing vector files to disk.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:113
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)=0
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QGis::WkbType wkbType() const
Returns the WKBType or WKBUnknown in case of error.
virtual void stopRender(QgsRenderContext &context)=0
virtual QgsSymbolV2List symbols()=0
for symbol levels
#define TO8F(x)
const QgsFeatureIds & selectedFeaturesIds() const
Return reference to identifiers of selected features.
#define FID_TO_NUMBER(fid)
Definition: qgsfeature.h:82
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
Definition: qgsfeature.cpp:181
This class wraps a request for features to a vector layer (or directly its vector data provider)...
~QgsVectorFileWriter()
close opened shapefile for writing
QList< int > QgsAttributeList
int symbolLayerCount()
Definition: qgssymbolv2.h:85
bool addFeature(QgsFeature &feature, QgsFeatureRendererV2 *renderer=0, QGis::UnitType outputUnit=QGis::Meters)
add feature to the currently opened shapefile
int count() const
Return number of items.
Definition: qgsfield.h:214
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
QGis::WkbType mWkbType
geometry type which is being used
Encapsulate a field in an attribute table or data source.
Definition: qgsfield.h:33
QMap< int, int > mAttrIdxToOgrIdx
map attribute indizes to OGR field indexes
QList< QgsSymbolV2LevelItem > QgsSymbolV2Level
Definition: qgsrendererv2.h:63
int renderingPass() const
static QMap< QString, QString > ogrDriverList()
Returns driver list that can be used for dialogs.
QString file
Definition: qgssvgcache.cpp:76
QString errorMessage()
retrieves error message
QString providerType() const
Return the provider type for this layer.
QString what() const
Definition: qgsexception.h:35
Contains information about the context of a rendering operation.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
WriterError hasError()
checks whether there were any errors in constructor
QVariant attribute(const QString &name) const
Lookup attribute value from attribute name.
Definition: qgsfeature.cpp:230
QgsAttributeList pendingAllAttributesList()
returns list of attributes
QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, QGis::WkbType geometryType, const QgsCoordinateReferenceSystem *srs, const QString &driverName="ESRI Shapefile", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=0, SymbologyExport symbologyExport=NoSymbology)
create shapefile and initialize it
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat)
return list of symbols used for rendering the feature.
void setSymbologyScaleDenominator(double d)
QgsSymbolV2 * symbol()
Definition: qgsrendererv2.h:55
bool usingSymbolLevels() const
Class for storing a coordinate reference system (CRS)
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:74
int size() const
Return number of items.
Definition: qgsfield.h:216
Class for doing transforms between two map coordinate systems.
int transform(const QgsCoordinateTransform &ct)
Transform this geometry as described by CoordinateTranasform ct.
QList< QgsSymbolV2Level > QgsSymbolV2LevelOrder
Definition: qgsrendererv2.h:66
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
Custom exception class for Coordinate Reference System related exceptions.
const QgsFields & pendingFields() const
returns field list in the to-be-committed state
QgsSymbolLayerV2 * symbolLayer(int layer)
QgsVectorDataProvider * dataProvider()
Returns the data provider.
virtual int capabilities()
returns bitwise OR-ed capabilities of the renderer
bool nextFeature(QgsFeature &f)
Geometry is not required. It may still be returned if e.g. required for a filter condition.
const QgsCoordinateReferenceSystem & destCRS() const
bool intersects(const QgsRectangle &r) const
Test for intersection with a rectangle (uses GEOS)
Represents a vector layer which manages a vector based data sets.
int fieldNameIndex(const QString &fieldName) const
Returns the index of a field name or -1 if the field does not exist.
virtual QgsSymbolV2 * symbolForFeature(QgsFeature &feature)=0
to be overridden
QgsFeatureRequest & setFlags(Flags flags)
Set flags that affect how features will be fetched.
const unsigned char * asWkb() const
Returns the buffer containing this geometry in WKB format.
OGRGeometryH createEmptyGeometry(QGis::WkbType wkbType)
int max(int a, int b)
Definition: util.h:87
static WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem *destCRS, const QString &driverName="ESRI Shapefile", bool onlySelected=false, QString *errorMessage=0, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=0, SymbologyExport symbologyExport=NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=0)
Write contents of vector layer to an (OGR supported) vector formt.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
virtual QString dataSourceUri() const
Get the data source specification.
static WkbType multiType(WkbType type)
Definition: qgis.h:85
void * OGRSpatialReferenceH
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:64
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
#define tr(sourceText)