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