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