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