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