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