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