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