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