QGIS API Documentation  2.5.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties 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",
636  QObject::tr( "Comma Separated Value" ),
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  // SQLite
1283  datasetOptions.clear();
1284  layerOptions.clear();
1285 
1286  datasetOptions.insert( "METADATA", new BoolOption(
1287  QObject::tr( "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1288  "tables in a new database. By default these metadata tables are created "
1289  "when a new database is created." )
1290  , true // Default value
1291  ) );
1292 
1293  // Will handle the spatialite alias
1294  datasetOptions.insert( "SPATIALITE", new HiddenOption(
1295  "NO"
1296  ) );
1297 
1298 
1299  datasetOptions.insert( "INIT_WITH_EPSG", new HiddenOption(
1300  "NO"
1301  ) );
1302 
1303  layerOptions.insert( "FORMAT", new SetOption(
1304  QObject::tr( "Controls the format used for the geometry column. Defaults to WKB."
1305  "This is generally more space and processing efficient, but harder "
1306  "to inspect or use in simple applications than WKT (Well Known Text)." ),
1307  QStringList()
1308  << "WKB"
1309  << "WKT"
1310  , "WKB" // Default value
1311  ) );
1312 
1313  layerOptions.insert( "LAUNDER", new BoolOption(
1314  QObject::tr( "Controls whether layer and field names will be laundered for easier use "
1315  "in SQLite. Laundered names will be converted to lower case and some special "
1316  "characters(' - #) will be changed to underscores." )
1317  , true // Default value
1318  ) );
1319 
1320  layerOptions.insert( "SPATIAL_INDEX", new HiddenOption(
1321  "NO"
1322  ) );
1323 
1324  layerOptions.insert( "COMPRESS_GEOM", new HiddenOption(
1325  "NO"
1326  ) );
1327 
1328  layerOptions.insert( "SRID", new HiddenOption(
1329  ""
1330  ) );
1331 
1332  layerOptions.insert( "COMPRESS_COLUMNS", new StringOption(
1333  QObject::tr( "column_name1[,column_name2, ...] A list of (String) columns that "
1334  "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1335  "for databases that have big string blobs. However, use with care, since "
1336  "the value of such columns will be seen as compressed binary content with "
1337  "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1338  "modifying or queryings compressed columns, compression/decompression is "
1339  "done transparently. However, such columns cannot be (easily) queried with "
1340  "an attribute filter or WHERE clause. Note: in table definition, such columns "
1341  "have the 'VARCHAR_deflate' declaration type." )
1342  , "" // Default value
1343  ) );
1344 
1345  driverMetadata.insert( "SQLite",
1346  MetaData(
1347  "SQLite",
1348  QObject::tr( "SQLite" ),
1349  "*.sqlite",
1350  "sqlite",
1351  datasetOptions,
1352  layerOptions
1353  )
1354  );
1355  // SpatiaLite
1356 
1357  datasetOptions.clear();
1358  layerOptions.clear();
1359 
1360  datasetOptions.insert( "METADATA", new BoolOption(
1361  QObject::tr( "Can be used to avoid creating the geometry_columns and spatial_ref_sys "
1362  "tables in a new database. By default these metadata tables are created "
1363  "when a new database is created." )
1364  , true // Default value
1365  ) );
1366 
1367  datasetOptions.insert( "SPATIALITE", new HiddenOption(
1368  "YES"
1369  ) );
1370 
1371  datasetOptions.insert( "INIT_WITH_EPSG", new BoolOption(
1372  QObject::tr( "Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
1373  "Set to NO for regular SQLite databases." )
1374  , true // Default value
1375  ) );
1376 
1377  layerOptions.insert( "FORMAT", new HiddenOption(
1378  "SPATIALITE"
1379  ) );
1380 
1381  layerOptions.insert( "LAUNDER", new BoolOption(
1382  QObject::tr( "Controls whether layer and field names will be laundered for easier use "
1383  "in SQLite. Laundered names will be convered to lower case and some special "
1384  "characters(' - #) will be changed to underscores." )
1385  , true // Default value
1386  ) );
1387 
1388  layerOptions.insert( "SPATIAL_INDEX", new BoolOption(
1389  QObject::tr( "If the database is of the SpatiaLite flavour, and if OGR is linked "
1390  "against libspatialite, this option can be used to control if a spatial "
1391  "index must be created." )
1392  , true // Default value
1393  ) );
1394 
1395  layerOptions.insert( "COMPRESS_GEOM", new BoolOption(
1396  QObject::tr( "If the format of the geometry BLOB is of the SpatiaLite flavour, "
1397  "this option can be used to control if the compressed format for "
1398  "geometries (LINESTRINGs, POLYGONs) must be used" )
1399  , false // Default value
1400  ) );
1401 
1402  layerOptions.insert( "SRID", new StringOption(
1403  QObject::tr( "Used to force the SRID number of the SRS associated with the layer. "
1404  "When this option isn't specified and that a SRS is associated with the "
1405  "layer, a search is made in the spatial_ref_sys to find a match for the "
1406  "SRS, and, if there is no match, a new entry is inserted for the SRS in "
1407  "the spatial_ref_sys table. When the SRID option is specified, this "
1408  "search (and the eventual insertion of a new entry) will not be done: "
1409  "the specified SRID is used as such." )
1410  , "" // Default value
1411  ) );
1412 
1413  layerOptions.insert( "COMPRESS_COLUMNS", new StringOption(
1414  QObject::tr( "column_name1[,column_name2, ...] A list of (String) columns that "
1415  "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
1416  "for databases that have big string blobs. However, use with care, since "
1417  "the value of such columns will be seen as compressed binary content with "
1418  "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
1419  "modifying or queryings compressed columns, compression/decompression is "
1420  "done transparently. However, such columns cannot be (easily) queried with "
1421  "an attribute filter or WHERE clause. Note: in table definition, such columns "
1422  "have the 'VARCHAR_deflate' declaration type." )
1423  , "" // Default value
1424  ) );
1425 
1426  driverMetadata.insert( "SpatiaLite",
1427  MetaData(
1428  "SpatiaLite",
1429  QObject::tr( "SpatiaLite" ),
1430  "*.sqlite",
1431  "sqlite",
1432  datasetOptions,
1433  layerOptions
1434  )
1435  );
1436  // AutoCAD DXF
1437  datasetOptions.clear();
1438  layerOptions.clear();
1439 
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 
1450  driverMetadata.insert( "DXF",
1451  MetaData(
1452  "AutoCAD DXF",
1453  QObject::tr( "AutoCAD DXF" ),
1454  "*.dxf",
1455  "dxf",
1456  datasetOptions,
1457  layerOptions
1458  )
1459  );
1460 
1461  // Geoconcept
1462  datasetOptions.clear();
1463  layerOptions.clear();
1464 
1465  datasetOptions.insert( "EXTENSION", new SetOption(
1466  QObject::tr( "Indicates the GeoConcept export file extension. "
1467  "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
1468  QStringList()
1469  << "GXT"
1470  << "TXT"
1471  , "GXT" // Default value
1472  ) );
1473 
1474 // datasetOptions.insert( "CONFIG", new StringOption(
1475 // QObject::tr( "path to the GCT : the GCT file describe the GeoConcept types definitions: "
1476 // "In this file, every line must start with //# followed by a keyword. "
1477 // "Lines starting with // are comments." )
1478 // , "" // Default value
1479 // ) );
1480 
1481  driverMetadata.insert( "Geoconcept",
1482  MetaData(
1483  "Geoconcept",
1484  QObject::tr( "Geoconcept" ),
1485  "*.gxt *.txt",
1486  "gxt",
1487  datasetOptions,
1488  layerOptions
1489  )
1490  );
1491 
1492  // ESRI FileGDB
1493  datasetOptions.clear();
1494  layerOptions.clear();
1495 
1496  layerOptions.insert( "FEATURE_DATASET", new StringOption(
1497  QObject::tr( "When this option is set, the new layer will be created inside the named "
1498  "FeatureDataset folder. If the folder does not already exist, it will be created." )
1499  , "" // Default value
1500  ) );
1501 
1502  layerOptions.insert( "GEOMETRY_NAME", new StringOption(
1503  QObject::tr( "Set name of geometry column in new layer. Defaults to 'SHAPE'." )
1504  , "SHAPE" // Default value
1505  ) );
1506 
1507  layerOptions.insert( "OID_NAME", new StringOption(
1508  QObject::tr( "Name of the OID column to create. Defaults to 'OBJECTID'." )
1509  , "OBJECTID" // Default value
1510  ) );
1511 
1512  driverMetadata.insert( "FileGDB",
1513  MetaData(
1514  "ESRI FileGDB",
1515  QObject::tr( "ESRI FileGDB" ),
1516  "*.gdb",
1517  "gdb",
1518  datasetOptions,
1519  layerOptions
1520  )
1521  );
1522  return driverMetadata;
1523 }
1524 
1525 bool QgsVectorFileWriter::driverMetadata( const QString& driverName, QgsVectorFileWriter::MetaData& driverMetadata )
1526 {
1527  static const QMap<QString, MetaData> sDriverMetadata = initMetaData();
1528 
1529  QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.constBegin();
1530 
1531  for ( ; it != sDriverMetadata.constEnd(); ++it )
1532  {
1533  if ( it.key().startsWith( driverName ) )
1534  {
1535  driverMetadata = it.value();
1536  return true;
1537  }
1538  }
1539 
1540  return false;
1541 }
1542 
1543 
1545 {
1546  return mError;
1547 }
1548 
1550 {
1551  return mErrorMessage;
1552 }
1553 
1555 {
1556  // create the feature
1557  OGRFeatureH poFeature = createFeature( feature );
1558  if ( !poFeature )
1559  return false;
1560 
1561  //add OGR feature style type
1562  if ( mSymbologyExport != NoSymbology && renderer )
1563  {
1564  //SymbolLayerSymbology: concatenate ogr styles of all symbollayers
1565  QgsSymbolV2List symbols = renderer->symbolsForFeature( feature );
1566  QString styleString;
1567  QString currentStyle;
1568 
1569  QgsSymbolV2List::const_iterator symbolIt = symbols.constBegin();
1570  for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
1571  {
1572  int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
1573  for ( int i = 0; i < nSymbolLayers; ++i )
1574  {
1575 #if 0
1576  QMap< QgsSymbolLayerV2*, QString >::const_iterator it = mSymbolLayerTable.find(( *symbolIt )->symbolLayer( i ) );
1577  if ( it == mSymbolLayerTable.constEnd() )
1578  {
1579  continue;
1580  }
1581 #endif
1582  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
1583  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
1584 
1585  currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );//"@" + it.value();
1586 
1588  {
1589  if ( symbolIt != symbols.constBegin() || i != 0 )
1590  {
1591  styleString.append( ";" );
1592  }
1593  styleString.append( currentStyle );
1594  }
1595  else if ( mSymbologyExport == SymbolLayerSymbology )
1596  {
1597  OGR_F_SetStyleString( poFeature, currentStyle.toLocal8Bit().data() );
1598  if ( !writeFeature( mLayer, poFeature ) )
1599  {
1600  return false;
1601  }
1602  }
1603  }
1604  }
1605  OGR_F_SetStyleString( poFeature, styleString.toLocal8Bit().data() );
1606  }
1607 
1609  {
1610  if ( !writeFeature( mLayer, poFeature ) )
1611  {
1612  return false;
1613  }
1614  }
1615 
1616  OGR_F_Destroy( poFeature );
1617  return true;
1618 }
1619 
1621 {
1622  OGRFeatureH poFeature = OGR_F_Create( OGR_L_GetLayerDefn( mLayer ) );
1623 
1624  qint64 fid = FID_TO_NUMBER( feature.id() );
1625  if ( fid > std::numeric_limits<int>::max() )
1626  {
1627  QgsDebugMsg( QString( "feature id %1 too large." ).arg( fid ) );
1628  OGRErr err = OGR_F_SetFID( poFeature, static_cast<long>( fid ) );
1629  if ( err != OGRERR_NONE )
1630  {
1631  QgsDebugMsg( QString( "Failed to set feature id to %1: %2 (OGR error: %3)" )
1632  .arg( feature.id() )
1633  .arg( err ).arg( CPLGetLastErrorMsg() )
1634  );
1635  }
1636  }
1637 
1638  // attribute handling
1639  for ( int fldIdx = 0; fldIdx < mFields.count(); ++fldIdx )
1640  {
1641  if ( !mAttrIdxToOgrIdx.contains( fldIdx ) )
1642  {
1643  QgsDebugMsg( QString( "no ogr field for field %1" ).arg( fldIdx ) );
1644  continue;
1645  }
1646 
1647  const QVariant& attrValue = feature.attribute( fldIdx );
1648  int ogrField = mAttrIdxToOgrIdx[ fldIdx ];
1649 
1650  if ( !attrValue.isValid() || attrValue.isNull() )
1651  continue;
1652 
1653  switch ( attrValue.type() )
1654  {
1655  case QVariant::Int:
1656  OGR_F_SetFieldInteger( poFeature, ogrField, attrValue.toInt() );
1657  break;
1658  case QVariant::Double:
1659  OGR_F_SetFieldDouble( poFeature, ogrField, attrValue.toDouble() );
1660  break;
1661  case QVariant::LongLong:
1662  case QVariant::String:
1663  OGR_F_SetFieldString( poFeature, ogrField, mCodec->fromUnicode( attrValue.toString() ).data() );
1664  break;
1665  case QVariant::Date:
1666  OGR_F_SetFieldDateTime( poFeature, ogrField,
1667  attrValue.toDate().year(),
1668  attrValue.toDate().month(),
1669  attrValue.toDate().day(),
1670  0, 0, 0, 0 );
1671  break;
1672  case QVariant::DateTime:
1673  OGR_F_SetFieldDateTime( poFeature, ogrField,
1674  attrValue.toDateTime().date().year(),
1675  attrValue.toDateTime().date().month(),
1676  attrValue.toDateTime().date().day(),
1677  attrValue.toDateTime().time().hour(),
1678  attrValue.toDateTime().time().minute(),
1679  attrValue.toDateTime().time().second(),
1680  0 );
1681  break;
1682  case QVariant::Invalid:
1683  break;
1684  default:
1685  mErrorMessage = QObject::tr( "Invalid variant type for field %1[%2]: received %3 with type %4" )
1686  .arg( mFields[fldIdx].name() )
1687  .arg( ogrField )
1688  .arg( QMetaType::typeName( attrValue.type() ) )
1689  .arg( attrValue.toString() );
1692  return 0;
1693  }
1694  }
1695 
1696  if ( mWkbType != QGis::WKBNoGeometry )
1697  {
1698  // build geometry from WKB
1699  QgsGeometry *geom = feature.geometry();
1700 
1701  // turn single geoemetry to multi geometry if needed
1702  if ( geom && geom->wkbType() != mWkbType && geom->wkbType() == QGis::singleType( mWkbType ) )
1703  {
1704  geom->convertToMultiType();
1705  }
1706 
1707  if ( geom && geom->wkbType() != mWkbType )
1708  {
1709  // there's a problem when layer type is set as wkbtype Polygon
1710  // although there are also features of type MultiPolygon
1711  // (at least in OGR provider)
1712  // If the feature's wkbtype is different from the layer's wkbtype,
1713  // try to export it too.
1714  //
1715  // Btw. OGRGeometry must be exactly of the type of the geometry which it will receive
1716  // i.e. Polygons can't be imported to OGRMultiPolygon
1717 
1718  OGRGeometryH mGeom2 = createEmptyGeometry( geom->wkbType() );
1719 
1720  if ( !mGeom2 )
1721  {
1722  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1723  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1726  OGR_F_Destroy( poFeature );
1727  return 0;
1728  }
1729 
1730  OGRErr err = OGR_G_ImportFromWkb( mGeom2, const_cast<unsigned char *>( geom->asWkb() ), ( int ) geom->wkbSize() );
1731  if ( err != OGRERR_NONE )
1732  {
1733  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1734  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1737  OGR_F_Destroy( poFeature );
1738  return 0;
1739  }
1740 
1741  // pass ownership to geometry
1742  OGR_F_SetGeometryDirectly( poFeature, mGeom2 );
1743  }
1744  else if ( geom )
1745  {
1746  OGRErr err = OGR_G_ImportFromWkb( mGeom, const_cast<unsigned char *>( geom->asWkb() ), ( int ) geom->wkbSize() );
1747  if ( err != OGRERR_NONE )
1748  {
1749  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1750  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1753  OGR_F_Destroy( poFeature );
1754  return 0;
1755  }
1756 
1757  // set geometry (ownership is not passed to OGR)
1758  OGR_F_SetGeometry( poFeature, mGeom );
1759  }
1760  }
1761  return poFeature;
1762 }
1763 
1764 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
1765 {
1766  if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
1767  {
1768  mErrorMessage = QObject::tr( "Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1771  OGR_F_Destroy( feature );
1772  return false;
1773  }
1774  return true;
1775 }
1776 
1778 {
1779  if ( mGeom )
1780  {
1781  OGR_G_DestroyGeometry( mGeom );
1782  }
1783 
1784  if ( mDS )
1785  {
1786  OGR_DS_Destroy( mDS );
1787  }
1788 }
1789 
1792  const QString& fileName,
1793  const QString& fileEncoding,
1794  const QgsCoordinateReferenceSystem *destCRS,
1795  const QString& driverName,
1796  bool onlySelected,
1797  QString *errorMessage,
1798  const QStringList &datasourceOptions,
1799  const QStringList &layerOptions,
1800  bool skipAttributeCreation,
1801  QString *newFilename,
1802  SymbologyExport symbologyExport,
1803  double symbologyScale,
1804  const QgsRectangle* filterExtent )
1805 {
1806  QgsCoordinateTransform* ct = 0;
1807  if ( destCRS && layer )
1808  {
1809  ct = new QgsCoordinateTransform( layer->crs(), *destCRS );
1810  }
1811 
1812  QgsVectorFileWriter::WriterError error = writeAsVectorFormat( layer, fileName, fileEncoding, ct, driverName, onlySelected,
1813  errorMessage, datasourceOptions, layerOptions, skipAttributeCreation, newFilename, symbologyExport, symbologyScale, filterExtent );
1814  delete ct;
1815  return error;
1816 }
1817 
1819  const QString& fileName,
1820  const QString& fileEncoding,
1821  const QgsCoordinateTransform* ct,
1822  const QString& driverName,
1823  bool onlySelected,
1824  QString *errorMessage,
1825  const QStringList &datasourceOptions,
1826  const QStringList &layerOptions,
1827  bool skipAttributeCreation,
1828  QString *newFilename,
1829  SymbologyExport symbologyExport,
1830  double symbologyScale,
1831  const QgsRectangle* filterExtent )
1832 {
1833  if ( !layer )
1834  {
1835  return ErrInvalidLayer;
1836  }
1837 
1838  bool shallTransform = false;
1839  const QgsCoordinateReferenceSystem* outputCRS = 0;
1840  if ( ct )
1841  {
1842  // This means we should transform
1843  outputCRS = &( ct->destCRS() );
1844  shallTransform = true;
1845  }
1846  else
1847  {
1848  // This means we shouldn't transform, use source CRS as output (if defined)
1849  outputCRS = &layer->crs();
1850  }
1851 
1852  if ( layer->providerType() == "ogr" )
1853  {
1854  QStringList theURIParts = layer->dataProvider()->dataSourceUri().split( "|" );
1855  QString srcFileName = theURIParts[0];
1856 
1857  if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
1858  {
1859  if ( errorMessage )
1860  *errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
1861  return ErrCreateDataSource;
1862  }
1863  }
1864 
1865  QgsVectorFileWriter* writer =
1866  new QgsVectorFileWriter( fileName, fileEncoding, skipAttributeCreation ? QgsFields() : layer->pendingFields(), layer->wkbType(), outputCRS, driverName, datasourceOptions, layerOptions, newFilename, symbologyExport );
1867  writer->setSymbologyScaleDenominator( symbologyScale );
1868 
1869  if ( newFilename )
1870  {
1871  QgsDebugMsg( "newFilename = " + *newFilename );
1872  }
1873 
1874  // check whether file creation was successful
1875  WriterError err = writer->hasError();
1876  if ( err != NoError )
1877  {
1878  if ( errorMessage )
1879  *errorMessage = writer->errorMessage();
1880  delete writer;
1881  return err;
1882  }
1883 
1884  if ( errorMessage )
1885  {
1886  errorMessage->clear();
1887  }
1888 
1889  QgsAttributeList allAttr = skipAttributeCreation ? QgsAttributeList() : layer->pendingAllAttributesList();
1890  QgsFeature fet;
1891 
1892  //add possible attributes needed by renderer
1893  writer->addRendererAttributes( layer, allAttr );
1894 
1895  QgsFeatureRequest req;
1896  if ( layer->wkbType() == QGis::WKBNoGeometry )
1897  {
1899  }
1900  req.setSubsetOfAttributes( allAttr );
1901  QgsFeatureIterator fit = layer->getFeatures( req );
1902 
1903  const QgsFeatureIds& ids = layer->selectedFeaturesIds();
1904 
1905  //create symbol table if needed
1906  if ( writer->symbologyExport() != NoSymbology )
1907  {
1908  //writer->createSymbolLayerTable( layer, writer->mDS );
1909  }
1910 
1911  if ( writer->symbologyExport() == SymbolLayerSymbology )
1912  {
1913  QgsFeatureRendererV2* r = layer->rendererV2();
1915  && r->usingSymbolLevels() )
1916  {
1917  QgsVectorFileWriter::WriterError error = writer->exportFeaturesSymbolLevels( layer, fit, ct, errorMessage );
1918  delete writer;
1919  delete ct;
1920  return ( error == NoError ) ? NoError : ErrFeatureWriteFailed;
1921  }
1922  }
1923 
1924  int n = 0, errors = 0;
1925 
1926  //unit type
1927  QGis::UnitType mapUnits = layer->crs().mapUnits();
1928  if ( ct )
1929  {
1930  mapUnits = ct->destCRS().mapUnits();
1931  }
1932 
1933  writer->startRender( layer );
1934 
1935  // enabling transaction on databases that support it
1936  bool transactionsEnabled = true;
1937 
1938  if ( OGRERR_NONE != OGR_L_StartTransaction( writer->mLayer ) )
1939  {
1940  QgsDebugMsg( "Error when trying to enable transactions on OGRLayer." );
1941  transactionsEnabled = false;
1942  }
1943 
1944  // write all features
1945  while ( fit.nextFeature( fet ) )
1946  {
1947  if ( onlySelected && !ids.contains( fet.id() ) )
1948  continue;
1949 
1950  if ( shallTransform )
1951  {
1952  try
1953  {
1954  if ( fet.geometry() )
1955  {
1956  fet.geometry()->transform( *ct );
1957  }
1958  }
1959  catch ( QgsCsException &e )
1960  {
1961  delete ct;
1962  delete writer;
1963 
1964  QString msg = QObject::tr( "Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
1965  .arg( fet.id() ).arg( e.what() );
1966  QgsLogger::warning( msg );
1967  if ( errorMessage )
1968  *errorMessage = msg;
1969 
1970  return ErrProjection;
1971  }
1972  }
1973 
1974  if ( fet.geometry() && filterExtent && !fet.geometry()->intersects( *filterExtent ) )
1975  continue;
1976 
1977  if ( allAttr.size() < 1 && skipAttributeCreation )
1978  {
1979  fet.initAttributes( 0 );
1980  }
1981 
1982  if ( !writer->addFeature( fet, layer->rendererV2(), mapUnits ) )
1983  {
1984  WriterError err = writer->hasError();
1985  if ( err != NoError && errorMessage )
1986  {
1987  if ( errorMessage->isEmpty() )
1988  {
1989  *errorMessage = QObject::tr( "Feature write errors:" );
1990  }
1991  *errorMessage += "\n" + writer->errorMessage();
1992  }
1993  errors++;
1994 
1995  if ( errors > 1000 )
1996  {
1997  if ( errorMessage )
1998  {
1999  *errorMessage += QObject::tr( "Stopping after %1 errors" ).arg( errors );
2000  }
2001 
2002  n = -1;
2003  break;
2004  }
2005  }
2006  n++;
2007  }
2008 
2009  if ( transactionsEnabled )
2010  {
2011  if ( OGRERR_NONE != OGR_L_CommitTransaction( writer->mLayer ) )
2012  {
2013  QgsDebugMsg( "Error while committing transaction on OGRLayer." );
2014  }
2015  }
2016 
2017  writer->stopRender( layer );
2018  delete writer;
2019 
2020  if ( errors > 0 && errorMessage && n > 0 )
2021  {
2022  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
2023  }
2024 
2025  return errors == 0 ? NoError : ErrFeatureWriteFailed;
2026 }
2027 
2028 
2029 bool QgsVectorFileWriter::deleteShapeFile( QString theFileName )
2030 {
2031  QFileInfo fi( theFileName );
2032  QDir dir = fi.dir();
2033 
2034  QStringList filter;
2035  const char *suffixes[] = { ".shp", ".shx", ".dbf", ".prj", ".qix", ".qpj" };
2036  for ( std::size_t i = 0; i < sizeof( suffixes ) / sizeof( *suffixes ); i++ )
2037  {
2038  filter << fi.completeBaseName() + suffixes[i];
2039  }
2040 
2041  bool ok = true;
2042  foreach ( QString file, dir.entryList( filter ) )
2043  {
2044  if ( !QFile::remove( dir.canonicalPath() + "/" + file ) )
2045  {
2046  QgsDebugMsg( "Removing file failed : " + file );
2047  ok = false;
2048  }
2049  }
2050 
2051  return ok;
2052 }
2053 
2055 {
2056  QMap<QString, QString> resultMap;
2057 
2059  int const drvCount = OGRGetDriverCount();
2060 
2061  for ( int i = 0; i < drvCount; ++i )
2062  {
2063  OGRSFDriverH drv = OGRGetDriver( i );
2064  if ( drv )
2065  {
2066  QString drvName = OGR_Dr_GetName( drv );
2067  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
2068  {
2069  QString filterString = filterForDriver( drvName );
2070  if ( filterString.isEmpty() )
2071  continue;
2072 
2073  resultMap.insert( filterString, drvName );
2074  }
2075  }
2076  }
2077 
2078  return resultMap;
2079 }
2080 
2081 QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
2082 {
2083  QMap<QString, QString> resultMap;
2084 
2086  int const drvCount = OGRGetDriverCount();
2087 
2088  QStringList writableDrivers;
2089  for ( int i = 0; i < drvCount; ++i )
2090  {
2091  OGRSFDriverH drv = OGRGetDriver( i );
2092  if ( drv )
2093  {
2094  QString drvName = OGR_Dr_GetName( drv );
2095  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
2096  {
2097  // Add separate format for Mapinfo MIF (MITAB is OGR default)
2098  if ( drvName == "MapInfo File" )
2099  {
2100  writableDrivers << "MapInfo MIF";
2101  }
2102  else if ( drvName == "SQLite" )
2103  {
2104  // Unfortunately it seems that there is no simple way to detect if
2105  // OGR SQLite driver is compiled with SpatiaLite support.
2106  // We have HAVE_SPATIALITE in QGIS, but that may differ from OGR
2107  // http://lists.osgeo.org/pipermail/gdal-dev/2012-November/034580.html
2108  // -> test if creation failes
2109  QString option = "SPATIALITE=YES";
2110  char **options = new char *[2];
2111  options[0] = CPLStrdup( option.toLocal8Bit().data() );
2112  options[1] = NULL;
2113  OGRSFDriverH poDriver;
2115  poDriver = OGRGetDriverByName( drvName.toLocal8Bit().data() );
2116  if ( poDriver )
2117  {
2118  OGRDataSourceH ds = OGR_Dr_CreateDataSource( poDriver, TO8F( QString( "/vsimem/spatialitetest.sqlite" ) ), options );
2119  if ( ds )
2120  {
2121  writableDrivers << "SpatiaLite";
2122  OGR_Dr_DeleteDataSource( poDriver, TO8F( QString( "/vsimem/spatialitetest.sqlite" ) ) );
2123  OGR_DS_Destroy( ds );
2124  }
2125  }
2126  CPLFree( options[0] );
2127  delete [] options;
2128  }
2129  else if ( drvName == "ESRI Shapefile" )
2130  {
2131  writableDrivers << "DBF file";
2132  }
2133  writableDrivers << drvName;
2134  }
2135  }
2136  }
2137 
2138  foreach ( QString drvName, writableDrivers )
2139  {
2140  QString longName;
2141  QString trLongName;
2142  QString glob;
2143  QString exts;
2144  if ( QgsVectorFileWriter::driverMetadata( drvName, longName, trLongName, glob, exts ) && !trLongName.isEmpty() )
2145  {
2146  resultMap.insert( trLongName, drvName );
2147  }
2148  }
2149 
2150  return resultMap;
2151 }
2152 
2154 {
2155  QString filterString;
2156  QMap< QString, QString> driverFormatMap = supportedFiltersAndFormats();
2157  QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
2158  for ( ; it != driverFormatMap.constEnd(); ++it )
2159  {
2160  if ( filterString.isEmpty() )
2161  filterString += ";;";
2162 
2163  filterString += it.key();
2164  }
2165  return filterString;
2166 }
2167 
2168 QString QgsVectorFileWriter::filterForDriver( const QString& driverName )
2169 {
2170  QString longName;
2171  QString trLongName;
2172  QString glob;
2173  QString exts;
2174  if ( !driverMetadata( driverName, longName, trLongName, glob, exts ) || trLongName.isEmpty() || glob.isEmpty() )
2175  return "";
2176 
2177  return trLongName + " [OGR] (" + glob.toLower() + " " + glob.toUpper() + ")";
2178 }
2179 
2181 {
2182  if ( codecName == "System" )
2183  return QString( "LDID/0" );
2184 
2185  QRegExp re = QRegExp( QString( "(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
2186  if ( re.exactMatch( codecName ) )
2187  {
2188  QString c = re.cap( 2 ).replace( "-" , "" );
2189  bool isNumber;
2190  c.toInt( &isNumber );
2191  if ( isNumber )
2192  return c;
2193  }
2194  return codecName;
2195 }
2196 
2197 bool QgsVectorFileWriter::driverMetadata( QString driverName, QString &longName, QString &trLongName, QString &glob, QString &ext )
2198 {
2199  if ( driverName.startsWith( "AVCE00" ) )
2200  {
2201  longName = "Arc/Info ASCII Coverage";
2202  trLongName = QObject::tr( "Arc/Info ASCII Coverage" );
2203  glob = "*.e00";
2204  ext = "e00";
2205  }
2206  else if ( driverName.startsWith( "BNA" ) )
2207  {
2208  longName = "Atlas BNA";
2209  trLongName = QObject::tr( "Atlas BNA" );
2210  glob = "*.bna";
2211  ext = "bna";
2212  }
2213  else if ( driverName.startsWith( "CSV" ) )
2214  {
2215  longName = "Comma Separated Value";
2216  trLongName = QObject::tr( "Comma Separated Value" );
2217  glob = "*.csv";
2218  ext = "csv";
2219  }
2220  else if ( driverName.startsWith( "ESRI" ) )
2221  {
2222  longName = "ESRI Shapefile";
2223  trLongName = QObject::tr( "ESRI Shapefile" );
2224  glob = "*.shp";
2225  ext = "shp";
2226  }
2227  else if ( driverName.startsWith( "DBF file" ) )
2228  {
2229  longName = "DBF File";
2230  trLongName = QObject::tr( "DBF file" );
2231  glob = "*.dbf";
2232  ext = "dbf";
2233  }
2234  else if ( driverName.startsWith( "FMEObjects Gateway" ) )
2235  {
2236  longName = "FMEObjects Gateway";
2237  trLongName = QObject::tr( "FMEObjects Gateway" );
2238  glob = "*.fdd";
2239  ext = "fdd";
2240  }
2241  else if ( driverName.startsWith( "GeoJSON" ) )
2242  {
2243  longName = "GeoJSON";
2244  trLongName = QObject::tr( "GeoJSON" );
2245  glob = "*.geojson";
2246  ext = "geojson";
2247  }
2248  else if ( driverName.startsWith( "GeoRSS" ) )
2249  {
2250  longName = "GeoRSS";
2251  trLongName = QObject::tr( "GeoRSS" );
2252  glob = "*.xml";
2253  ext = "xml";
2254  }
2255  else if ( driverName.startsWith( "GML" ) )
2256  {
2257  longName = "Geography Markup Language [GML]";
2258  trLongName = QObject::tr( "Geography Markup Language [GML]" );
2259  glob = "*.gml";
2260  ext = "gml";
2261  }
2262  else if ( driverName.startsWith( "GMT" ) )
2263  {
2264  longName = "Generic Mapping Tools [GMT]";
2265  trLongName = QObject::tr( "Generic Mapping Tools [GMT]" );
2266  glob = "*.gmt";
2267  ext = "gmt";
2268  }
2269  else if ( driverName.startsWith( "GPX" ) )
2270  {
2271  longName = "GPS eXchange Format [GPX]";
2272  trLongName = QObject::tr( "GPS eXchange Format [GPX]" );
2273  glob = "*.gpx";
2274  ext = "gpx";
2275  }
2276  else if ( driverName.startsWith( "Interlis 1" ) )
2277  {
2278  longName = "INTERLIS 1";
2279  trLongName = QObject::tr( "INTERLIS 1" );
2280  glob = "*.itf *.xml *.ili";
2281  ext = "ili";
2282  }
2283  else if ( driverName.startsWith( "Interlis 2" ) )
2284  {
2285  longName = "INTERLIS 2";
2286  trLongName = QObject::tr( "INTERLIS 2" );
2287  glob = "*.itf *.xml *.ili";
2288  ext = "ili";
2289  }
2290  else if ( driverName.startsWith( "KML" ) )
2291  {
2292  longName = "Keyhole Markup Language [KML]";
2293  trLongName = QObject::tr( "Keyhole Markup Language [KML]" );
2294  glob = "*.kml" ;
2295  ext = "kml" ;
2296  }
2297  else if ( driverName.startsWith( "MapInfo File" ) )
2298  {
2299  longName = "Mapinfo TAB";
2300  trLongName = QObject::tr( "Mapinfo TAB" );
2301  glob = "*.tab";
2302  ext = "tab";
2303  }
2304  // 'MapInfo MIF' is internal QGIS addition to distinguish between MITAB and MIF
2305  else if ( driverName.startsWith( "MapInfo MIF" ) )
2306  {
2307  longName = "Mapinfo MIF";
2308  trLongName = QObject::tr( "Mapinfo MIF" );
2309  glob = "*.mif";
2310  ext = "mif";
2311  }
2312  else if ( driverName.startsWith( "DGN" ) )
2313  {
2314  longName = "Microstation DGN";
2315  trLongName = QObject::tr( "Microstation DGN" );
2316  glob = "*.dgn";
2317  ext = "dgn";
2318  }
2319  else if ( driverName.startsWith( "S57" ) )
2320  {
2321  longName = "S-57 Base file";
2322  trLongName = QObject::tr( "S-57 Base file" );
2323  glob = "*.000";
2324  ext = "000";
2325  }
2326  else if ( driverName.startsWith( "SDTS" ) )
2327  {
2328  longName = "Spatial Data Transfer Standard [SDTS]";
2329  trLongName = QObject::tr( "Spatial Data Transfer Standard [SDTS]" );
2330  glob = "*catd.ddf";
2331  ext = "ddf";
2332  }
2333  else if ( driverName.startsWith( "SQLite" ) )
2334  {
2335  longName = "SQLite";
2336  trLongName = QObject::tr( "SQLite" );
2337  glob = "*.sqlite";
2338  ext = "sqlite";
2339  }
2340  // QGIS internal addition for SpatialLite
2341  else if ( driverName.startsWith( "SpatiaLite" ) )
2342  {
2343  longName = "SpatiaLite";
2344  trLongName = QObject::tr( "SpatiaLite" );
2345  glob = "*.sqlite";
2346  ext = "sqlite";
2347  }
2348  else if ( driverName.startsWith( "DXF" ) )
2349  {
2350  longName = "AutoCAD DXF";
2351  trLongName = QObject::tr( "AutoCAD DXF" );
2352  glob = "*.dxf";
2353  ext = "dxf";
2354  }
2355  else if ( driverName.startsWith( "Geoconcept" ) )
2356  {
2357  longName = "Geoconcept";
2358  trLongName = QObject::tr( "Geoconcept" );
2359  glob = "*.gxt *.txt";
2360  ext = "gxt";
2361  }
2362  else if ( driverName.startsWith( "FileGDB" ) )
2363  {
2364  longName = "ESRI FileGDB";
2365  trLongName = QObject::tr( "ESRI FileGDB" );
2366  glob = "*.gdb";
2367  ext = "gdb";
2368  }
2369  else
2370  {
2371  return false;
2372  }
2373 
2374  return true;
2375 }
2376 
2378 {
2379  if ( !vl || !ds )
2380  {
2381  return;
2382  }
2383 
2384  QgsFeatureRendererV2* renderer = vl->rendererV2();
2385  if ( !renderer )
2386  {
2387  return;
2388  }
2389 
2390  //unit type
2391  QGis::UnitType mapUnits = vl->crs().mapUnits();
2392  if ( ct )
2393  {
2394  mapUnits = ct->destCRS().mapUnits();
2395  }
2396 
2397 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1700
2398  mSymbolLayerTable.clear();
2399  OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
2400  OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
2401 
2402  //get symbols
2403  int nTotalLevels = 0;
2404  QgsSymbolV2List symbolList = renderer->symbols();
2405  QgsSymbolV2List::iterator symbolIt = symbolList.begin();
2406  for ( ; symbolIt != symbolList.end(); ++symbolIt )
2407  {
2408  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits );
2409  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits );
2410 
2411  int nLevels = ( *symbolIt )->symbolLayerCount();
2412  for ( int i = 0; i < nLevels; ++i )
2413  {
2414  mSymbolLayerTable.insert(( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
2415  OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
2416  ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
2417  ++nTotalLevels;
2418  }
2419  }
2420  OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
2421 #endif
2422 }
2423 
2425  const QgsCoordinateTransform* ct, QString* errorMessage )
2426 {
2427  if ( !layer )
2428  {
2429  //return error
2430  }
2431  QgsFeatureRendererV2* renderer = layer->rendererV2();
2432  if ( !renderer )
2433  {
2434  //return error
2435  }
2436  QHash< QgsSymbolV2*, QList<QgsFeature> > features;
2437 
2438  //unit type
2439  QGis::UnitType mapUnits = layer->crs().mapUnits();
2440  if ( ct )
2441  {
2442  mapUnits = ct->destCRS().mapUnits();
2443  }
2444 
2445  startRender( layer );
2446 
2447  //fetch features
2448  QgsFeature fet;
2449  QgsSymbolV2* featureSymbol = 0;
2450  while ( fit.nextFeature( fet ) )
2451  {
2452  if ( ct )
2453  {
2454  try
2455  {
2456  if ( fet.geometry() )
2457  {
2458  fet.geometry()->transform( *ct );
2459  }
2460  }
2461  catch ( QgsCsException &e )
2462  {
2463  delete ct;
2464 
2465  QString msg = QObject::tr( "Failed to transform, writing stopped. (Exception: %1)" )
2466  .arg( e.what() );
2467  QgsLogger::warning( msg );
2468  if ( errorMessage )
2469  *errorMessage = msg;
2470 
2471  return ErrProjection;
2472  }
2473  }
2474 
2475  featureSymbol = renderer->symbolForFeature( fet );
2476  if ( !featureSymbol )
2477  {
2478  continue;
2479  }
2480 
2481  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
2482  if ( it == features.end() )
2483  {
2484  it = features.insert( featureSymbol, QList<QgsFeature>() );
2485  }
2486  it.value().append( fet );
2487  }
2488 
2489  //find out order
2490  QgsSymbolV2LevelOrder levels;
2491  QgsSymbolV2List symbols = renderer->symbols();
2492  for ( int i = 0; i < symbols.count(); i++ )
2493  {
2494  QgsSymbolV2* sym = symbols[i];
2495  for ( int j = 0; j < sym->symbolLayerCount(); j++ )
2496  {
2497  int level = sym->symbolLayer( j )->renderingPass();
2498  if ( level < 0 || level >= 1000 ) // ignore invalid levels
2499  continue;
2500  QgsSymbolV2LevelItem item( sym, j );
2501  while ( level >= levels.count() ) // append new empty levels
2502  levels.append( QgsSymbolV2Level() );
2503  levels[level].append( item );
2504  }
2505  }
2506 
2507  int nErrors = 0;
2508  int nTotalFeatures = 0;
2509 
2510  //export symbol layers and symbology
2511  for ( int l = 0; l < levels.count(); l++ )
2512  {
2513  QgsSymbolV2Level& level = levels[l];
2514  for ( int i = 0; i < level.count(); i++ )
2515  {
2516  QgsSymbolV2LevelItem& item = level[i];
2517  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
2518  if ( levelIt == features.end() )
2519  {
2520  ++nErrors;
2521  continue;
2522  }
2523 
2524  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(), mapUnits );
2525  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(), mapUnits );
2526 
2527  int llayer = item.layer();
2528  QList<QgsFeature>& featureList = levelIt.value();
2529  QList<QgsFeature>::iterator featureIt = featureList.begin();
2530  for ( ; featureIt != featureList.end(); ++featureIt )
2531  {
2532  ++nTotalFeatures;
2533  OGRFeatureH ogrFeature = createFeature( *featureIt );
2534  if ( !ogrFeature )
2535  {
2536  ++nErrors;
2537  continue;
2538  }
2539 
2540  QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
2541  if ( !styleString.isEmpty() )
2542  {
2543  OGR_F_SetStyleString( ogrFeature, styleString.toLocal8Bit().data() );
2544  if ( ! writeFeature( mLayer, ogrFeature ) )
2545  {
2546  ++nErrors;
2547  }
2548  }
2549  OGR_F_Destroy( ogrFeature );
2550  }
2551  }
2552  }
2553 
2554  stopRender( layer );
2555 
2556  if ( nErrors > 0 && errorMessage )
2557  {
2558  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
2559  }
2560 
2562 }
2563 
2564 double QgsVectorFileWriter::mmScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
2565 {
2566  if ( symbolUnits == QgsSymbolV2::MM )
2567  {
2568  return 1.0;
2569  }
2570  else
2571  {
2572  //conversion factor map units -> mm
2573  if ( mapUnits == QGis::Meters )
2574  {
2575  return 1000 / scaleDenominator;
2576  }
2577 
2578  }
2579  return 1.0; //todo: map units
2580 }
2581 
2582 double QgsVectorFileWriter::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
2583 {
2584  if ( symbolUnits == QgsSymbolV2::MapUnit )
2585  {
2586  return 1.0;
2587  }
2588  else
2589  {
2590  if ( symbolUnits == QgsSymbolV2::MM && mapUnits == QGis::Meters )
2591  {
2592  return scaleDenominator / 1000;
2593  }
2594  }
2595  return 1.0;
2596 }
2597 
2599 {
2600  QgsRenderContext context;
2602  return context;
2603 }
2604 
2606 {
2607  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2608  if ( !renderer )
2609  {
2610  return;
2611  }
2612 
2614  renderer->startRender( ctx, vl->pendingFields() );
2615 }
2616 
2618 {
2619  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2620  if ( !renderer )
2621  {
2622  return;
2623  }
2624 
2626  renderer->stopRender( ctx );
2627 }
2628 
2630 {
2631  if ( mSymbologyExport == NoSymbology )
2632  {
2633  return 0;
2634  }
2635  if ( !vl )
2636  {
2637  return 0;
2638  }
2639 
2640  return vl->rendererV2();
2641 }
2642 
2644 {
2645  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2646  if ( renderer )
2647  {
2648  QList<QString> rendererAttributes = renderer->usedAttributes();
2649  for ( int i = 0; i < rendererAttributes.size(); ++i )
2650  {
2651  int index = vl->fieldNameIndex( rendererAttributes.at( i ) );
2652  if ( index != -1 )
2653  {
2654  attList.push_back( vl->fieldNameIndex( rendererAttributes.at( i ) ) );
2655  }
2656  }
2657  }
2658 }
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:58
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
void createSymbolLayerTable(QgsVectorLayer *vl, const QgsCoordinateTransform *ct, OGRDataSourceH ds)
bool writeFeature(OGRLayerH layer, OGRFeatureH feature)
WriterError mError
contains error value if construction was not successful
size_t wkbSize() const
Returns the size of the WKB in asWkb().
static QString fileFilterString()
Returns filter string that can be used for dialogs.
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
QSet< QgsFeatureId > QgsFeatureIds
Definition: qgsfeature.h:325
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:162
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:78
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:163
double mmScaleFactor(double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits)
void addRendererAttributes(QgsVectorLayer *vl, QgsAttributeList &attList)
Adds attributes needed for classification.
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)
double mapUnitScaleFactor(double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits)
void startRender(QgsVectorLayer *vl) const
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
OGRFeatureH createFeature(QgsFeature &feature)
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:200
QGis::WkbType wkbType() const
Returns type of wkb (point / linestring / polygon etc.)
void stopRender(QgsVectorLayer *vl) const
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
WriterError exportFeaturesSymbolLevels(QgsVectorLayer *layer, QgsFeatureIterator &fit, const QgsCoordinateTransform *ct, QString *errorMessage=0)
Writes features considering symbol level order.
QList< QgsSymbolV2LevelItem > QgsSymbolV2Level
Definition: qgsrendererv2.h:60
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
QgsRenderContext renderContext() const
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
static QMap< QString, MetaData > initMetaData()
virtual QgsSymbolV2List symbolsForFeature(QgsFeature &feat)
return list of symbols used for rendering the feature.
void setSymbologyScaleDenominator(double d)
QgsSymbolV2 * symbol()
Definition: qgsrendererv2.h:52
bool usingSymbolLevels() const
Class for storing a coordinate reference system (CRS)
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:73
int size() const
Return number of items.
Definition: qgsfield.h:202
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:63
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.
QgsFeatureRendererV2 * symbologyRenderer(QgsVectorLayer *vl) const
OGRGeometryH createEmptyGeometry(QGis::WkbType wkbType)
int max(int a, int b)
Definition: util.h:87
static QMap< QString, MetaData > sDriverMetadata
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.
void * OGRSpatialReferenceH
QVariant::Type type() const
Gets variant type of the field as it will be retrieved from data source.
Definition: qgsfield.cpp:63
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
#define tr(sourceText)