QGIS API Documentation  2.2.0-Valmiera
 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 use of the LINEFORMAT option." ),
584  QStringList()
585  << "AS_WKT"
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  << "CRLF"
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. Default value : COMMA" ),
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 
1552  //add OGR feature style type
1553  if ( mSymbologyExport != NoSymbology && renderer )
1554  {
1555  //SymbolLayerSymbology: concatenate ogr styles of all symbollayers
1556  QgsSymbolV2List symbols = renderer->symbolsForFeature( feature );
1557  QString styleString;
1558  QString currentStyle;
1559 
1560  QgsSymbolV2List::const_iterator symbolIt = symbols.constBegin();
1561  for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
1562  {
1563  int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
1564  for ( int i = 0; i < nSymbolLayers; ++i )
1565  {
1566 #if 0
1567  QMap< QgsSymbolLayerV2*, QString >::const_iterator it = mSymbolLayerTable.find(( *symbolIt )->symbolLayer( i ) );
1568  if ( it == mSymbolLayerTable.constEnd() )
1569  {
1570  continue;
1571  }
1572 #endif
1573  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
1574  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), outputUnit );
1575 
1576  currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );//"@" + it.value();
1577 
1579  {
1580  if ( symbolIt != symbols.constBegin() || i != 0 )
1581  {
1582  styleString.append( ";" );
1583  }
1584  styleString.append( currentStyle );
1585  }
1586  else if ( mSymbologyExport == SymbolLayerSymbology )
1587  {
1588  OGR_F_SetStyleString( poFeature, currentStyle.toLocal8Bit().data() );
1589  if ( !writeFeature( mLayer, poFeature ) )
1590  {
1591  return false;
1592  }
1593  }
1594  }
1595  }
1596  OGR_F_SetStyleString( poFeature, styleString.toLocal8Bit().data() );
1597  }
1598 
1600  {
1601  if ( !writeFeature( mLayer, poFeature ) )
1602  {
1603  return false;
1604  }
1605  }
1606 
1607  OGR_F_Destroy( poFeature );
1608  return true;
1609 }
1610 
1612 {
1613  OGRFeatureH poFeature = OGR_F_Create( OGR_L_GetLayerDefn( mLayer ) );
1614 
1615  qint64 fid = FID_TO_NUMBER( feature.id() );
1616  if ( fid > std::numeric_limits<int>::max() )
1617  {
1618  QgsDebugMsg( QString( "feature id %1 too large." ).arg( fid ) );
1619  OGRErr err = OGR_F_SetFID( poFeature, static_cast<long>( fid ) );
1620  if ( err != OGRERR_NONE )
1621  {
1622  QgsDebugMsg( QString( "Failed to set feature id to %1: %2 (OGR error: %3)" )
1623  .arg( feature.id() )
1624  .arg( err ).arg( CPLGetLastErrorMsg() )
1625  );
1626  }
1627  }
1628 
1629  // attribute handling
1630  for ( int fldIdx = 0; fldIdx < mFields.count(); ++fldIdx )
1631  {
1632  if ( !mAttrIdxToOgrIdx.contains( fldIdx ) )
1633  {
1634  QgsDebugMsg( QString( "no ogr field for field %1" ).arg( fldIdx ) );
1635  continue;
1636  }
1637 
1638  const QVariant& attrValue = feature.attribute( fldIdx );
1639  int ogrField = mAttrIdxToOgrIdx[ fldIdx ];
1640 
1641  if ( !attrValue.isValid() || attrValue.isNull() )
1642  continue;
1643 
1644  switch ( attrValue.type() )
1645  {
1646  case QVariant::Int:
1647  OGR_F_SetFieldInteger( poFeature, ogrField, attrValue.toInt() );
1648  break;
1649  case QVariant::Double:
1650  OGR_F_SetFieldDouble( poFeature, ogrField, attrValue.toDouble() );
1651  break;
1652  case QVariant::LongLong:
1653  case QVariant::String:
1654  OGR_F_SetFieldString( poFeature, ogrField, mCodec->fromUnicode( attrValue.toString() ).data() );
1655  break;
1656  case QVariant::Date:
1657  OGR_F_SetFieldDateTime( poFeature, ogrField,
1658  attrValue.toDate().year(),
1659  attrValue.toDate().month(),
1660  attrValue.toDate().day(),
1661  0, 0, 0, 0 );
1662  break;
1663  case QVariant::DateTime:
1664  OGR_F_SetFieldDateTime( poFeature, ogrField,
1665  attrValue.toDateTime().date().year(),
1666  attrValue.toDateTime().date().month(),
1667  attrValue.toDateTime().date().day(),
1668  attrValue.toDateTime().time().hour(),
1669  attrValue.toDateTime().time().minute(),
1670  attrValue.toDateTime().time().second(),
1671  0 );
1672  break;
1673  case QVariant::Invalid:
1674  break;
1675  default:
1676  mErrorMessage = QObject::tr( "Invalid variant type for field %1[%2]: received %3 with type %4" )
1677  .arg( mFields[fldIdx].name() )
1678  .arg( ogrField )
1679  .arg( QMetaType::typeName( attrValue.type() ) )
1680  .arg( attrValue.toString() );
1683  return 0;
1684  }
1685  }
1686 
1687  if ( mWkbType != QGis::WKBNoGeometry )
1688  {
1689  // build geometry from WKB
1690  QgsGeometry *geom = feature.geometry();
1691 
1692  // turn single geoemetry to multi geometry if needed
1693  if ( geom && geom->wkbType() != mWkbType && geom->wkbType() == QGis::singleType( mWkbType ) )
1694  {
1695  geom->convertToMultiType();
1696  }
1697 
1698  if ( geom && geom->wkbType() != mWkbType )
1699  {
1700  // there's a problem when layer type is set as wkbtype Polygon
1701  // although there are also features of type MultiPolygon
1702  // (at least in OGR provider)
1703  // If the feature's wkbtype is different from the layer's wkbtype,
1704  // try to export it too.
1705  //
1706  // Btw. OGRGeometry must be exactly of the type of the geometry which it will receive
1707  // i.e. Polygons can't be imported to OGRMultiPolygon
1708 
1709  OGRGeometryH mGeom2 = createEmptyGeometry( geom->wkbType() );
1710 
1711  if ( !mGeom2 )
1712  {
1713  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1714  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1717  OGR_F_Destroy( poFeature );
1718  return 0;
1719  }
1720 
1721  OGRErr err = OGR_G_ImportFromWkb( mGeom2, const_cast<unsigned char *>( geom->asWkb() ), ( int ) geom->wkbSize() );
1722  if ( err != OGRERR_NONE )
1723  {
1724  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1725  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1728  OGR_F_Destroy( poFeature );
1729  return 0;
1730  }
1731 
1732  // pass ownership to geometry
1733  OGR_F_SetGeometryDirectly( poFeature, mGeom2 );
1734  }
1735  else if ( geom )
1736  {
1737  OGRErr err = OGR_G_ImportFromWkb( mGeom, const_cast<unsigned char *>( geom->asWkb() ), ( int ) geom->wkbSize() );
1738  if ( err != OGRERR_NONE )
1739  {
1740  mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
1741  .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1744  OGR_F_Destroy( poFeature );
1745  return 0;
1746  }
1747 
1748  // set geometry (ownership is not passed to OGR)
1749  OGR_F_SetGeometry( poFeature, mGeom );
1750  }
1751  }
1752  return poFeature;
1753 }
1754 
1755 bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
1756 {
1757  if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
1758  {
1759  mErrorMessage = QObject::tr( "Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
1762  OGR_F_Destroy( feature );
1763  return false;
1764  }
1765  return true;
1766 }
1767 
1769 {
1770  if ( mGeom )
1771  {
1772  OGR_G_DestroyGeometry( mGeom );
1773  }
1774 
1775  if ( mDS )
1776  {
1777  OGR_DS_Destroy( mDS );
1778  }
1779 }
1780 
1783  const QString& fileName,
1784  const QString& fileEncoding,
1785  const QgsCoordinateReferenceSystem *destCRS,
1786  const QString& driverName,
1787  bool onlySelected,
1788  QString *errorMessage,
1789  const QStringList &datasourceOptions,
1790  const QStringList &layerOptions,
1791  bool skipAttributeCreation,
1792  QString *newFilename,
1793  SymbologyExport symbologyExport,
1794  double symbologyScale )
1795 {
1796  QgsCoordinateTransform* ct = 0;
1797  if ( destCRS && layer )
1798  {
1799  ct = new QgsCoordinateTransform( layer->crs(), *destCRS );
1800  }
1801 
1802  QgsVectorFileWriter::WriterError error = writeAsVectorFormat( layer, fileName, fileEncoding, ct, driverName, onlySelected,
1803  errorMessage, datasourceOptions, layerOptions, skipAttributeCreation, newFilename, symbologyExport, symbologyScale );
1804  delete ct;
1805  return error;
1806 }
1807 
1809  const QString& fileName,
1810  const QString& fileEncoding,
1811  const QgsCoordinateTransform* ct,
1812  const QString& driverName,
1813  bool onlySelected,
1814  QString *errorMessage,
1815  const QStringList &datasourceOptions, // added in 1.6
1816  const QStringList &layerOptions, // added in 1.6
1817  bool skipAttributeCreation, // added in 1.6
1818  QString *newFilename, // added in 1.9
1819  SymbologyExport symbologyExport, //added in 2.0
1820  double symbologyScale // added in 2.0
1821  )
1822 {
1823  if ( !layer )
1824  {
1825  return ErrInvalidLayer;
1826  }
1827 
1828  bool shallTransform = false;
1829  const QgsCoordinateReferenceSystem* outputCRS = 0;
1830  if ( ct )
1831  {
1832  // This means we should transform
1833  outputCRS = &( ct->destCRS() );
1834  shallTransform = true;
1835  }
1836  else
1837  {
1838  // This means we shouldn't transform, use source CRS as output (if defined)
1839  outputCRS = &layer->crs();
1840  }
1841 
1842  if ( layer->providerType() == "ogr" )
1843  {
1844  QStringList theURIParts = layer->dataProvider()->dataSourceUri().split( "|" );
1845  QString srcFileName = theURIParts[0];
1846 
1847  if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
1848  {
1849  if ( errorMessage )
1850  *errorMessage = QObject::tr( "Cannot overwrite a OGR layer in place" );
1851  return ErrCreateDataSource;
1852  }
1853  }
1854 
1855  QgsVectorFileWriter* writer =
1856  new QgsVectorFileWriter( fileName, fileEncoding, skipAttributeCreation ? QgsFields() : layer->pendingFields(), layer->wkbType(), outputCRS, driverName, datasourceOptions, layerOptions, newFilename, symbologyExport );
1857  writer->setSymbologyScaleDenominator( symbologyScale );
1858 
1859  if ( newFilename )
1860  {
1861  QgsDebugMsg( "newFilename = " + *newFilename );
1862  }
1863 
1864  // check whether file creation was successful
1865  WriterError err = writer->hasError();
1866  if ( err != NoError )
1867  {
1868  if ( errorMessage )
1869  *errorMessage = writer->errorMessage();
1870  delete writer;
1871  return err;
1872  }
1873 
1874  if ( errorMessage )
1875  {
1876  errorMessage->clear();
1877  }
1878 
1879  QgsAttributeList allAttr = skipAttributeCreation ? QgsAttributeList() : layer->pendingAllAttributesList();
1880  QgsFeature fet;
1881 
1882  //add possible attributes needed by renderer
1883  writer->addRendererAttributes( layer, allAttr );
1884 
1885  QgsFeatureRequest req;
1886  if ( layer->wkbType() == QGis::WKBNoGeometry )
1887  {
1889  }
1890  req.setSubsetOfAttributes( allAttr );
1891  QgsFeatureIterator fit = layer->getFeatures( req );
1892 
1893  const QgsFeatureIds& ids = layer->selectedFeaturesIds();
1894 
1895  //create symbol table if needed
1896  if ( writer->symbologyExport() != NoSymbology )
1897  {
1898  //writer->createSymbolLayerTable( layer, writer->mDS );
1899  }
1900 
1901  if ( writer->symbologyExport() == SymbolLayerSymbology )
1902  {
1903  QgsFeatureRendererV2* r = layer->rendererV2();
1905  && r->usingSymbolLevels() )
1906  {
1907  QgsVectorFileWriter::WriterError error = writer->exportFeaturesSymbolLevels( layer, fit, ct, errorMessage );
1908  delete writer;
1909  delete ct;
1910  return ( error == NoError ) ? NoError : ErrFeatureWriteFailed;
1911  }
1912  }
1913 
1914  int n = 0, errors = 0;
1915 
1916  //unit type
1917  QGis::UnitType mapUnits = layer->crs().mapUnits();
1918  if ( ct )
1919  {
1920  mapUnits = ct->destCRS().mapUnits();
1921  }
1922 
1923  writer->startRender( layer );
1924 
1925  // enabling transaction on databases that support it
1926  bool transactionsEnabled = true;
1927 
1928  if ( OGRERR_NONE != OGR_L_StartTransaction( writer->mLayer ) )
1929  {
1930  QgsDebugMsg( "Error when trying to enable transactions on OGRLayer." );
1931  transactionsEnabled = false;
1932  }
1933 
1934  // write all features
1935  while ( fit.nextFeature( fet ) )
1936  {
1937  if ( onlySelected && !ids.contains( fet.id() ) )
1938  continue;
1939 
1940  if ( shallTransform )
1941  {
1942  try
1943  {
1944  if ( fet.geometry() )
1945  {
1946  fet.geometry()->transform( *ct );
1947  }
1948  }
1949  catch ( QgsCsException &e )
1950  {
1951  delete ct;
1952  delete writer;
1953 
1954  QString msg = QObject::tr( "Failed to transform a point while drawing a feature with ID '%1'. Writing stopped. (Exception: %2)" )
1955  .arg( fet.id() ).arg( e.what() );
1956  QgsLogger::warning( msg );
1957  if ( errorMessage )
1958  *errorMessage = msg;
1959 
1960  return ErrProjection;
1961  }
1962  }
1963  if ( allAttr.size() < 1 && skipAttributeCreation )
1964  {
1965  fet.initAttributes( 0 );
1966  }
1967 
1968  if ( !writer->addFeature( fet, layer->rendererV2(), mapUnits ) )
1969  {
1970  WriterError err = writer->hasError();
1971  if ( err != NoError && errorMessage )
1972  {
1973  if ( errorMessage->isEmpty() )
1974  {
1975  *errorMessage = QObject::tr( "Feature write errors:" );
1976  }
1977  *errorMessage += "\n" + writer->errorMessage();
1978  }
1979  errors++;
1980 
1981  if ( errors > 1000 )
1982  {
1983  if ( errorMessage )
1984  {
1985  *errorMessage += QObject::tr( "Stopping after %1 errors" ).arg( errors );
1986  }
1987 
1988  n = -1;
1989  break;
1990  }
1991  }
1992  n++;
1993  }
1994 
1995  if ( transactionsEnabled )
1996  {
1997  if ( OGRERR_NONE != OGR_L_CommitTransaction( writer->mLayer ) )
1998  {
1999  QgsDebugMsg( "Error while committing transaction on OGRLayer." );
2000  }
2001  }
2002 
2003  writer->stopRender( layer );
2004  delete writer;
2005 
2006  if ( errors > 0 && errorMessage && n > 0 )
2007  {
2008  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
2009  }
2010 
2011  return errors == 0 ? NoError : ErrFeatureWriteFailed;
2012 }
2013 
2014 
2015 bool QgsVectorFileWriter::deleteShapeFile( QString theFileName )
2016 {
2017  QFileInfo fi( theFileName );
2018  QDir dir = fi.dir();
2019 
2020  QStringList filter;
2021  const char *suffixes[] = { ".shp", ".shx", ".dbf", ".prj", ".qix", ".qpj" };
2022  for ( std::size_t i = 0; i < sizeof( suffixes ) / sizeof( *suffixes ); i++ )
2023  {
2024  filter << fi.completeBaseName() + suffixes[i];
2025  }
2026 
2027  bool ok = true;
2028  foreach ( QString file, dir.entryList( filter ) )
2029  {
2030  if ( !QFile::remove( dir.canonicalPath() + "/" + file ) )
2031  {
2032  QgsDebugMsg( "Removing file failed : " + file );
2033  ok = false;
2034  }
2035  }
2036 
2037  return ok;
2038 }
2039 
2041 {
2042  QMap<QString, QString> resultMap;
2043 
2045  int const drvCount = OGRGetDriverCount();
2046 
2047  for ( int i = 0; i < drvCount; ++i )
2048  {
2049  OGRSFDriverH drv = OGRGetDriver( i );
2050  if ( drv )
2051  {
2052  QString drvName = OGR_Dr_GetName( drv );
2053  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
2054  {
2055  QString filterString = filterForDriver( drvName );
2056  if ( filterString.isEmpty() )
2057  continue;
2058 
2059  resultMap.insert( filterString, drvName );
2060  }
2061  }
2062  }
2063 
2064  return resultMap;
2065 }
2066 
2067 QMap<QString, QString> QgsVectorFileWriter::ogrDriverList()
2068 {
2069  QMap<QString, QString> resultMap;
2070 
2072  int const drvCount = OGRGetDriverCount();
2073 
2074  QStringList writableDrivers;
2075  for ( int i = 0; i < drvCount; ++i )
2076  {
2077  OGRSFDriverH drv = OGRGetDriver( i );
2078  if ( drv )
2079  {
2080  QString drvName = OGR_Dr_GetName( drv );
2081  if ( OGR_Dr_TestCapability( drv, "CreateDataSource" ) != 0 )
2082  {
2083  // Add separate format for Mapinfo MIF (MITAB is OGR default)
2084  if ( drvName == "MapInfo File" )
2085  {
2086  writableDrivers << "MapInfo MIF";
2087  }
2088  else if ( drvName == "SQLite" )
2089  {
2090  // Unfortunately it seems that there is no simple way to detect if
2091  // OGR SQLite driver is compiled with SpatiaLite support.
2092  // We have HAVE_SPATIALITE in QGIS, but that may differ from OGR
2093  // http://lists.osgeo.org/pipermail/gdal-dev/2012-November/034580.html
2094  // -> test if creation failes
2095  QString option = "SPATIALITE=YES";
2096  char **options = new char *[2];
2097  options[0] = CPLStrdup( option.toLocal8Bit().data() );
2098  options[1] = NULL;
2099  OGRSFDriverH poDriver;
2101  poDriver = OGRGetDriverByName( drvName.toLocal8Bit().data() );
2102  if ( poDriver )
2103  {
2104  OGRDataSourceH ds = OGR_Dr_CreateDataSource( poDriver, TO8F( QString( "/vsimem/spatialitetest.sqlite" ) ), options );
2105  if ( ds )
2106  {
2107  writableDrivers << "SpatiaLite";
2108  OGR_Dr_DeleteDataSource( poDriver, TO8F( QString( "/vsimem/spatialitetest.sqlite" ) ) );
2109  OGR_DS_Destroy( ds );
2110  }
2111  }
2112  CPLFree( options[0] );
2113  delete [] options;
2114  }
2115  else if ( drvName == "ESRI Shapefile" )
2116  {
2117  writableDrivers << "DBF file";
2118  }
2119  writableDrivers << drvName;
2120  }
2121  }
2122  }
2123 
2124  foreach ( QString drvName, writableDrivers )
2125  {
2126  QString longName;
2127  QString trLongName;
2128  QString glob;
2129  QString exts;
2130  if ( QgsVectorFileWriter::driverMetadata( drvName, longName, trLongName, glob, exts ) && !trLongName.isEmpty() )
2131  {
2132  resultMap.insert( trLongName, drvName );
2133  }
2134  }
2135 
2136  return resultMap;
2137 }
2138 
2140 {
2141  QString filterString;
2142  QMap< QString, QString> driverFormatMap = supportedFiltersAndFormats();
2143  QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
2144  for ( ; it != driverFormatMap.constEnd(); ++it )
2145  {
2146  if ( filterString.isEmpty() )
2147  filterString += ";;";
2148 
2149  filterString += it.key();
2150  }
2151  return filterString;
2152 }
2153 
2154 QString QgsVectorFileWriter::filterForDriver( const QString& driverName )
2155 {
2156  QString longName;
2157  QString trLongName;
2158  QString glob;
2159  QString exts;
2160  if ( !driverMetadata( driverName, longName, trLongName, glob, exts ) || trLongName.isEmpty() || glob.isEmpty() )
2161  return "";
2162 
2163  return trLongName + " [OGR] (" + glob.toLower() + " " + glob.toUpper() + ")";
2164 }
2165 
2167 {
2168  if ( codecName == "System" )
2169  return QString( "LDID/0" );
2170 
2171  QRegExp re = QRegExp( QString( "(CP|windows-|ISO[ -])(.+)" ), Qt::CaseInsensitive );
2172  if ( re.exactMatch( codecName ) )
2173  {
2174  QString c = re.cap( 2 ).replace( "-" , "" );
2175  bool isNumber;
2176  c.toInt( &isNumber );
2177  if ( isNumber )
2178  return c;
2179  }
2180  return codecName;
2181 }
2182 
2183 bool QgsVectorFileWriter::driverMetadata( QString driverName, QString &longName, QString &trLongName, QString &glob, QString &ext )
2184 {
2185  if ( driverName.startsWith( "AVCE00" ) )
2186  {
2187  longName = "Arc/Info ASCII Coverage";
2188  trLongName = QObject::tr( "Arc/Info ASCII Coverage" );
2189  glob = "*.e00";
2190  ext = "e00";
2191  }
2192  else if ( driverName.startsWith( "BNA" ) )
2193  {
2194  longName = "Atlas BNA";
2195  trLongName = QObject::tr( "Atlas BNA" );
2196  glob = "*.bna";
2197  ext = "bna";
2198  }
2199  else if ( driverName.startsWith( "CSV" ) )
2200  {
2201  longName = "Comma Separated Value";
2202  trLongName = QObject::tr( "Comma Separated Value" );
2203  glob = "*.csv";
2204  ext = "csv";
2205  }
2206  else if ( driverName.startsWith( "ESRI" ) )
2207  {
2208  longName = "ESRI Shapefile";
2209  trLongName = QObject::tr( "ESRI Shapefile" );
2210  glob = "*.shp";
2211  ext = "shp";
2212  }
2213  else if ( driverName.startsWith( "DBF file" ) )
2214  {
2215  longName = "DBF File";
2216  trLongName = QObject::tr( "DBF file" );
2217  glob = "*.dbf";
2218  ext = "dbf";
2219  }
2220  else if ( driverName.startsWith( "FMEObjects Gateway" ) )
2221  {
2222  longName = "FMEObjects Gateway";
2223  trLongName = QObject::tr( "FMEObjects Gateway" );
2224  glob = "*.fdd";
2225  ext = "fdd";
2226  }
2227  else if ( driverName.startsWith( "GeoJSON" ) )
2228  {
2229  longName = "GeoJSON";
2230  trLongName = QObject::tr( "GeoJSON" );
2231  glob = "*.geojson";
2232  ext = "geojson";
2233  }
2234  else if ( driverName.startsWith( "GeoRSS" ) )
2235  {
2236  longName = "GeoRSS";
2237  trLongName = QObject::tr( "GeoRSS" );
2238  glob = "*.xml";
2239  ext = "xml";
2240  }
2241  else if ( driverName.startsWith( "GML" ) )
2242  {
2243  longName = "Geography Markup Language [GML]";
2244  trLongName = QObject::tr( "Geography Markup Language [GML]" );
2245  glob = "*.gml";
2246  ext = "gml";
2247  }
2248  else if ( driverName.startsWith( "GMT" ) )
2249  {
2250  longName = "Generic Mapping Tools [GMT]";
2251  trLongName = QObject::tr( "Generic Mapping Tools [GMT]" );
2252  glob = "*.gmt";
2253  ext = "gmt";
2254  }
2255  else if ( driverName.startsWith( "GPX" ) )
2256  {
2257  longName = "GPS eXchange Format [GPX]";
2258  trLongName = QObject::tr( "GPS eXchange Format [GPX]" );
2259  glob = "*.gpx";
2260  ext = "gpx";
2261  }
2262  else if ( driverName.startsWith( "Interlis 1" ) )
2263  {
2264  longName = "INTERLIS 1";
2265  trLongName = QObject::tr( "INTERLIS 1" );
2266  glob = "*.itf *.xml *.ili";
2267  ext = "ili";
2268  }
2269  else if ( driverName.startsWith( "Interlis 2" ) )
2270  {
2271  longName = "INTERLIS 2";
2272  trLongName = QObject::tr( "INTERLIS 2" );
2273  glob = "*.itf *.xml *.ili";
2274  ext = "ili";
2275  }
2276  else if ( driverName.startsWith( "KML" ) )
2277  {
2278  longName = "Keyhole Markup Language [KML]";
2279  trLongName = QObject::tr( "Keyhole Markup Language [KML]" );
2280  glob = "*.kml" ;
2281  ext = "kml" ;
2282  }
2283  else if ( driverName.startsWith( "MapInfo File" ) )
2284  {
2285  longName = "Mapinfo TAB";
2286  trLongName = QObject::tr( "Mapinfo TAB" );
2287  glob = "*.tab";
2288  ext = "tab";
2289  }
2290  // 'MapInfo MIF' is internal QGIS addition to distinguish between MITAB and MIF
2291  else if ( driverName.startsWith( "MapInfo MIF" ) )
2292  {
2293  longName = "Mapinfo MIF";
2294  trLongName = QObject::tr( "Mapinfo MIF" );
2295  glob = "*.mif";
2296  ext = "mif";
2297  }
2298  else if ( driverName.startsWith( "DGN" ) )
2299  {
2300  longName = "Microstation DGN";
2301  trLongName = QObject::tr( "Microstation DGN" );
2302  glob = "*.dgn";
2303  ext = "dgn";
2304  }
2305  else if ( driverName.startsWith( "S57" ) )
2306  {
2307  longName = "S-57 Base file";
2308  trLongName = QObject::tr( "S-57 Base file" );
2309  glob = "*.000";
2310  ext = "000";
2311  }
2312  else if ( driverName.startsWith( "SDTS" ) )
2313  {
2314  longName = "Spatial Data Transfer Standard [SDTS]";
2315  trLongName = QObject::tr( "Spatial Data Transfer Standard [SDTS]" );
2316  glob = "*catd.ddf";
2317  ext = "ddf";
2318  }
2319  else if ( driverName.startsWith( "SQLite" ) )
2320  {
2321  longName = "SQLite";
2322  trLongName = QObject::tr( "SQLite" );
2323  glob = "*.sqlite";
2324  ext = "sqlite";
2325  }
2326  // QGIS internal addition for SpatialLite
2327  else if ( driverName.startsWith( "SpatiaLite" ) )
2328  {
2329  longName = "SpatiaLite";
2330  trLongName = QObject::tr( "SpatiaLite" );
2331  glob = "*.sqlite";
2332  ext = "sqlite";
2333  }
2334  else if ( driverName.startsWith( "DXF" ) )
2335  {
2336  longName = "AutoCAD DXF";
2337  trLongName = QObject::tr( "AutoCAD DXF" );
2338  glob = "*.dxf";
2339  ext = "dxf";
2340  }
2341  else if ( driverName.startsWith( "Geoconcept" ) )
2342  {
2343  longName = "Geoconcept";
2344  trLongName = QObject::tr( "Geoconcept" );
2345  glob = "*.gxt *.txt";
2346  ext = "gxt";
2347  }
2348  else if ( driverName.startsWith( "FileGDB" ) )
2349  {
2350  longName = "ESRI FileGDB";
2351  trLongName = QObject::tr( "ESRI FileGDB" );
2352  glob = "*.gdb";
2353  ext = "gdb";
2354  }
2355  else
2356  {
2357  return false;
2358  }
2359 
2360  return true;
2361 }
2362 
2364 {
2365  if ( !vl || !ds )
2366  {
2367  return;
2368  }
2369 
2370  QgsFeatureRendererV2* renderer = vl->rendererV2();
2371  if ( !renderer )
2372  {
2373  return;
2374  }
2375 
2376  //unit type
2377  QGis::UnitType mapUnits = vl->crs().mapUnits();
2378  if ( ct )
2379  {
2380  mapUnits = ct->destCRS().mapUnits();
2381  }
2382 
2383 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1700
2384  mSymbolLayerTable.clear();
2385  OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
2386  OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
2387 
2388  //get symbols
2389  int nTotalLevels = 0;
2390  QgsSymbolV2List symbolList = renderer->symbols();
2391  QgsSymbolV2List::iterator symbolIt = symbolList.begin();
2392  for ( ; symbolIt != symbolList.end(); ++symbolIt )
2393  {
2394  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits );
2395  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, ( *symbolIt )->outputUnit(), mapUnits );
2396 
2397  int nLevels = ( *symbolIt )->symbolLayerCount();
2398  for ( int i = 0; i < nLevels; ++i )
2399  {
2400  mSymbolLayerTable.insert(( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
2401  OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
2402  ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
2403  ++nTotalLevels;
2404  }
2405  }
2406  OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
2407 #endif
2408 }
2409 
2411  const QgsCoordinateTransform* ct, QString* errorMessage )
2412 {
2413  if ( !layer )
2414  {
2415  //return error
2416  }
2417  QgsFeatureRendererV2* renderer = layer->rendererV2();
2418  if ( !renderer )
2419  {
2420  //return error
2421  }
2422  QHash< QgsSymbolV2*, QList<QgsFeature> > features;
2423 
2424  //unit type
2425  QGis::UnitType mapUnits = layer->crs().mapUnits();
2426  if ( ct )
2427  {
2428  mapUnits = ct->destCRS().mapUnits();
2429  }
2430 
2431  startRender( layer );
2432 
2433  //fetch features
2434  QgsFeature fet;
2435  QgsSymbolV2* featureSymbol = 0;
2436  while ( fit.nextFeature( fet ) )
2437  {
2438  if ( ct )
2439  {
2440  try
2441  {
2442  if ( fet.geometry() )
2443  {
2444  fet.geometry()->transform( *ct );
2445  }
2446  }
2447  catch ( QgsCsException &e )
2448  {
2449  delete ct;
2450 
2451  QString msg = QObject::tr( "Failed to transform, writing stopped. (Exception: %1)" )
2452  .arg( e.what() );
2453  QgsLogger::warning( msg );
2454  if ( errorMessage )
2455  *errorMessage = msg;
2456 
2457  return ErrProjection;
2458  }
2459  }
2460 
2461  featureSymbol = renderer->symbolForFeature( fet );
2462  if ( !featureSymbol )
2463  {
2464  continue;
2465  }
2466 
2467  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
2468  if ( it == features.end() )
2469  {
2470  it = features.insert( featureSymbol, QList<QgsFeature>() );
2471  }
2472  it.value().append( fet );
2473  }
2474 
2475  //find out order
2476  QgsSymbolV2LevelOrder levels;
2477  QgsSymbolV2List symbols = renderer->symbols();
2478  for ( int i = 0; i < symbols.count(); i++ )
2479  {
2480  QgsSymbolV2* sym = symbols[i];
2481  for ( int j = 0; j < sym->symbolLayerCount(); j++ )
2482  {
2483  int level = sym->symbolLayer( j )->renderingPass();
2484  if ( level < 0 || level >= 1000 ) // ignore invalid levels
2485  continue;
2486  QgsSymbolV2LevelItem item( sym, j );
2487  while ( level >= levels.count() ) // append new empty levels
2488  levels.append( QgsSymbolV2Level() );
2489  levels[level].append( item );
2490  }
2491  }
2492 
2493  int nErrors = 0;
2494  int nTotalFeatures = 0;
2495 
2496  //export symbol layers and symbology
2497  for ( int l = 0; l < levels.count(); l++ )
2498  {
2499  QgsSymbolV2Level& level = levels[l];
2500  for ( int i = 0; i < level.count(); i++ )
2501  {
2502  QgsSymbolV2LevelItem& item = level[i];
2503  QHash< QgsSymbolV2*, QList<QgsFeature> >::iterator levelIt = features.find( item.symbol() );
2504  if ( levelIt == features.end() )
2505  {
2506  ++nErrors;
2507  continue;
2508  }
2509 
2510  double mmsf = mmScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(), mapUnits );
2511  double musf = mapUnitScaleFactor( mSymbologyScaleDenominator, levelIt.key()->outputUnit(), mapUnits );
2512 
2513  int llayer = item.layer();
2514  QList<QgsFeature>& featureList = levelIt.value();
2515  QList<QgsFeature>::iterator featureIt = featureList.begin();
2516  for ( ; featureIt != featureList.end(); ++featureIt )
2517  {
2518  ++nTotalFeatures;
2519  OGRFeatureH ogrFeature = createFeature( *featureIt );
2520  if ( !ogrFeature )
2521  {
2522  ++nErrors;
2523  continue;
2524  }
2525 
2526  QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
2527  if ( !styleString.isEmpty() )
2528  {
2529  OGR_F_SetStyleString( ogrFeature, styleString.toLocal8Bit().data() );
2530  if ( ! writeFeature( mLayer, ogrFeature ) )
2531  {
2532  ++nErrors;
2533  }
2534  }
2535  OGR_F_Destroy( ogrFeature );
2536  }
2537  }
2538  }
2539 
2540  stopRender( layer );
2541 
2542  if ( nErrors > 0 && errorMessage )
2543  {
2544  *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
2545  }
2546 
2548 }
2549 
2550 double QgsVectorFileWriter::mmScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
2551 {
2552  if ( symbolUnits == QgsSymbolV2::MM )
2553  {
2554  return 1.0;
2555  }
2556  else
2557  {
2558  //conversion factor map units -> mm
2559  if ( mapUnits == QGis::Meters )
2560  {
2561  return 1000 / scaleDenominator;
2562  }
2563 
2564  }
2565  return 1.0; //todo: map units
2566 }
2567 
2568 double QgsVectorFileWriter::mapUnitScaleFactor( double scaleDenominator, QgsSymbolV2::OutputUnit symbolUnits, QGis::UnitType mapUnits )
2569 {
2570  if ( symbolUnits == QgsSymbolV2::MapUnit )
2571  {
2572  return 1.0;
2573  }
2574  else
2575  {
2576  if ( symbolUnits == QgsSymbolV2::MM && mapUnits == QGis::Meters )
2577  {
2578  return scaleDenominator / 1000;
2579  }
2580  }
2581  return 1.0;
2582 }
2583 
2585 {
2586  QgsRenderContext context;
2588  return context;
2589 }
2590 
2592 {
2593  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2594  if ( !renderer )
2595  {
2596  return;
2597  }
2598 
2600  renderer->startRender( ctx, vl );
2601 }
2602 
2604 {
2605  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2606  if ( !renderer )
2607  {
2608  return;
2609  }
2610 
2612  renderer->stopRender( ctx );
2613 }
2614 
2616 {
2617  if ( mSymbologyExport == NoSymbology )
2618  {
2619  return 0;
2620  }
2621  if ( !vl )
2622  {
2623  return 0;
2624  }
2625 
2626  return vl->rendererV2();
2627 }
2628 
2630 {
2631  QgsFeatureRendererV2* renderer = symbologyRenderer( vl );
2632  if ( renderer )
2633  {
2634  QList<QString> rendererAttributes = renderer->usedAttributes();
2635  for ( int i = 0; i < rendererAttributes.size(); ++i )
2636  {
2637  int index = vl->fieldNameIndex( rendererAttributes.at( i ) );
2638  if ( index != -1 )
2639  {
2640  attList.push_back( vl->fieldNameIndex( rendererAttributes.at( i ) ) );
2641  }
2642  }
2643  }
2644 }
QgsFeatureId id() const
Get the feature id for this feature.
Definition: qgsfeature.cpp:101
static WkbType singleType(WkbType type)
Definition: qgis.h:71
const QString & name() const
Gets the name of the field.
Definition: qgsfield.cpp:55
Wrapper for iterator of features from vector data provider or vector layer.
QgsFeatureRendererV2 * rendererV2()
Return renderer V2.
static unsigned index
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:36
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:322
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:113
void setRendererScale(double scale)
int precision() const
Gets the precision of the field.
Definition: qgsfield.cpp:75
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:162
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:114
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
double ANALYSIS_EXPORT max(double x, double y)
returns the maximum of two doubles or the first argument if both are equal
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:182
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:83
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:196
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:29
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:59
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:231
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:51
bool usingSymbolLevels() const
Class for storing a coordinate reference system (CRS)
int length() const
Gets the length of the field.
Definition: qgsfield.cpp:70
int size() const
Return number of items.
Definition: qgsfield.h:198
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:62
const QgsCoordinateReferenceSystem & crs() const
Returns layer's spatial reference system.
virtual void startRender(QgsRenderContext &context, const QgsVectorLayer *vlayer)=0
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)
Write contents of vector layer to an (OGR supported) vector formt.
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
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)
static QMap< QString, MetaData > sDriverMetadata
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:60
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
#define tr(sourceText)