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