47#include <QRegularExpression>
48#include <QJsonDocument>
54#include <ogr_srs_api.h>
57#include <cpl_string.h>
76 const QString &fileEncoding,
80 const QString &driverName,
81 const QStringList &datasourceOptions,
82 const QStringList &layerOptions,
94 init( vectorFileName, fileEncoding, fields, geometryType,
95 srs, driverName, datasourceOptions, layerOptions, newFilename,
nullptr,
100 const QString &fileEncoding,
104 const QString &driverName,
105 const QStringList &datasourceOptions,
106 const QStringList &layerOptions,
107 QString *newFilename,
110 const QString &layerName,
116 bool includeConstraints,
117 bool setFieldDomains,
120 , mWkbType( geometryType )
121 , mSymbologyExport( symbologyExport )
122 , mSymbologyScale( 1.0 )
123 , mIncludeConstraints( includeConstraints )
124 , mSetFieldDomains( setFieldDomains )
126 init( vectorFileName, fileEncoding, fields, geometryType, srs, driverName,
127 datasourceOptions, layerOptions, newFilename, fieldValueConverter,
128 layerName, action, newLayer, sinkFlags, transformContext, fieldNameSource, sourceDatabaseProviderConnection );
132 const QString &fileName,
139 QString *newFilename,
153 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
157 GDALDriverH gdalDriver = GDALGetDriverByName( driverName.toLocal8Bit().constData() );
165#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
166 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES_WRITE,
false );
168 return CSLFetchBoolean(
driverMetadata, GDAL_DCAP_FEATURE_STYLES,
false );
172void QgsVectorFileWriter::init( QString vectorFileName,
173 QString fileEncoding,
177 const QString &driverName,
178 QStringList datasourceOptions,
179 QStringList layerOptions,
180 QString *newFilename,
181 FieldValueConverter *fieldValueConverter,
182 const QString &layerNameIn,
183 ActionOnExistingFile action,
184 QString *newLayer, SinkFlags sinkFlags,
188#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,5,0)
189 ( void )sourceDatabaseProviderConnection;
194 if ( vectorFileName.isEmpty() )
201 if ( driverName == QLatin1String(
"MapInfo MIF" ) )
205 else if ( driverName == QLatin1String(
"SpatiaLite" ) )
208 if ( !datasourceOptions.contains( QStringLiteral(
"SPATIALITE=YES" ) ) )
210 datasourceOptions.append( QStringLiteral(
"SPATIALITE=YES" ) );
213 else if ( driverName == QLatin1String(
"DBF file" ) )
216 if ( !layerOptions.contains( QStringLiteral(
"SHPT=NULL" ) ) )
218 layerOptions.append( QStringLiteral(
"SHPT=NULL" ) );
227#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
228 QString fidFieldName;
231 for (
const QString &layerOption : layerOptions )
233 if ( layerOption.startsWith( QLatin1String(
"FID=" ) ) )
235 fidFieldName = layerOption.mid( 4 );
239 if ( fidFieldName.isEmpty() )
240 fidFieldName = QStringLiteral(
"fid" );
245 OGRSFDriverH poDriver;
248 poDriver = OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() );
252 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
254 QString::fromUtf8( CPLGetLastErrorMsg() ) );
259 mOgrDriverLongName = QString( GDALGetMetadataItem( poDriver, GDAL_DMD_LONGNAME,
nullptr ) );
266 if ( layerOptions.join( QString() ).toUpper().indexOf( QLatin1String(
"ENCODING=" ) ) == -1 )
271 if ( driverName == QLatin1String(
"ESRI Shapefile" ) && !vectorFileName.endsWith( QLatin1String(
".shp" ), Qt::CaseInsensitive ) )
273 vectorFileName += QLatin1String(
".shp" );
275 else if ( driverName == QLatin1String(
"DBF file" ) && !vectorFileName.endsWith( QLatin1String(
".dbf" ), Qt::CaseInsensitive ) )
277 vectorFileName += QLatin1String(
".dbf" );
287 QStringList allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
289 const auto constAllExts = allExts;
290 for (
const QString &ext : constAllExts )
292 if ( vectorFileName.endsWith(
'.' + ext, Qt::CaseInsensitive ) )
301 vectorFileName +=
'.' + allExts[0];
307 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
309 QDir dir( vectorFileName );
312 QFileInfoList fileList = dir.entryInfoList(
313 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
314 const auto constFileList = fileList;
315 for (
const QFileInfo &info : constFileList )
317 QFile::remove( info.absoluteFilePath() );
320 QDir().rmdir( vectorFileName );
324 QFile::remove( vectorFileName );
329 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
331 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
333 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
334 fileEncoding = metadata.compulsoryEncoding;
339 char **options =
nullptr;
340 if ( !datasourceOptions.isEmpty() )
342 options =
new char *[ datasourceOptions.size() + 1 ];
343 for (
int i = 0; i < datasourceOptions.size(); i++ )
345 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
346 options[i] = CPLStrdup( datasourceOptions[i].toUtf8().constData() );
348 options[ datasourceOptions.size()] =
nullptr;
355 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
357 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
361 for (
int i = 0; i < datasourceOptions.size(); i++ )
362 CPLFree( options[i] );
371 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
372 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
374 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
375 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
379 QString layerName( layerNameIn );
380 if ( layerName.isEmpty() )
381 layerName = QFileInfo( vectorFileName ).baseName();
385 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
386 for (
int i = 0; i < layer_count; i++ )
388 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
389 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
391 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
394 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
395 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
409 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
413 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
416 QgsDebugError(
"error finding QTextCodec for " + fileEncoding );
419 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
420 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
424 mCodec = QTextCodec::codecForLocale();
430 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
432 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
447 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
448 if ( optIndex != -1 )
450 layerOptions.removeAt( optIndex );
453 if ( !layerOptions.isEmpty() )
455 options =
new char *[ layerOptions.size() + 1 ];
456 for (
int i = 0; i < layerOptions.size(); i++ )
459 options[i] = CPLStrdup( layerOptions[i].toUtf8().constData() );
461 options[ layerOptions.size()] =
nullptr;
465 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
469 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
472 *newLayer = OGR_L_GetName(
mLayer );
473 if ( driverName == QLatin1String(
"GPX" ) )
480 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
481 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
483 *newLayer = QStringLiteral(
"waypoints" );
490 const char *pszForceGPXTrack
491 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
492 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
493 *newLayer = QStringLiteral(
"tracks" );
495 *newLayer = QStringLiteral(
"routes" );
502 const char *pszForceGPXRoute
503 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
504 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
505 *newLayer = QStringLiteral(
"routes" );
507 *newLayer = QStringLiteral(
"tracks" );
517 else if ( driverName == QLatin1String(
"DGN" ) )
519 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
523 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
528 for (
int i = 0; i < layerOptions.size(); i++ )
529 CPLFree( options[i] );
538 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
539 QFile prjFile( layerName +
".qpj" );
540 if ( prjFile.exists() )
548 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
549 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
551 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
552 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
557 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
566 QSet<int> existingIdxs;
570#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
571 if (
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
nullptr ) )
573 char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags,
" ", 0 );
574 if ( CSLFindString( papszTokens,
"AlternativeName" ) >= 0 )
578 if ( CSLFindString( papszTokens,
"Comment" ) >= 0 )
582 CSLDestroy( papszTokens );
592#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0)
593 QSet<QString> existingDestDomainNames;
594 if ( sourceDatabaseProviderConnection )
596 char **domainNames = GDALDatasetGetFieldDomainNames(
mDS.get(),
nullptr );
597 for (
const char *
const *iterDomainNames = domainNames; iterDomainNames && *iterDomainNames; ++iterDomainNames )
599 existingDestDomainNames.insert( QString::fromUtf8( *iterDomainNames ) );
601 CSLDestroy( domainNames );
604#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
605 QSet< QString > usedAlternativeNames;
607 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
611 if ( fieldValueConverter )
613 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
618 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
627 switch ( fieldNameSource )
630 name = attrField.
name();
634 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
638 OGRFieldType ogrType = OFTString;
639 OGRFieldSubType ogrSubType = OFSTNone;
640 int ogrWidth = attrField.
length();
641 int ogrPrecision = attrField.
precision();
642 if ( ogrPrecision > 0 )
645 switch ( attrField.
type() )
647 case QMetaType::Type::LongLong:
649 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
650 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
651 ogrType = OFTInteger64;
654 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
658 case QMetaType::Type::QString:
660 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
664 case QMetaType::Type::Int:
665 ogrType = OFTInteger;
666 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
670 case QMetaType::Type::Bool:
671 ogrType = OFTInteger;
672 ogrSubType = OFSTBoolean;
677 case QMetaType::Type::Double:
678#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
679 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
682 ogrType = OFTInteger64;
689 case QMetaType::Type::QDate:
693 case QMetaType::Type::QTime:
705 case QMetaType::Type::QDateTime:
713 ogrType = OFTDateTime;
717 case QMetaType::Type::QByteArray:
721 case QMetaType::Type::QStringList:
727 ogrSubType = OFSTJSON;
731 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
732 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
734 ogrType = OFTStringList;
735 mSupportedListSubTypes.insert( QMetaType::Type::QString );
745 case QMetaType::Type::QVariantMap:
748 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
749 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
752 ogrSubType = OFSTJSON;
760 case QMetaType::Type::QVariantList:
765 ogrSubType = OFSTJSON;
770 if ( attrField.
subType() == QMetaType::Type::QString )
772 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
773 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
775 ogrType = OFTStringList;
776 mSupportedListSubTypes.insert( QMetaType::Type::QString );
785 else if ( attrField.
subType() == QMetaType::Type::Int )
787 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
788 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
790 ogrType = OFTIntegerList;
791 mSupportedListSubTypes.insert( QMetaType::Type::Int );
800 else if ( attrField.
subType() == QMetaType::Type::Double )
802 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
803 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
805 ogrType = OFTRealList;
806 mSupportedListSubTypes.insert( QMetaType::Type::Double );
815 else if ( attrField.
subType() == QMetaType::Type::LongLong )
817 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
818 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
820 ogrType = OFTInteger64List;
821 mSupportedListSubTypes.insert( QMetaType::Type::LongLong );
835 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
836 .arg( attrField.
name() );
841 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
844 for ( i = 0; i < 10; i++ )
846 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
849 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
852 if ( j == fields.
size() )
858 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
863 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
870 OGR_Fld_SetWidth( fld.get(), ogrWidth );
873 if ( ogrPrecision >= 0 )
875 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
878 if ( ogrSubType != OFSTNone )
879 OGR_Fld_SetSubType( fld.get(), ogrSubType );
881#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
882 if ( !attrField.
alias().isEmpty() )
884 QString alternativeName = attrField.
alias();
886 while ( usedAlternativeNames.contains( alternativeName ) )
889 alternativeName = attrField.
alias() + QStringLiteral(
" (%1)" ).arg( ++counter );
891 OGR_Fld_SetAlternativeName( fld.get(),
mCodec->fromUnicode( alternativeName ).constData() );
892 usedAlternativeNames.insert( alternativeName );
895#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
896 OGR_Fld_SetComment( fld.get(),
mCodec->fromUnicode( attrField.
comment() ).constData() );
903 OGR_Fld_SetNullable( fld.get(),
false );
907 OGR_Fld_SetUnique( fld.get(),
true );
910#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0)
914 if ( !domainName.isEmpty() )
916 bool canSetFieldDomainName =
false;
917 if ( existingDestDomainNames.contains( domainName ) )
921 canSetFieldDomainName =
true;
923 else if ( GDALDatasetTestCapability(
mDS.get(), ODsCAddFieldDomain ) )
931 std::unique_ptr<QgsFieldDomain> domain( sourceDatabaseProviderConnection->
fieldDomain( domainName ) );
937 char *pszFailureReason =
nullptr;
938 if ( GDALDatasetAddFieldDomain(
mDS.get(), hFieldDomain, &pszFailureReason ) )
940 existingDestDomainNames.insert( domainName );
941 canSetFieldDomainName =
true;
945 QgsDebugMsgLevel( QStringLiteral(
"cannot create field domain: %1" ).arg( pszFailureReason ), 2 );
947 CPLFree( pszFailureReason );
948 OGR_FldDomain_Destroy( hFieldDomain );
952 if ( canSetFieldDomainName )
954 OGR_Fld_SetDomainName( fld.get(), domainName.toUtf8().toStdString().c_str() );
962 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
963 " width " + QString::number( ogrWidth ) +
964 " precision " + QString::number( ogrPrecision ), 2 );
965 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
968 mErrorMessage = QObject::tr(
"Creation of field %1 failed (OGR error: %2)" )
969 .arg( attrField.
name(),
970 QString::fromUtf8( CPLGetLastErrorMsg() ) );
975 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
976 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
977 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
980 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
985 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
986 .arg( attrField.
name(),
987 QString::fromUtf8( CPLGetLastErrorMsg() ) );
993 existingIdxs.insert( ogrIdx );
1001 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
1004 QString name( attrField.
name() );
1005 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1017 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
1028 *newFilename = vectorFileName;
1031 mUsingTransaction =
true;
1032 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
1034 mUsingTransaction =
false;
1044class QgsVectorFileWriterMetadataContainer
1048 QgsVectorFileWriterMetadataContainer()
1050 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
1051 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
1054 datasetOptions.clear();
1055 layerOptions.clear();
1058 QObject::tr(
"Compression method." ),
1060 << QStringLiteral(
"UNCOMPRESSED" )
1061 << QStringLiteral(
"ZSTD" )
1062 << QStringLiteral(
"LZ4" ),
1063 QStringLiteral(
"LZ4" ),
1068 QObject::tr(
"Geometry encoding." ),
1070 << QStringLiteral(
"GEOARROW" )
1071 << QStringLiteral(
"WKB" )
1072 << QStringLiteral(
"WKT" ),
1073 QStringLiteral(
"GEOARROW" ),
1078 QObject::tr(
"Maximum number of rows per batch." ),
1083 QObject::tr(
"Name for the feature identifier column" ),
1088 QObject::tr(
"Name for the geometry column" ),
1089 QStringLiteral(
"geometry" )
1092 driverMetadata.insert( QStringLiteral(
"Arrow" ),
1094 QStringLiteral(
"(Geo)Arrow" ),
1095 QObject::tr(
"(Geo)Arrow" ),
1096 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
1097 QStringLiteral(
"arrow" ),
1100 QStringLiteral(
"UTF-8" )
1105 datasetOptions.clear();
1106 layerOptions.clear();
1108 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
1110 QStringLiteral(
"Arc/Info ASCII Coverage" ),
1111 QObject::tr(
"Arc/Info ASCII Coverage" ),
1112 QStringLiteral(
"*.e00" ),
1113 QStringLiteral(
"e00" ),
1120#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,0)
1124 datasetOptions.clear();
1125 layerOptions.clear();
1128 QObject::tr(
"New BNA files are created by the "
1129 "systems default line termination conventions. "
1130 "This may be overridden here." ),
1132 << QStringLiteral(
"CRLF" )
1133 << QStringLiteral(
"LF" ),
1139 QObject::tr(
"By default, BNA files are created in multi-line format. "
1140 "For each record, the first line contains the identifiers and the "
1141 "type/number of coordinates to follow. Each following line contains "
1142 "a pair of coordinates." ),
1147 QObject::tr(
"BNA records may contain from 2 to 4 identifiers per record. "
1148 "Some software packages only support a precise number of identifiers. "
1149 "You can override the default value (2) by a precise value." ),
1151 << QStringLiteral(
"2" )
1152 << QStringLiteral(
"3" )
1153 << QStringLiteral(
"4" )
1154 << QStringLiteral(
"NB_SOURCE_FIELDS" ),
1155 QStringLiteral(
"2" )
1159 QObject::tr(
"The BNA writer will try to recognize ellipses and circles when writing a polygon. "
1160 "This will only work if the feature has previously been read from a BNA file. "
1161 "As some software packages do not support ellipses/circles in BNA data file, "
1162 "it may be useful to tell the writer by specifying ELLIPSES_AS_ELLIPSES=NO not "
1163 "to export them as such, but keep them as polygons." ),
1168 QObject::tr(
"Limit the number of coordinate pairs per line in multiline format." ),
1173 QObject::tr(
"Set the number of decimal for coordinates. Default value is 10." ),
1177 driverMetadata.insert( QStringLiteral(
"BNA" ),
1179 QStringLiteral(
"Atlas BNA" ),
1180 QObject::tr(
"Atlas BNA" ),
1181 QStringLiteral(
"*.bna" ),
1182 QStringLiteral(
"bna" ),
1190 datasetOptions.clear();
1191 layerOptions.clear();
1194 QObject::tr(
"By default when creating new .csv files they "
1195 "are created with the line termination conventions "
1196 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1197 "This may be overridden through the use of the LINEFORMAT option." ),
1199 << QStringLiteral(
"CRLF" )
1200 << QStringLiteral(
"LF" ),
1206 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1207 "It is possible to export the geometry in its WKT representation by "
1208 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1209 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1210 "or GEOMETRY=AS_YX." ),
1212 << QStringLiteral(
"AS_WKT" )
1213 << QStringLiteral(
"AS_XYZ" )
1214 << QStringLiteral(
"AS_XY" )
1215 << QStringLiteral(
"AS_YX" ),
1221 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1222 "column of the layer and its optional width and precision." ),
1227 QObject::tr(
"Field separator character." ),
1229 << QStringLiteral(
"COMMA" )
1230 << QStringLiteral(
"SEMICOLON" )
1231 << QStringLiteral(
"TAB" ),
1232 QStringLiteral(
"COMMA" )
1236 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1238 << QStringLiteral(
"IF_NEEDED" )
1239 << QStringLiteral(
"IF_AMBIGUOUS" )
1240 << QStringLiteral(
"ALWAYS" ),
1241 QStringLiteral(
"IF_AMBIGUOUS" )
1245 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1249 driverMetadata.insert( QStringLiteral(
"CSV" ),
1251 QStringLiteral(
"Comma Separated Value [CSV]" ),
1252 QObject::tr(
"Comma Separated Value [CSV]" ),
1253 QStringLiteral(
"*.csv" ),
1254 QStringLiteral(
"csv" ),
1261 datasetOptions.clear();
1262 layerOptions.clear();
1264 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1266 QStringLiteral(
"FlatGeobuf" ),
1267 QObject::tr(
"FlatGeobuf" ),
1268 QStringLiteral(
"*.fgb" ),
1269 QStringLiteral(
"fgb" ),
1272 QStringLiteral(
"UTF-8" )
1277 datasetOptions.clear();
1278 layerOptions.clear();
1281 QObject::tr(
"Override the type of shapefile created. "
1282 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1283 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1284 "MULTIPOINTZ for 3D;" ) +
1285 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1286 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1288 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1291 << QStringLiteral(
"NULL" )
1292 << QStringLiteral(
"POINT" )
1293 << QStringLiteral(
"ARC" )
1294 << QStringLiteral(
"POLYGON" )
1295 << QStringLiteral(
"MULTIPOINT" )
1296 << QStringLiteral(
"POINTZ" )
1297 << QStringLiteral(
"ARCZ" )
1298 << QStringLiteral(
"POLYGONZ" )
1299 << QStringLiteral(
"MULTIPOINTZ" )
1300 << QStringLiteral(
"POINTM" )
1301 << QStringLiteral(
"ARCM" )
1302 << QStringLiteral(
"POLYGONM" )
1303 << QStringLiteral(
"MULTIPOINTM" )
1304 << QStringLiteral(
"POINTZM" )
1305 << QStringLiteral(
"ARCZM" )
1306 << QStringLiteral(
"POLYGONZM" )
1307 << QStringLiteral(
"MULTIPOINTZM" )
1308 << QStringLiteral(
"MULTIPATCH" )
1318 QObject::tr(
"Set the encoding value in the DBF file. "
1319 "The default value is LDID/87. It is not clear "
1320 "what other values may be appropriate." ),
1328 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1332 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1334 QStringLiteral(
"ESRI Shapefile" ),
1335 QObject::tr(
"ESRI Shapefile" ),
1336 QStringLiteral(
"*.shp" ),
1337 QStringLiteral(
"shp" ),
1344 datasetOptions.clear();
1345 layerOptions.clear();
1347 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1349 QStringLiteral(
"DBF File" ),
1350 QObject::tr(
"DBF File" ),
1351 QStringLiteral(
"*.dbf" ),
1352 QStringLiteral(
"dbf" ),
1359 datasetOptions.clear();
1360 layerOptions.clear();
1362 driverMetadata.insert( QStringLiteral(
"FMEObjects Gateway" ),
1364 QStringLiteral(
"FMEObjects Gateway" ),
1365 QObject::tr(
"FMEObjects Gateway" ),
1366 QStringLiteral(
"*.fdd" ),
1367 QStringLiteral(
"fdd" ),
1374 datasetOptions.clear();
1375 layerOptions.clear();
1378 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1379 "of the geometries at the feature and feature collection level." ),
1384 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1385 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1390 QObject::tr(
"Whether to use RFC 7946 standard. "
1391 "If disabled GeoJSON 2008 initial version will be used. "
1392 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1396 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1398 QStringLiteral(
"GeoJSON" ),
1399 QObject::tr(
"GeoJSON" ),
1400 QStringLiteral(
"*.geojson" ),
1401 QStringLiteral(
"geojson" ),
1404 QStringLiteral(
"UTF-8" )
1409 datasetOptions.clear();
1410 layerOptions.clear();
1413 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1414 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1419 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1420 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1421 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1425 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1427 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1428 QObject::tr(
"GeoJSON - Newline Delimited" ),
1429 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1430 QStringLiteral(
"json" ),
1433 QStringLiteral(
"UTF-8" )
1438 datasetOptions.clear();
1439 layerOptions.clear();
1442 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1443 "Default value : RSS" ),
1445 << QStringLiteral(
"RSS" )
1446 << QStringLiteral(
"ATOM" ),
1447 QStringLiteral(
"RSS" )
1451 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1452 "W3C_GEO only supports point geometries. "
1453 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1455 << QStringLiteral(
"SIMPLE" )
1456 << QStringLiteral(
"GML" )
1457 << QStringLiteral(
"W3C_GEO" ),
1458 QStringLiteral(
"SIMPLE" )
1462 QObject::tr(
"If defined to YES, extension fields will be written. "
1463 "If the field name not found in the base schema matches "
1464 "the foo_bar pattern, foo will be considered as the namespace "
1465 "of the element, and a <foo:bar> element will be written. "
1466 "Otherwise, elements will be written in the <ogr:> namespace." ),
1471 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1472 "The user will have to provide the appropriate header and footer of the document." ),
1477 QObject::tr(
"XML content that will be put between the <channel> element and the "
1478 "first <item> element for a RSS document, or between the xml tag and "
1479 "the first <entry> element for an Atom document." ),
1484 QObject::tr(
"Value put inside the <title> element in the header. "
1485 "If not provided, a dummy value will be used as that element is compulsory." ),
1490 QObject::tr(
"Value put inside the <description> element in the header. "
1491 "If not provided, a dummy value will be used as that element is compulsory." ),
1496 QObject::tr(
"Value put inside the <link> element in the header. "
1497 "If not provided, a dummy value will be used as that element is compulsory." ),
1502 QObject::tr(
"Value put inside the <updated> element in the header. "
1503 "Should be formatted as a XML datetime. "
1504 "If not provided, a dummy value will be used as that element is compulsory." ),
1509 QObject::tr(
"Value put inside the <author><name> element in the header. "
1510 "If not provided, a dummy value will be used as that element is compulsory." ),
1515 QObject::tr(
"Value put inside the <id> element in the header. "
1516 "If not provided, a dummy value will be used as that element is compulsory." ),
1520 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1522 QStringLiteral(
"GeoRSS" ),
1523 QObject::tr(
"GeoRSS" ),
1524 QStringLiteral(
"*.xml" ),
1525 QStringLiteral(
"xml" ),
1528 QStringLiteral(
"UTF-8" )
1533 datasetOptions.clear();
1534 layerOptions.clear();
1537 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1538 "Note that the schema file isn't actually accessed by OGR, so it "
1539 "is up to the user to ensure it will match the schema of the OGR "
1540 "produced GML data file." ),
1545 QObject::tr(
"This writes a GML application schema file to a corresponding "
1546 ".xsd file (with the same basename). If INTERNAL is used the "
1547 "schema is written within the GML file, but this is experimental "
1548 "and almost certainly not valid XML. "
1549 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1551 << QStringLiteral(
"EXTERNAL" )
1552 << QStringLiteral(
"INTERNAL" )
1553 << QStringLiteral(
"OFF" ),
1554 QStringLiteral(
"EXTERNAL" )
1558 QObject::tr(
"This is the prefix for the application target namespace." ),
1559 QStringLiteral(
"ogr" )
1563 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1564 "application target namespace in the GML file." ),
1569 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1570 "This is the application target namespace." ),
1571 QStringLiteral(
"http://ogr.maptools.org/" )
1575 QObject::tr(
"GML version to use." ),
1577 << QStringLiteral(
"GML2" )
1578 << QStringLiteral(
"GML3" )
1579 << QStringLiteral(
"GML3Deegree" )
1580 << QStringLiteral(
"GML3.2" ),
1581 QStringLiteral(
"GML3.2" )
1585 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1586 "If YES, SRS with EPSG authority will be written with the "
1587 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1588 "geographic SRS without explicit AXIS order, but that the same "
1589 "SRS authority code imported with ImportFromEPSGA() should be "
1590 "treated as lat/long, then the function will take care of coordinate "
1591 "order swapping. If set to NO, SRS with EPSG authority will be "
1592 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1597 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1598 "If set to NO, the <gml:boundedBy> element will not be written for "
1604 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1605 "for more readability, but at the expense of file size." ),
1610 driverMetadata.insert( QStringLiteral(
"GML" ),
1612 QStringLiteral(
"Geography Markup Language [GML]" ),
1613 QObject::tr(
"Geography Markup Language [GML]" ),
1614 QStringLiteral(
"*.gml" ),
1615 QStringLiteral(
"gml" ),
1618 QStringLiteral(
"UTF-8" )
1623 datasetOptions.clear();
1624 layerOptions.clear();
1627 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1632 QObject::tr(
"Human-readable description for the layer content" ),
1637 QObject::tr(
"Name for the feature identifier column" ),
1638 QStringLiteral(
"fid" )
1642 QObject::tr(
"Name for the geometry column" ),
1643 QStringLiteral(
"geom" )
1647 QObject::tr(
"If a spatial index must be created." ),
1651 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1653 QStringLiteral(
"GeoPackage" ),
1654 QObject::tr(
"GeoPackage" ),
1655 QStringLiteral(
"*.gpkg" ),
1656 QStringLiteral(
"gpkg" ),
1659 QStringLiteral(
"UTF-8" )
1664 datasetOptions.clear();
1665 layerOptions.clear();
1667 driverMetadata.insert( QStringLiteral(
"GMT" ),
1669 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1670 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1671 QStringLiteral(
"*.gmt" ),
1672 QStringLiteral(
"gmt" ),
1679 datasetOptions.clear();
1680 layerOptions.clear();
1683 QObject::tr(
"By default when writing a layer whose features are of "
1684 "type wkbLineString, the GPX driver chooses to write "
1685 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1686 "they will be written as tracks." ),
1691 QObject::tr(
"By default when writing a layer whose features are of "
1692 "type wkbMultiLineString, the GPX driver chooses to write "
1693 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1694 "they will be written as routes, provided that the multilines "
1695 "are composed of only one single line." ),
1700 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1701 "extra fields will be written inside the <extensions> tag." ),
1706 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1707 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1708 QStringLiteral(
"ogr" )
1712 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1713 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1714 QStringLiteral(
"http://osgeo.org/gdal" )
1718 QObject::tr(
"By default files are created with the line termination "
1719 "conventions of the local platform (CR/LF on win32 or LF "
1720 "on all other systems). This may be overridden through use "
1721 "of the LINEFORMAT layer creation option which may have a value "
1722 "of CRLF (DOS format) or LF (Unix format)." ),
1724 << QStringLiteral(
"CRLF" )
1725 << QStringLiteral(
"LF" ),
1730 driverMetadata.insert( QStringLiteral(
"GPX" ),
1732 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1733 QObject::tr(
"GPS eXchange Format [GPX]" ),
1734 QStringLiteral(
"*.gpx" ),
1735 QStringLiteral(
"gpx" ),
1738 QStringLiteral(
"UTF-8" )
1743 datasetOptions.clear();
1744 layerOptions.clear();
1746 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1748 QStringLiteral(
"INTERLIS 1" ),
1749 QObject::tr(
"INTERLIS 1" ),
1750 QStringLiteral(
"*.itf *.xml *.ili" ),
1751 QStringLiteral(
"ili" ),
1758 datasetOptions.clear();
1759 layerOptions.clear();
1761 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1763 QStringLiteral(
"INTERLIS 2" ),
1764 QObject::tr(
"INTERLIS 2" ),
1765 QStringLiteral(
"*.xtf *.xml *.ili" ),
1766 QStringLiteral(
"ili" ),
1773 datasetOptions.clear();
1774 layerOptions.clear();
1777 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1778 QStringLiteral(
"Name" )
1782 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1783 QStringLiteral(
"Description" )
1787 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1788 "This will only affect 3D geometries and must be one of the valid KML options." ),
1790 << QStringLiteral(
"clampToGround" )
1791 << QStringLiteral(
"relativeToGround" )
1792 << QStringLiteral(
"absolute" ),
1793 QStringLiteral(
"relativeToGround" )
1797 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1798 "the id of the root <Document> node. The default value is root_doc." ),
1799 QStringLiteral(
"root_doc" )
1802 driverMetadata.insert( QStringLiteral(
"KML" ),
1804 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1805 QObject::tr(
"Keyhole Markup Language [KML]" ),
1806 QStringLiteral(
"*.kml" ),
1807 QStringLiteral(
"kml" ),
1810 QStringLiteral(
"UTF-8" )
1815 datasetOptions.clear();
1816 layerOptions.clear();
1818 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1821 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1822 "In this mode writing files can be about 5 times faster, "
1823 "but spatial queries can be up to 30 times slower." ),
1825 << QStringLiteral(
"QUICK" )
1826 << QStringLiteral(
"OPTIMIZED" ),
1827 QStringLiteral(
"QUICK" ),
1832 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1833 "to 512. MapInfo 15.2 and above creates .tab files with a "
1834 "blocksize of 16384 bytes. Any MapInfo version should be "
1835 "able to handle block sizes from 512 to 32256." ),
1839 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1840 "accuracy of the coordinates. Note: the geometry of written "
1841 "features must be within the defined box." ),
1845 insertMapInfoOptions( datasetOptions, layerOptions );
1847 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1849 QStringLiteral(
"Mapinfo" ),
1850 QObject::tr(
"Mapinfo TAB" ),
1851 QStringLiteral(
"*.tab" ),
1852 QStringLiteral(
"tab" ),
1857 datasetOptions.clear();
1858 layerOptions.clear();
1859 insertMapInfoOptions( datasetOptions, layerOptions );
1862 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1864 QStringLiteral(
"Mapinfo" ),
1865 QObject::tr(
"Mapinfo MIF" ),
1866 QStringLiteral(
"*.mif" ),
1867 QStringLiteral(
"mif" ),
1874 datasetOptions.clear();
1875 layerOptions.clear();
1878 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1879 "seed file should be used. This option is ignored if the SEED option is provided." ),
1884 QObject::tr(
"Override the seed file to use." ),
1889 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1890 "If not, only the first three elements will be copied." ),
1895 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1900 QObject::tr(
"Override the master unit name from the seed file with "
1901 "the provided one or two character unit name." ),
1906 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1907 "one or two character unit name." ),
1912 QObject::tr(
"Override the number of subunits per master unit. "
1913 "By default the seed file value is used." ),
1918 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1919 "per sub unit. By default the seed file value is used." ),
1924 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1925 "By default the origin from the seed file is used." ),
1929 driverMetadata.insert( QStringLiteral(
"DGN" ),
1931 QStringLiteral(
"Microstation DGN" ),
1932 QObject::tr(
"Microstation DGN" ),
1933 QStringLiteral(
"*.dgn" ),
1934 QStringLiteral(
"dgn" ),
1941 datasetOptions.clear();
1942 layerOptions.clear();
1945 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1947 << QStringLiteral(
"APPLY" )
1948 << QStringLiteral(
"IGNORE" ),
1949 QStringLiteral(
"APPLY" )
1953 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1954 "Multipoint geometries are not well handled by many formats, "
1955 "so it can be convenient to split single sounding features with many points "
1956 "into many single point features." ),
1961 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1962 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1968 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1969 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1974 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1975 "be preserved as a special numeric value. This option should not generally "
1976 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1981 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1982 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1987 QObject::tr(
"Should additional attributes relating features to their underlying "
1988 "geometric primitives be attached. These are the values of the FSPT group, "
1989 "and are primarily needed when doing S-57 to S-57 translations." ),
1994 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1995 "specified in the S57 DSSI record." ),
2001 driverMetadata.insert( QStringLiteral(
"S57" ),
2003 QStringLiteral(
"S-57 Base file" ),
2004 QObject::tr(
"S-57 Base file" ),
2005 QStringLiteral(
"*.000" ),
2006 QStringLiteral(
"000" ),
2013 datasetOptions.clear();
2014 layerOptions.clear();
2016 driverMetadata.insert( QStringLiteral(
"SDTS" ),
2018 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
2019 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
2020 QStringLiteral(
"*catd.ddf" ),
2021 QStringLiteral(
"ddf" ),
2028 datasetOptions.clear();
2029 layerOptions.clear();
2032 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2033 "tables in a new database. By default these metadata tables are created "
2034 "when a new database is created." ),
2040 QStringLiteral(
"NO" )
2045 QStringLiteral(
"NO" )
2049 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
2050 "This is generally more space and processing efficient, but harder "
2051 "to inspect or use in simple applications than WKT (Well Known Text)." ),
2053 << QStringLiteral(
"WKB" )
2054 << QStringLiteral(
"WKT" ),
2055 QStringLiteral(
"WKB" )
2059 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2060 "in SQLite. Laundered names will be converted to lower case and some special "
2061 "characters(' - #) will be changed to underscores." ),
2066 QStringLiteral(
"NO" )
2070 QStringLiteral(
"NO" )
2078 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2079 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2080 "for databases that have big string blobs. However, use with care, since "
2081 "the value of such columns will be seen as compressed binary content with "
2082 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2083 "modifying or querying compressed columns, compression/decompression is "
2084 "done transparently. However, such columns cannot be (easily) queried with "
2085 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2086 "have the 'VARCHAR_deflate' declaration type." ),
2090 driverMetadata.insert( QStringLiteral(
"SQLite" ),
2092 QStringLiteral(
"SQLite" ),
2093 QObject::tr(
"SQLite" ),
2094 QStringLiteral(
"*.sqlite" ),
2095 QStringLiteral(
"sqlite" ),
2098 QStringLiteral(
"UTF-8" )
2103 datasetOptions.clear();
2104 layerOptions.clear();
2107 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2108 "tables in a new database. By default these metadata tables are created "
2109 "when a new database is created." ),
2114 QStringLiteral(
"YES" )
2118 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2119 "Set to NO for regular SQLite databases." ),
2124 QStringLiteral(
"SPATIALITE" )
2128 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2129 "in SQLite. Laundered names will be converted to lower case and some special "
2130 "characters(' - #) will be changed to underscores." ),
2135 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2136 "against libspatialite, this option can be used to control if a spatial "
2137 "index must be created." ),
2142 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2143 "this option can be used to control if the compressed format for "
2144 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2149 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2150 "When this option isn't specified and that a SRS is associated with the "
2151 "layer, a search is made in the spatial_ref_sys to find a match for the "
2152 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2153 "the spatial_ref_sys table. When the SRID option is specified, this "
2154 "search (and the eventual insertion of a new entry) will not be done: "
2155 "the specified SRID is used as such." ),
2160 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2161 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2162 "for databases that have big string blobs. However, use with care, since "
2163 "the value of such columns will be seen as compressed binary content with "
2164 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2165 "modifying or queryings compressed columns, compression/decompression is "
2166 "done transparently. However, such columns cannot be (easily) queried with "
2167 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2168 "have the 'VARCHAR_deflate' declaration type." ),
2172 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2174 QStringLiteral(
"SpatiaLite" ),
2175 QObject::tr(
"SpatiaLite" ),
2176 QStringLiteral(
"*.sqlite" ),
2177 QStringLiteral(
"sqlite" ),
2180 QStringLiteral(
"UTF-8" )
2184 datasetOptions.clear();
2185 layerOptions.clear();
2188 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2193 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2197 driverMetadata.insert( QStringLiteral(
"DXF" ),
2199 QStringLiteral(
"AutoCAD DXF" ),
2200 QObject::tr(
"AutoCAD DXF" ),
2201 QStringLiteral(
"*.dxf" ),
2202 QStringLiteral(
"dxf" ),
2209 datasetOptions.clear();
2210 layerOptions.clear();
2213 QObject::tr(
"Indicates the GeoConcept export file extension. "
2214 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2216 << QStringLiteral(
"GXT" )
2217 << QStringLiteral(
"TXT" ),
2218 QStringLiteral(
"GXT" )
2222 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2223 "In this file, every line must start with //# followed by a keyword. "
2224 "Lines starting with // are comments." ),
2229 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2230 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2231 "the Name found in the GCT file for a sub-type section within the previous "
2236 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2238 QStringLiteral(
"Geoconcept" ),
2239 QObject::tr(
"Geoconcept" ),
2240 QStringLiteral(
"*.gxt *.txt" ),
2241 QStringLiteral(
"gxt" ),
2248 datasetOptions.clear();
2249 layerOptions.clear();
2252 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2253 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2258 QObject::tr(
"Set layer name alias." ),
2263 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2264 QStringLiteral(
"SHAPE" )
2268 QObject::tr(
"Whether the values of the geometry column can be NULL. Can be set to NO so that geometry is required. Default to 'YES'." ),
2273 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2274 QStringLiteral(
"OBJECTID" )
2290 QObject::tr(
"A list of strings of format field_name=fgdb_field_type (separated by comma) to force the FileGDB column type of fields to be created." ),
2295 QObject::tr(
"XML documentation for the layer." ),
2299 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2300 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2301 QStringLiteral(
"DEFAULTS" ),
2306 QObject::tr(
" Defaults to NO (through CreateLayer() API). When this option is set, a Shape_Area and Shape_Length special fields will be created for polygonal layers (Shape_Length only for linear layers). These fields will automatically be populated with the feature’s area or length whenever a new feature is added to the dataset or an existing feature is amended. When using ogr2ogr with a source layer that has Shape_Area/Shape_Length special fields, and this option is not explicitly specified, it will be automatically set, so that the resulting FileGeodatabase has those fields properly tagged." ),
2310 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2312 QStringLiteral(
"ESRI File Geodatabase" ),
2313 QObject::tr(
"ESRI File Geodatabase" ),
2314 QStringLiteral(
"*.gdb" ),
2315 QStringLiteral(
"gdb" ),
2318 QStringLiteral(
"UTF-8" )
2323 datasetOptions.clear();
2324 layerOptions.clear();
2327 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2328 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2333 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2334 QStringLiteral(
"SHAPE" )
2338 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2339 QStringLiteral(
"OBJECTID" )
2342 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2344 QStringLiteral(
"ESRI FileGDB" ),
2345 QObject::tr(
"ESRI FileGDB" ),
2346 QStringLiteral(
"*.gdb" ),
2347 QStringLiteral(
"gdb" ),
2350 QStringLiteral(
"UTF-8" )
2355 datasetOptions.clear();
2356 layerOptions.clear();
2359 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2360 "to STRING, all fields will be of String type." ),
2362 << QStringLiteral(
"AUTO" )
2363 << QStringLiteral(
"STRING" ),
2364 QStringLiteral(
"AUTO" ),
2369 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2370 "if the first line might be the name of columns. If set to FORCE, the driver "
2371 "will consider the first line as the header line. If set to "
2372 "DISABLE, it will be considered as the first feature. Otherwise "
2373 "auto-detection will occur." ),
2375 << QStringLiteral(
"FORCE" )
2376 << QStringLiteral(
"DISABLE" )
2377 << QStringLiteral(
"AUTO" ),
2378 QStringLiteral(
"AUTO" ),
2382 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2384 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2385 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2386 QStringLiteral(
"*.xlsx" ),
2387 QStringLiteral(
"xlsx" ),
2390 QStringLiteral(
"UTF-8" )
2395 datasetOptions.clear();
2396 layerOptions.clear();
2399 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2400 "to STRING, all fields will be of String type." ),
2402 << QStringLiteral(
"AUTO" )
2403 << QStringLiteral(
"STRING" ),
2404 QStringLiteral(
"AUTO" ),
2409 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2410 "if the first line might be the name of columns. If set to FORCE, the driver "
2411 "will consider the first line as the header line. If set to "
2412 "DISABLE, it will be considered as the first feature. Otherwise "
2413 "auto-detection will occur." ),
2415 << QStringLiteral(
"FORCE" )
2416 << QStringLiteral(
"DISABLE" )
2417 << QStringLiteral(
"AUTO" ),
2418 QStringLiteral(
"AUTO" ),
2422 driverMetadata.insert( QStringLiteral(
"ODS" ),
2424 QStringLiteral(
"Open Document Spreadsheet" ),
2425 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2426 QStringLiteral(
"*.ods" ),
2427 QStringLiteral(
"ods" ),
2430 QStringLiteral(
"UTF-8" )
2435 datasetOptions.clear();
2436 layerOptions.clear();
2439 QObject::tr(
"Compression method." ),
2441 << QStringLiteral(
"UNCOMPRESSED" )
2442 << QStringLiteral(
"SNAPPY" ),
2443 QStringLiteral(
"SNAPPY" ),
2448 QObject::tr(
"Geometry encoding." ),
2450 << QStringLiteral(
"WKB" )
2451 << QStringLiteral(
"WKT" )
2452 << QStringLiteral(
"GEOARROW" ),
2453 QStringLiteral(
"WKB" ),
2458 QObject::tr(
"Maximum number of rows per group." ),
2463 QObject::tr(
"Name for the feature identifier column" ),
2468 QObject::tr(
"Name for the geometry column" ),
2469 QStringLiteral(
"geometry" )
2473 QObject::tr(
"Name of the coordinate system for the edges." ),
2475 << QStringLiteral(
"PLANAR" )
2476 << QStringLiteral(
"SPHERICAL" ),
2477 QStringLiteral(
"PLANAR" ),
2481 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2483 QStringLiteral(
"(Geo)Parquet" ),
2484 QObject::tr(
"(Geo)Parquet" ),
2485 QStringLiteral(
"*.parquet" ),
2486 QStringLiteral(
"parquet" ),
2489 QStringLiteral(
"UTF-8" )
2494 datasetOptions.clear();
2495 layerOptions.clear();
2498 QObject::tr(
"Line termination character sequence." ),
2500 << QStringLiteral(
"CRLF" )
2501 << QStringLiteral(
"LF" ),
2502 QStringLiteral(
"LF" ),
2508 QObject::tr(
"Format of geometry columns." ),
2510 << QStringLiteral(
"geometry" )
2511 << QStringLiteral(
"geography" ),
2512 QStringLiteral(
"geometry" ),
2517 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2518 "Laundered names will be converted to lower case and some special "
2519 "characters(' - #) will be changed to underscores." ),
2524 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2525 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2528 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2531 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2536 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2541 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2543 << QStringLiteral(
"YES" )
2544 << QStringLiteral(
"NO" )
2545 << QStringLiteral(
"IF_EXISTS" ),
2546 QStringLiteral(
"YES" ),
2551 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2552 "When this option isn't specified and that a SRS is associated with the "
2553 "layer, a search is made in the spatial_ref_sys to find a match for the "
2554 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2555 "the spatial_ref_sys table. When the SRID option is specified, this "
2556 "search (and the eventual insertion of a new entry) will not be done: "
2557 "the specified SRID is used as such." ),
2562 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2563 "Important to set it correctly if using non-linear geometry types" ),
2564 QStringLiteral(
"2.2" )
2567 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2569 QStringLiteral(
"PostgreSQL SQL dump" ),
2570 QObject::tr(
"PostgreSQL SQL dump" ),
2571 QStringLiteral(
"*.sql" ),
2572 QStringLiteral(
"sql" ),
2575 QStringLiteral(
"UTF-8" )
2581 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2582 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2583 ~QgsVectorFileWriterMetadataContainer()
2585 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2587 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2588 delete optionIt.value();
2589 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2590 delete optionIt.value();
2594 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2601 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2602 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2604 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2606 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2607 driverName != QLatin1String(
"PGDUMP" ) &&
2608 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2613 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2628 return QStringList();
2637 return QStringList();
2644 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2675 return mCapabilities;
2685 QgsFeatureList::iterator fIt = features.begin();
2687 for ( ; fIt != features.end(); ++fIt )
2712 QString styleString;
2713 QString currentStyle;
2715 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2716 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2718 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2719 for (
int i = 0; i < nSymbolLayers; ++i )
2722 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2728 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2729 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2731 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2737 if ( symbolIt != symbols.constBegin() || i != 0 )
2739 styleString.append(
';' );
2741 styleString.append( currentStyle );
2746 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2747 if ( !writeFeature(
mLayer, poFeature.get() ) )
2759 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2767 if ( !writeFeature(
mLayer, poFeature.get() ) )
2791 int fldIdx = it.key();
2792 int ogrField = it.value();
2794 QVariant attrValue = feature.
attribute( fldIdx );
2799 OGR_F_UnsetField( poFeature.get(), ogrField );
2812 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2827 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2828 .arg( feature.
attribute( fldIdx ).toString(),
2835 switch ( field.
type() )
2837 case QMetaType::Type::Int:
2838 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2840 case QMetaType::Type::LongLong:
2841 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2843 case QMetaType::Type::Bool:
2844 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2846 case QMetaType::Type::QString:
2847 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2849 case QMetaType::Type::Double:
2850 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2852 case QMetaType::Type::QDate:
2853 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2854 attrValue.toDate().year(),
2855 attrValue.toDate().month(),
2856 attrValue.toDate().day(),
2859 case QMetaType::Type::QDateTime:
2862 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2866 const QDateTime dt = attrValue.toDateTime();
2867 const QDate date = dt.date();
2868 const QTime time = dt.time();
2869 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2875 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2879 case QMetaType::Type::QTime:
2882 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2886 const QTime time = attrValue.toTime();
2887 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2891 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2896 case QMetaType::Type::QByteArray:
2898 const QByteArray ba = attrValue.toByteArray();
2899 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2903 case QMetaType::Type::UnknownType:
2906 case QMetaType::Type::QStringList:
2911 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2913 if ( !doc.isNull() )
2915 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2917 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2921 QStringList list = attrValue.toStringList();
2922 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2924 int count = list.count();
2925 char **lst =
new char *[count + 1];
2929 for (
const QString &
string : list )
2931 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2935 lst[count] =
nullptr;
2936 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2941 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2946 case QMetaType::Type::QVariantList:
2950 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2952 if ( !doc.isNull() )
2954 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
2956 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2961 if ( field.
subType() == QMetaType::Type::QString )
2963 QStringList list = attrValue.toStringList();
2964 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2966 int count = list.count();
2967 char **lst =
new char *[count + 1];
2971 for (
const QString &
string : list )
2973 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2977 lst[count] =
nullptr;
2978 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2983 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2987 else if ( field.
subType() == QMetaType::Type::Int )
2989 const QVariantList list = attrValue.toList();
2990 if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
2992 const int count = list.count();
2993 int *lst =
new int[count];
2997 for (
const QVariant &value : list )
2999 lst[pos] = value.toInt();
3003 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
3008 QStringList strings;
3009 strings.reserve( list.size() );
3010 for (
const QVariant &value : list )
3012 strings << QString::number( value.toInt() );
3014 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3018 else if ( field.
subType() == QMetaType::Type::Double )
3020 const QVariantList list = attrValue.toList();
3021 if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
3023 const int count = list.count();
3024 double *lst =
new double[count];
3028 for (
const QVariant &value : list )
3030 lst[pos] = value.toDouble();
3034 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
3039 QStringList strings;
3040 strings.reserve( list.size() );
3041 for (
const QVariant &value : list )
3043 strings << QString::number( value.toDouble() );
3045 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3049 else if ( field.
subType() == QMetaType::Type::LongLong )
3051 const QVariantList list = attrValue.toList();
3052 if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
3054 const int count = list.count();
3055 long long *lst =
new long long[count];
3059 for (
const QVariant &value : list )
3061 lst[pos] = value.toLongLong();
3065 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
3070 QStringList strings;
3071 strings.reserve( list.size() );
3072 for (
const QVariant &value : list )
3074 strings << QString::number( value.toLongLong() );
3076 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3083 case QMetaType::Type::QVariantMap:
3086 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
3087 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
3089 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3091 if ( !doc.isNull() )
3093 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3094 jsonString = QString::fromUtf8( json.data() );
3096 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3106 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
3109 .arg( attrValue.typeName(),
3110 attrValue.toString() );
3123 if ( mCoordinateTransform )
3128 geom.
transform( *mCoordinateTransform );
3146 OGRGeometryH mGeom2 =
nullptr;
3175 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3182 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3202 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3203 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3213 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3214 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3215 if ( err != OGRERR_NONE )
3217 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3218 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3225 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3233 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3235 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3236 if ( err != OGRERR_NONE )
3238 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3239 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3246 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3261 for (
int i = 0; i < attributes.size(); i++ )
3263 if ( omap.find( i ) != omap.end() )
3268bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3270 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3272 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3282 if ( mUsingTransaction )
3284 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3286 QgsDebugError( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3299 const QString &fileName,
3300 const QString &fileEncoding,
3302 const QString &driverName,
3304 QString *errorMessage,
3305 const QStringList &datasourceOptions,
3306 const QStringList &layerOptions,
3307 bool skipAttributeCreation,
3308 QString *newFilename,
3310 double symbologyScale,
3320 if ( destCRS.
isValid() && layer )
3346 const QString &fileName,
3347 const QString &fileEncoding,
3349 const QString &driverName,
3351 QString *errorMessage,
3352 const QStringList &datasourceOptions,
3353 const QStringList &layerOptions,
3354 bool skipAttributeCreation,
3355 QString *newFilename,
3357 double symbologyScale,
3388 : driverName( QStringLiteral(
"GPKG" ) )
3396 if ( !layer || !layer->
isValid() )
3403 details.sourceCrs = layer->
crs();
3404 details.sourceWkbType = layer->
wkbType();
3405 details.sourceFields = layer->
fields();
3414 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3422 details.geometryTypeScanIterator = layer->
getFeatures( req );
3426 details.renderContext.setExpressionContext( details.expressionContext );
3427 details.renderContext.setRendererScale( options.
symbologyScale );
3429 details.shallTransform =
false;
3434 details.shallTransform =
true;
3439 details.outputCrs = details.sourceCrs;
3442 details.destWkbType = details.sourceWkbType;
3456 details.attributes.clear();
3457 else if ( details.attributes.isEmpty() )
3459 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3460 for (
int idx : allAttributes )
3462 QgsField fld = details.sourceFields.at( idx );
3463 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3465 details.attributes.append( idx );
3469 if ( !details.attributes.isEmpty() )
3471 for (
int attrIdx : std::as_const( details.attributes ) )
3473 if ( details.sourceFields.exists( attrIdx ) )
3475 QgsField field = details.sourceFields.at( attrIdx );
3477 details.outputFields.append( field );
3481 QgsDebugError( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3488 if ( details.providerType == QLatin1String(
"spatialite" ) )
3490 for (
int i = 0; i < details.outputFields.size(); i++ )
3492 if ( details.outputFields.at( i ).type() == QMetaType::Type::LongLong )
3497 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3499 details.outputFields[i].setType( QMetaType::Type::Int );
3507 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3517 bool useFilterRect =
true;
3518 if ( details.shallTransform )
3529 useFilterRect =
false;
3532 if ( useFilterRect )
3538 details.filterRectEngine->prepareGeometry();
3540 details.sourceFeatureIterator = layer->
getFeatures( req );
3559 int lastProgressReport = 0;
3560 long long total = details.featureCount;
3563 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3565 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3566 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3570 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3571 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3572 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3573 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3576 *
errorMessage = QObject::tr(
"Cannot overwrite a OGR layer in place" );
3596 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3597 if ( newProgress != lastProgressReport )
3599 lastProgressReport = newProgress;
3614 QString tempNewFilename;
3615 QString tempNewLayer;
3623 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions,
QgsFeatureSink::SinkFlags(), &tempNewFilename, &tempNewLayer ) );
3627 *newFilename = tempNewFilename;
3630 *newLayer = tempNewLayer;
3659 switch ( writer->symbologyExport() )
3677 int n = 0, errors = 0;
3686 writer->startRender( details.renderer.get(), details.sourceFields );
3688 writer->resetMap( details.attributes );
3690 writer->mFields = details.sourceFields;
3694 int initialProgress = lastProgressReport;
3695 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3706 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3707 if ( newProgress < 100 && newProgress != lastProgressReport )
3709 lastProgressReport = newProgress;
3714 if ( details.shallTransform )
3727 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" )
3728 .arg( fet.
id() ).arg( e.
what() );
3745 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3752 *
errorMessage = QObject::tr(
"Feature write errors:" );
3758 if ( errors > 1000 )
3762 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3772 writer->stopRender();
3776 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3781 bool metadataFailure =
false;
3786 {QStringLiteral(
"path" ), tempNewFilename },
3787 {QStringLiteral(
"layerName" ), tempNewLayer }
3801 metadataFailure =
true;
3812 metadataFailure =
true;
3820 const QString &fileName,
3822 QString *newFilename,
3826 QgsVectorFileWriter::PreparedWriterDetails details;
3827 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3835 const QString &fileName,
3838 QString *newFilename,
3842 QgsVectorFileWriter::PreparedWriterDetails details;
3843 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3852 QgsVectorFileWriter::PreparedWriterDetails details;
3853 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3862 QFileInfo fi( fileName );
3863 QDir dir = fi.dir();
3866 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3868 filter << fi.completeBaseName() + suffix;
3872 const auto constEntryList = dir.entryList( filter );
3873 for (
const QString &file : constEntryList )
3875 QFile f( dir.canonicalPath() +
'/' + file );
3878 QgsDebugError( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3894 QStringList driverNames;
3897 for (
int i = 0; i < GDALGetDriverCount(); ++i )
3899 GDALDriverH
driver = GDALGetDriver( i );
3906 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
3907 if ( driverExtensions.isEmpty() )
3910 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
3911 if ( splitExtensions.intersects( multiLayerExtensions ) )
3913 driverNames << OGR_Dr_GetName(
driver );
3921 static QReadWriteLock sFilterLock;
3922 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3926 const auto it = sFilters.constFind( options );
3927 if ( it != sFilters.constEnd() )
3931 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3934 int const drvCount = OGRGetDriverCount();
3938 for (
int i = 0; i < drvCount; ++i )
3940 OGRSFDriverH drv = OGRGetDriver( i );
3943 const QString drvName = OGR_Dr_GetName( drv );
3947 if ( !multiLayerDrivers.contains( drvName ) )
3951 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
3952 bool nonSpatialFormat =
false;
3955 nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL,
nullptr ) !=
nullptr;
3958 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
3963 if ( nonSpatialFormat )
3968 if ( filterString.isEmpty() )
3975 globs = metadata.
glob.toLower().split(
' ' );
3981 details.
globs = globs;
3990 if ( options & SortRecommended )
3992 if ( a.driverName == QLatin1String(
"GPKG" ) )
3994 else if ( b.driverName == QLatin1String(
"GPKG" ) )
3996 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
3998 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4005 sFilters.insert( options, results );
4012 QSet< QString > extensions;
4014 const thread_local QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
4018 for (
const QString &glob : format.globs )
4020 const QRegularExpressionMatch match = rx.match( glob );
4021 if ( !match.hasMatch() )
4024 const QString matched = match.captured( 1 );
4025 extensions.insert( matched );
4029 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
4031 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
4033 if ( options & SortRecommended )
4035 if ( a == QLatin1String(
"gpkg" ) )
4037 else if ( b == QLatin1String(
"gpkg" ) )
4039 else if ( a == QLatin1String(
"shp" ) )
4041 else if ( b == QLatin1String(
"shp" ) )
4045 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
4048 return extensionList;
4053 QList< QgsVectorFileWriter::DriverDetails > results;
4056 const int drvCount = OGRGetDriverCount();
4060 QStringList writableDrivers;
4061 for (
int i = 0; i < drvCount; ++i )
4063 OGRSFDriverH drv = OGRGetDriver( i );
4066 const QString drvName = OGR_Dr_GetName( drv );
4070 if ( !multiLayerDrivers.contains( drvName ) )
4078 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
4082 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
4084 writableDrivers << QStringLiteral(
"DBF file" );
4086 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4089 if ( drvName == QLatin1String(
"MapInfo File" ) )
4091 writableDrivers << QStringLiteral(
"MapInfo MIF" );
4093 else if ( drvName == QLatin1String(
"SQLite" ) )
4100 QString option = QStringLiteral(
"SPATIALITE=YES" );
4101 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4102 OGRSFDriverH poDriver;
4104 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4107 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
4110 writableDrivers << QStringLiteral(
"SpatiaLite" );
4111 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
4114 CPLFree( options[0] );
4116 writableDrivers << drvName;
4121 results.reserve( writableDrivers.count() );
4122 for (
const QString &drvName : std::as_const( writableDrivers ) )
4136 if ( options & SortRecommended )
4138 if ( a.driverName == QLatin1String(
"GPKG" ) )
4140 else if ( b.driverName == QLatin1String(
"GPKG" ) )
4142 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
4144 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4148 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4155 QString ext = extension.trimmed();
4156 if ( ext.isEmpty() )
4159 if ( ext.startsWith(
'.' ) )
4163 int const drvCount = GDALGetDriverCount();
4165 for (
int i = 0; i < drvCount; ++i )
4167 GDALDriverH drv = GDALGetDriver( i );
4173 QString drvName = GDALGetDriverShortName( drv );
4174 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4176 const auto constDriverExtensions = driverExtensions;
4177 for (
const QString &
driver : constDriverExtensions )
4179 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4190 QString filterString;
4194 if ( !filterString.isEmpty() )
4195 filterString += QLatin1String(
";;" );
4197 filterString += details.filterString;
4199 return filterString;
4208 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
4209 metadata.
glob.toLower(),
4210 metadata.
glob.toUpper() );
4215 if ( codecName == QLatin1String(
"System" ) )
4216 return QStringLiteral(
"LDID/0" );
4218 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4219 const QRegularExpressionMatch match = re.match( codecName );
4220 if ( match.hasMatch() )
4222 QString
c = match.captured( 2 ).remove(
'-' );
4224 ( void )
c.toInt( &isNumber );
4252 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4253 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4256 int nTotalLevels = 0;
4258 QgsSymbolList::iterator symbolIt = symbolList.begin();
4259 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4261 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4262 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4264 int nLevels = ( *symbolIt )->symbolLayerCount();
4265 for (
int i = 0; i < nLevels; ++i )
4267 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4268 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4269 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4273 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4279 if ( !details.renderer )
4284 QHash< QgsSymbol *, QList<QgsFeature> > features;
4293 startRender( details.renderer.get(), details.sourceFields );
4313 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4324 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4325 if ( !featureSymbol )
4330 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4331 if ( it == features.end() )
4333 it = features.insert( featureSymbol, QList<QgsFeature>() );
4335 it.value().append( fet );
4340 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4341 for (
int i = 0; i < symbols.count(); i++ )
4347 if ( level < 0 || level >= 1000 )
4350 while ( level >= levels.count() )
4352 levels[level].append( item );
4357 int nTotalFeatures = 0;
4360 for (
int l = 0; l < levels.count(); l++ )
4363 for (
int i = 0; i < level.count(); i++ )
4366 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4367 if ( levelIt == features.end() )
4373 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4374 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4376 int llayer = item.
layer();
4377 QList<QgsFeature> &featureList = levelIt.value();
4378 QList<QgsFeature>::iterator featureIt = featureList.begin();
4379 for ( ; featureIt != featureList.end(); ++featureIt )
4389 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4390 if ( !styleString.isEmpty() )
4392 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4393 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4406 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4423 return 1000 / scale;
4440 return scale / 1000;
4448 mRenderer = createSymbologyRenderer( sourceRenderer );
4454 mRenderer->startRender( mRenderContext, fields );
4457void QgsVectorFileWriter::stopRender()
4464 mRenderer->stopRender( mRenderContext );
4467std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4480 if ( !sourceRenderer )
4485 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4492 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4493 for (
const QString &attr : rendererAttributes )
4498 attList.append( index );
4504QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4507 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4509 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4512 switch ( option->
type )
4519 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4529 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4539 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4546 if ( opt && !opt->
mValue.isEmpty() )
4548 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4559 OGRSFDriverH hDriver =
nullptr;
4563 QString drvName = OGR_Dr_GetName( hDriver );
4565 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4570 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4573 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4577 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4580 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4583 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4586 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4597 const QString &layerNameIn )
4599 OGRSFDriverH hDriver =
nullptr;
4604 QString layerName( layerNameIn );
4605 if ( layerName.isEmpty() )
4606 layerName = QFileInfo( datasetName ).baseName();
4608 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4613 const QString &layerName,
4617 OGRSFDriverH hDriver =
nullptr;
4621 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4627 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4628 const auto constAttributes = attributes;
4629 for (
int idx : constAttributes )
4632 if ( OGR_FD_GetFieldIndex( defn, fld.
name().toUtf8().constData() ) < 0 )
@ FieldComments
Writer can support field comments.
@ FieldAliases
Writer can support field aliases.
DistanceUnit
Units of distance.
QFlags< VectorFileWriterCapability > VectorFileWriterCapabilities
Capabilities supported by a QgsVectorFileWriter object.
RenderUnit
Rendering size units.
@ Millimeters
Millimeters.
WkbType
The WKB type describes the number of dimensions a geometry has.
@ MultiPolygon25D
MultiPolygon25D.
@ GeometryCollectionZ
GeometryCollectionZ.
@ MultiLineString
MultiLineString.
@ MultiPolygonZ
MultiPolygonZ.
FeatureSymbologyExport
Options for exporting features considering their symbology.
@ PerFeature
Keeps the number of features and export symbology per feature.
@ PerSymbolLayer
Exports one feature per symbol layer (considering symbol levels)
@ NoSymbology
Export only data.
@ Reverse
Reverse/inverse transform (from destination to source)
The QgsAbstractDatabaseProviderConnection class provides common functionality for DB based connection...
virtual QgsFieldDomain * fieldDomain(const QString &name) const
Returns the field domain with the specified name from the provider.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
QFlags< WkbFlag > WkbFlags
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
@ FlagExportTrianglesAsPolygons
Triangles should be exported as polygon geometries.
@ FlagExportNanAsDoubleMin
Use -DOUBLE_MAX to represent NaN.
static void registerOgrDrivers()
Register OGR drivers ensuring this only happens once.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Qgis::DistanceUnit mapUnits
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
virtual QString dataSourceUri(bool expandAuthConfig=false) const
Gets the data source specification.
Class for storing the component parts of a RDBMS data source URI (e.g.
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
void setFeature(const QgsFeature &feature)
Convenience function for setting a feature for the context.
Wrapper for iterator of features from vector data provider or vector layer.
bool nextFeature(QgsFeature &f)
Fetch next feature and stores in f, returns true on success.
Abstract base class for all 2D vector feature renderers.
virtual QgsSymbolList symbolsForFeature(const QgsFeature &feature, QgsRenderContext &context) const
Returns list of symbols used for rendering the feature.
virtual QgsSymbolList symbols(QgsRenderContext &context) const
Returns list of symbols used by the renderer.
bool usingSymbolLevels() const
virtual QgsFeatureRenderer::Capabilities capabilities()
Returns details about internals of this renderer.
virtual QSet< QString > usedAttributes(const QgsRenderContext &context) const =0
Returns a list of attributes required by this renderer.
@ SymbolLevels
Rendering with symbol levels (i.e. implements symbols(), symbolForFeature())
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
This class wraps a request for features to a vector layer (or directly its vector data provider).
QgsFeatureRequest & setFilterFids(const QgsFeatureIds &fids)
Sets the feature IDs that should be fetched.
QgsFeatureRequest & setSubsetOfAttributes(const QgsAttributeList &attrs)
Set a subset of attributes that will be fetched.
QgsFeatureRequest & setNoAttributes()
Set that no attributes will be fetched.
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken.
QFlags< SinkFlag > SinkFlags
@ RegeneratePrimaryKey
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
void initAttributes(int fieldCount)
Initialize this feature with the given number of fields.
bool hasGeometry() const
Returns true if the feature has an associated geometry.
bool isUnsetValue(int fieldIdx) const
Returns true if the attribute at the specified index is an unset value.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry.
bool isCanceled() const
Tells whether the operation has been canceled already.
void setProgress(double progress)
Sets the current progress for the feedback object.
QString domainName() const
Returns the associated field domain name, for providers which support field domains.
@ ConstraintNotNull
Field may not be null.
@ ConstraintUnique
Field must have a unique value.
Encapsulate a field in an attribute table or data source.
QString typeName() const
Gets the field type.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
void setName(const QString &name)
Set the field name.
QMetaType::Type subType() const
If the field is a collection, gets its element's type.
QgsFieldConstraints constraints
Container of fields for a vector layer.
int size() const
Returns number of items.
void clear()
Removes all fields.
QgsField at(int i) const
Returns the field at particular index (must be in range 0..N-1).
Q_INVOKABLE int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
static QStringList multiLayerFileExtensions()
Returns a list of file extensions which potentially contain multiple layers representing GDAL raster ...
A geometry is the spatial representation of a feature.
static QgsGeometry fromRect(const QgsRectangle &rect)
Creates a new geometry from a QgsRectangle.
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
bool convertToMultiType()
Converts single type geometry into multitype geometry e.g.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static void warning(const QString &msg)
Goes to qWarning.
static QgsAbstractDatabaseProviderConnection * databaseConnection(const QgsMapLayer *layer)
Creates and returns the (possibly nullptr) database connection for a layer.
QString providerType() const
Returns the provider type (provider key) for this layer.
QgsCoordinateReferenceSystem crs
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
static OGRSpatialReferenceH crsToOGRSpatialReference(const QgsCoordinateReferenceSystem &crs)
Returns a OGRSpatialReferenceH corresponding to the specified crs object.
static std::unique_ptr< QgsFieldDomain > convertFieldDomain(OGRFieldDomainH domain)
Converts an OGR field domain definition to a QgsFieldDomain equivalent.
static int OGRTZFlagFromQt(const QDateTime &datetime)
Gets the value of OGRField::Date::TZFlag from the timezone of a QDateTime.
QVariantMap decodeUri(const QString &providerKey, const QString &uri)
Breaks a provider data source URI into its component paths (e.g.
static QgsProviderRegistry * instance(const QString &pluginPath=QString())
Means of accessing canonical single instance.
QString encodeUri(const QString &providerKey, const QVariantMap &parts)
Reassembles a provider data source URI from its component paths (e.g.
bool saveLayerMetadata(const QString &providerKey, const QString &uri, const QgsLayerMetadata &metadata, QString &errorMessage)
Saves metadata to the layer corresponding to the specified uri.
The QgsReadWriteLocker class is a convenience class that simplifies locking and unlocking QReadWriteL...
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
bool isNull() const
Test if the rectangle is null (holding no spatial information).
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
int renderingPass() const
Specifies the rendering pass in which this symbol layer should be rendered.
int layer() const
The layer of this symbol level.
QgsSymbol * symbol() const
The symbol of this symbol level.
Abstract base class for all rendered symbols.
QgsSymbolLayer * symbolLayer(int layer)
Returns the symbol layer at the specified index.
int symbolLayerCount() const
Returns the total number of symbol layers contained in the symbol.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
Interface to convert raw field values to their user-friendly value.
virtual QVariant convert(int fieldIdxInLayer, const QVariant &value)
Convert the provided value, for field fieldIdxInLayer.
virtual QgsVectorFileWriter::FieldValueConverter * clone() const
Creates a clone of the FieldValueConverter.
virtual QgsField fieldDefinition(const QgsField &field)
Returns a possibly modified field definition.
QgsVectorFileWriter::OptionType type
Options to pass to writeAsVectorFormat()
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multi* geometries.
FieldNameSource fieldNameSource
Source for exported field names.
QString driverName
OGR driver to use.
QgsCoordinateTransform ct
Transform to reproject exported geometries with, or invalid transform for no transformation.
QStringList attributesExportNames
Attributes export names.
QgsLayerMetadata layerMetadata
Layer metadata to save for the exported vector file.
QString layerName
Layer name. If let empty, it will be derived from the filename.
QgsRectangle filterExtent
If not empty, only features intersecting the extent will be saved.
bool includeConstraints
Set to true to transfer field constraints to the exported vector file.
const QgsAbstractDatabaseProviderConnection * sourceDatabaseProviderConnection
Source database provider connection, for field domains.
QgsVectorFileWriter::FieldValueConverter * fieldValueConverter
Field value converter.
QStringList layerOptions
List of OGR layer creation options.
Qgis::WkbType overrideGeometryType
Set to a valid geometry type to override the default geometry type for the layer.
bool includeZ
Sets to true to include z dimension in output. This option is only valid if overrideGeometryType is s...
Qgis::FeatureSymbologyExport symbologyExport
Symbology to export.
bool saveMetadata
Set to true to save layer metadata for the exported vector file.
QgsVectorFileWriter::ActionOnExistingFile actionOnExistingFile
Action on existing file.
QgsAttributeList attributes
Attributes to export (empty means all unless skipAttributeCreation is set)
bool onlySelectedFeatures
Write only selected features of layer.
bool skipAttributeCreation
Only write geometries.
bool setFieldDomains
Set to true to transfer field domains to the exported vector file.
double symbologyScale
Scale of symbology.
QStringList datasourceOptions
List of OGR data source creation options.
QgsFeedback * feedback
Optional feedback object allowing cancellation of layer save.
A convenience class for writing vector layers to disk based formats (e.g.
static QgsVectorFileWriter::WriterError writeAsVectorFormatV3(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *errorMessage=nullptr, QString *newFilename=nullptr, QString *newLayer=nullptr)
Writes a layer out to a vector file.
Qgis::FeatureSymbologyExport mSymbologyExport
QString lastError() const override
Returns the most recent error encountered by the sink, e.g.
@ CanAddNewFieldsToExistingLayer
Flag to indicate that new fields can be added to an existing layer. Imply CanAppendToExistingLayer.
@ CanAppendToExistingLayer
Flag to indicate that new features can be added to an existing layer.
@ CanAddNewLayer
Flag to indicate that a new layer can be added to the dataset.
@ CanDeleteLayer
Flag to indicate that an existing layer can be deleted.
static QgsVectorFileWriter::EditionCapabilities editionCapabilities(const QString &datasetName)
Returns edition capabilities for an existing dataset name.
bool addFeature(QgsFeature &feature, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a single feature to the sink.
static bool supportsFeatureStyles(const QString &driverName)
Returns true if the specified driverName supports feature styles.
Qgis::WkbType mWkbType
Geometry type which is being used.
bool addFeatures(QgsFeatureList &features, QgsFeatureSink::Flags flags=QgsFeatureSink::Flags()) override
Adds a list of features to the sink.
double mSymbologyScale
Scale for symbology export (e.g. for symbols units in map units)
QMap< int, int > mAttrIdxToOgrIdx
Map attribute indizes to OGR field indexes.
@ ErrAttributeTypeUnsupported
@ Canceled
Writing was interrupted by manual cancellation.
@ ErrAttributeCreationFailed
@ ErrSavingMetadata
Metadata saving failed.
gdal::ogr_datasource_unique_ptr mDS
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormatV2(QgsVectorLayer *layer, const QString &fileName, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QString *newFilename=nullptr, QString *newLayer=nullptr, QString *errorMessage=nullptr)
Writes a layer out to a vector file.
OGRGeometryH createEmptyGeometry(Qgis::WkbType wkbType)
QString mOgrDriverLongName
QFlags< EditionCapability > EditionCapabilities
Combination of CanAddNewLayer, CanAppendToExistingLayer, CanAddNewFieldsToExistingLayer or CanDeleteL...
~QgsVectorFileWriter() override
Close opened shapefile for writing.
static bool targetLayerExists(const QString &datasetName, const QString &layerName)
Returns whether the target layer already exists.
double symbologyScale() const
Returns the reference scale for output.
static QStringList defaultLayerOptions(const QString &driverName)
Returns a list of the default layer options for a specified driver.
static QString driverForExtension(const QString &extension)
Returns the OGR driver name for a specified file extension.
Qgis::VectorFileWriterCapabilities capabilities() const
Returns the capabilities supported by the writer.
static QList< QgsVectorFileWriter::FilterFormatDetails > supportedFiltersAndFormats(VectorFormatOptions options=SortRecommended)
Returns a list or pairs, with format filter string as first element and OGR format key as second elem...
OGRSpatialReferenceH mOgrRef
static bool driverMetadata(const QString &driverName, MetaData &driverMetadata)
static QgsVectorFileWriter * create(const QString &fileName, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs, const QgsCoordinateTransformContext &transformContext, const QgsVectorFileWriter::SaveVectorOptions &options, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newFilename=nullptr, QString *newLayer=nullptr)
Create a new vector file writer.
QString driver() const
Returns the GDAL (short) driver name associated with the output file.
static bool deleteShapeFile(const QString &fileName)
Delete a shapefile (and its accompanying shx / dbf / prj / qix / qpj / cpg / sbn / sbx / idm / ind)
Q_DECL_DEPRECATED QgsVectorFileWriter(const QString &vectorFileName, const QString &fileEncoding, const QgsFields &fields, Qgis::WkbType geometryType, const QgsCoordinateReferenceSystem &srs=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, QgsFeatureSink::SinkFlags sinkFlags=QgsFeatureSink::SinkFlags(), QString *newLayer=nullptr, const QgsCoordinateTransformContext &transformContext=QgsCoordinateTransformContext(), FieldNameSource fieldNameSource=Original)
Create a new vector file writer.
static Q_DECL_DEPRECATED QgsVectorFileWriter::WriterError writeAsVectorFormat(QgsVectorLayer *layer, const QString &fileName, const QString &fileEncoding, const QgsCoordinateReferenceSystem &destCRS=QgsCoordinateReferenceSystem(), const QString &driverName="GPKG", bool onlySelected=false, QString *errorMessage=nullptr, const QStringList &datasourceOptions=QStringList(), const QStringList &layerOptions=QStringList(), bool skipAttributeCreation=false, QString *newFilename=nullptr, Qgis::FeatureSymbologyExport symbologyExport=Qgis::FeatureSymbologyExport::NoSymbology, double symbologyScale=1.0, const QgsRectangle *filterExtent=nullptr, Qgis::WkbType overrideGeometryType=Qgis::WkbType::Unknown, bool forceMulti=false, bool includeZ=false, const QgsAttributeList &attributes=QgsAttributeList(), QgsVectorFileWriter::FieldValueConverter *fieldValueConverter=nullptr, QString *newLayer=nullptr)
Write contents of vector layer to an (OGR supported) vector format.
static QString filterForDriver(const QString &driverName)
Creates a filter for an OGR driver key.
QgsVectorFileWriter::WriterError hasError() const
Checks whether there were any errors in constructor.
@ SupportsMultipleLayers
Filter to only formats which support multiple layers.
@ SkipNonSpatialFormats
Filter out any formats which do not have spatial support (e.g. those which cannot save geometries)
static bool areThereNewFieldsToCreate(const QString &datasetName, const QString &layerName, QgsVectorLayer *layer, const QgsAttributeList &attributes)
Returns whether there are among the attributes specified some that do not exist yet in the layer.
static QList< QgsVectorFileWriter::DriverDetails > ogrDriverList(VectorFormatOptions options=SortRecommended)
Returns the driver list that can be used for dialogs.
QString driverLongName() const
Returns the GDAL long driver name associated with the output file.
QFlags< VectorFormatOption > VectorFormatOptions
WriterError mError
Contains error value if construction was not successful.
Qgis::FeatureSymbologyExport symbologyExport() const
Returns the feature symbology export handling for the writer.
FieldNameSource
Source for exported field names.
@ PreferAlias
Use the field alias as the exported field name, wherever one is set. Otherwise use the original field...
@ Original
Use original field names.
bool mIncludeConstraints
Whether to transfer field constraints to output.
static QStringList defaultDatasetOptions(const QString &driverName)
Returns a list of the default dataset options for a specified driver.
bool addFeatureWithStyle(QgsFeature &feature, QgsFeatureRenderer *renderer, Qgis::DistanceUnit outputUnit=Qgis::DistanceUnit::Meters)
Adds a feature to the currently opened data source, using the style from a specified renderer.
static QStringList supportedFormatExtensions(VectorFormatOptions options=SortRecommended)
Returns a list of file extensions for supported formats, e.g "shp", "gpkg".
bool mSetFieldDomains
Whether to set field domains to output.
static QString convertCodecNameForEncodingOption(const QString &codecName)
Converts codec name to string passed to ENCODING layer creation option of OGR Shapefile.
FieldValueConverter * mFieldValueConverter
Field value converter.
QString errorMessage() const
Retrieves error message.
void setSymbologyScale(double scale)
Set reference scale for output.
static OGRwkbGeometryType ogrTypeFromWkbType(Qgis::WkbType type)
Gets the ogr geometry type from an internal QGIS wkb type enum.
QMap< QgsSymbolLayer *, QString > mSymbolLayerTable
static QString fileFilterString(VectorFormatOptions options=SortRecommended)
Returns filter string that can be used for dialogs.
ActionOnExistingFile
Enumeration to describe how to handle existing files.
@ CreateOrOverwriteLayer
Create or overwrite layer.
@ CreateOrOverwriteFile
Create or overwrite file.
@ AppendToLayerNoNewFields
Append features to existing layer, but do not create new fields.
@ AppendToLayerAddFields
Append features to existing layer, and create new fields if needed.
Represents a vector layer which manages a vector based data sets.
long long featureCount(const QString &legendKey) const
Number of features rendered with specified legend key.
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
int selectedFeatureCount() const
Returns the number of features that are selected in this layer.
Q_INVOKABLE const QgsFeatureIds & selectedFeatureIds() const
Returns a list of the selected features IDs in this layer.
QString storageType() const
Returns the permanent storage type for this layer as a friendly name.
Q_INVOKABLE Qgis::WkbType wkbType() const FINAL
Returns the WKBType or WKBUnknown in case of error.
QgsFeatureRenderer * renderer()
Returns the feature renderer used for rendering the features in the layer in 2D map views.
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
static Qgis::WkbType to25D(Qgis::WkbType type)
Will convert the 25D version of the flat type if supported or Unknown if not supported.
static bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
static Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType multiType(Qgis::WkbType type)
Returns the multi type for a WKB type.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
std::unique_ptr< std::remove_pointer< OGRFeatureH >::type, OGRFeatureDeleter > ogr_feature_unique_ptr
Scoped OGR feature.
std::unique_ptr< std::remove_pointer< OGRDataSourceH >::type, OGRDataSourceDeleter > ogr_datasource_unique_ptr
Scoped OGR data source.
std::unique_ptr< std::remove_pointer< OGRFieldDefnH >::type, OGRFldDeleter > ogr_field_def_unique_ptr
Scoped OGR field definition.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
QList< QgsFeature > QgsFeatureList
QList< int > QgsAttributeList
#define QgsDebugMsgLevel(str, level)
#define QgsDebugError(str)
QList< QgsSymbolLevel > QgsSymbolLevelOrder
QList< QgsSymbolLevelItem > QgsSymbolLevel
QList< QgsSymbol * > QgsSymbolList
QStringList multiLayerFormats()
Details of available driver formats.
QString longName
Descriptive, user friendly name for the driver.
QString driverName
Unique driver name.