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.glob.split(
' ', Qt::SkipEmptyParts );
289 const auto constAllExts = allExts;
290 for (
const QString &ext : constAllExts )
293 if ( vectorFileName.endsWith( ext.mid( 1 ), Qt::CaseInsensitive ) )
302 allExts = metadata.ext.split(
' ', Qt::SkipEmptyParts );
303 vectorFileName +=
'.' + allExts[0];
309 if ( vectorFileName.endsWith( QLatin1String(
".gdb" ), Qt::CaseInsensitive ) )
311 QDir dir( vectorFileName );
314 QFileInfoList fileList = dir.entryInfoList(
315 QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst );
316 const auto constFileList = fileList;
317 for (
const QFileInfo &info : constFileList )
319 QFile::remove( info.absoluteFilePath() );
322 QDir().rmdir( vectorFileName );
326 QFile::remove( vectorFileName );
331 if ( metadataFound && !metadata.compulsoryEncoding.isEmpty() )
333 if ( fileEncoding.compare( metadata.compulsoryEncoding, Qt::CaseInsensitive ) != 0 )
335 QgsDebugMsgLevel( QStringLiteral(
"forced %1 encoding for %2" ).arg( metadata.compulsoryEncoding, driverName ), 2 );
336 fileEncoding = metadata.compulsoryEncoding;
341 char **options =
nullptr;
342 if ( !datasourceOptions.isEmpty() )
344 options =
new char *[ datasourceOptions.size() + 1 ];
345 for (
int i = 0; i < datasourceOptions.size(); i++ )
347 QgsDebugMsgLevel( QStringLiteral(
"-dsco=%1" ).arg( datasourceOptions[i] ), 2 );
348 options[i] = CPLStrdup( datasourceOptions[i].toUtf8().constData() );
350 options[ datasourceOptions.size()] =
nullptr;
357 mDS.reset( OGR_Dr_CreateDataSource( poDriver, vectorFileName.toUtf8().constData(), options ) );
359 mDS.reset( OGROpen( vectorFileName.toUtf8().constData(), TRUE,
nullptr ) );
363 for (
int i = 0; i < datasourceOptions.size(); i++ )
364 CPLFree( options[i] );
373 mErrorMessage = QObject::tr(
"Creation of data source failed (OGR error: %1)" )
374 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
376 mErrorMessage = QObject::tr(
"Opening of data source in update mode failed (OGR error: %1)" )
377 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
381 QString layerName( layerNameIn );
382 if ( layerName.isEmpty() )
383 layerName = QFileInfo( vectorFileName ).baseName();
387 const int layer_count = OGR_DS_GetLayerCount(
mDS.get() );
388 for (
int i = 0; i < layer_count; i++ )
390 OGRLayerH hLayer = OGR_DS_GetLayer(
mDS.get(), i );
391 if ( EQUAL( OGR_L_GetName( hLayer ), layerName.toUtf8().constData() ) )
393 if ( OGR_DS_DeleteLayer(
mDS.get(), i ) != OGRERR_NONE )
396 mErrorMessage = QObject::tr(
"Overwriting of existing layer failed (OGR error: %1)" )
397 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
411 QgsDebugMsgLevel( QStringLiteral(
"Opened data source in update mode" ), 2 );
415 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().constData() );
418 QgsDebugError(
"error finding QTextCodec for " + fileEncoding );
421 QString enc = settings.
value( QStringLiteral(
"UI/encoding" ),
"System" ).toString();
422 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().constData() );
426 mCodec = QTextCodec::codecForLocale();
432 if ( driverName == QLatin1String(
"KML" ) || driverName == QLatin1String(
"LIBKML" ) || driverName == QLatin1String(
"GPX" ) )
434 if ( srs.
authid() != QLatin1String(
"EPSG:4326" ) )
449 int optIndex = layerOptions.indexOf( QLatin1String(
"FEATURE_DATASET=" ) );
450 if ( optIndex != -1 )
452 layerOptions.removeAt( optIndex );
455 if ( !layerOptions.isEmpty() )
457 options =
new char *[ layerOptions.size() + 1 ];
458 for (
int i = 0; i < layerOptions.size(); i++ )
461 options[i] = CPLStrdup( layerOptions[i].toUtf8().constData() );
463 options[ layerOptions.size()] =
nullptr;
467 CPLSetConfigOption(
"SHAPE_ENCODING",
"" );
471 mLayer = OGR_DS_CreateLayer(
mDS.get(), layerName.toUtf8().constData(),
mOgrRef, wkbType, options );
474 *newLayer = OGR_L_GetName(
mLayer );
475 if ( driverName == QLatin1String(
"GPX" ) )
482 if ( !EQUAL( layerName.toUtf8().constData(),
"track_points" ) &&
483 !EQUAL( layerName.toUtf8().constData(),
"route_points" ) )
485 *newLayer = QStringLiteral(
"waypoints" );
492 const char *pszForceGPXTrack
493 = CSLFetchNameValue( options,
"FORCE_GPX_TRACK" );
494 if ( pszForceGPXTrack && CPLTestBool( pszForceGPXTrack ) )
495 *newLayer = QStringLiteral(
"tracks" );
497 *newLayer = QStringLiteral(
"routes" );
504 const char *pszForceGPXRoute
505 = CSLFetchNameValue( options,
"FORCE_GPX_ROUTE" );
506 if ( pszForceGPXRoute && CPLTestBool( pszForceGPXRoute ) )
507 *newLayer = QStringLiteral(
"routes" );
509 *newLayer = QStringLiteral(
"tracks" );
519 else if ( driverName == QLatin1String(
"DGN" ) )
521 mLayer = OGR_DS_GetLayerByName(
mDS.get(),
"elements" );
525 mLayer = OGR_DS_GetLayerByName(
mDS.get(), layerName.toUtf8().constData() );
530 for (
int i = 0; i < layerOptions.size(); i++ )
531 CPLFree( options[i] );
540 QString layerName = vectorFileName.left( vectorFileName.indexOf( QLatin1String(
".shp" ), Qt::CaseInsensitive ) );
541 QFile prjFile( layerName +
".qpj" );
542 if ( prjFile.exists() )
550 mErrorMessage = QObject::tr(
"Creation of layer failed (OGR error: %1)" )
551 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
553 mErrorMessage = QObject::tr(
"Opening of layer failed (OGR error: %1)" )
554 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
559 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
568 QSet<int> existingIdxs;
572#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
573 if (
const char *pszCreateFieldDefnFlags = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
nullptr ) )
575 char **papszTokens = CSLTokenizeString2( pszCreateFieldDefnFlags,
" ", 0 );
576 if ( CSLFindString( papszTokens,
"AlternativeName" ) >= 0 )
580 if ( CSLFindString( papszTokens,
"Comment" ) >= 0 )
584 CSLDestroy( papszTokens );
594#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0)
595 QSet<QString> existingDestDomainNames;
596 if ( sourceDatabaseProviderConnection )
598 char **domainNames = GDALDatasetGetFieldDomainNames(
mDS.get(),
nullptr );
599 for (
const char *
const *iterDomainNames = domainNames; iterDomainNames && *iterDomainNames; ++iterDomainNames )
601 existingDestDomainNames.insert( QString::fromUtf8( *iterDomainNames ) );
603 CSLDestroy( domainNames );
606#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
607 QSet< QString > usedAlternativeNames;
610 const QString ogrFidColumnName { OGR_L_GetFIDColumn(
mLayer ) };
611 const int fidNameIndex = OGR_FD_GetFieldIndex( defn, ogrFidColumnName.toUtf8() );
614 const bool promoteFidColumnToAttribute = !ogrFidColumnName.isEmpty() && fidNameIndex < 0 && fields.
lookupField( ogrFidColumnName ) >= 0;
615 int offsetRoomForFid = promoteFidColumnToAttribute ? 1 : 0;
617 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
621 if ( fieldValueConverter )
623 attrField = fieldValueConverter->fieldDefinition( fields.
at( fldIdx ) );
628 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
637 switch ( fieldNameSource )
640 name = attrField.
name();
644 name = !attrField.
alias().isEmpty() ? attrField.
alias() : attrField.
name();
648 OGRFieldType ogrType = OFTString;
649 OGRFieldSubType ogrSubType = OFSTNone;
650 int ogrWidth = attrField.
length();
651 int ogrPrecision = attrField.
precision();
652 if ( ogrPrecision > 0 )
655 switch ( attrField.
type() )
657 case QMetaType::Type::LongLong:
659 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
660 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64" ) )
661 ogrType = OFTInteger64;
664 ogrWidth = ogrWidth > 0 && ogrWidth <= 20 ? ogrWidth : 20;
668 case QMetaType::Type::QString:
670 if ( ( ogrWidth <= 0 || ogrWidth > 255 ) &&
mOgrDriverName == QLatin1String(
"ESRI Shapefile" ) )
674 case QMetaType::Type::Int:
675 ogrType = OFTInteger;
676 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
680 case QMetaType::Type::Bool:
681 ogrType = OFTInteger;
682 ogrSubType = OFSTBoolean;
687 case QMetaType::Type::Double:
688#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,3,1)
689 if (
mOgrDriverName == QLatin1String(
"GPKG" ) && attrField.
precision() == 0 && attrField.
name().compare( fidFieldName, Qt::CaseInsensitive ) == 0 )
692 ogrType = OFTInteger64;
699 case QMetaType::Type::QDate:
703 case QMetaType::Type::QTime:
715 case QMetaType::Type::QDateTime:
723 ogrType = OFTDateTime;
727 case QMetaType::Type::QByteArray:
731 case QMetaType::Type::QStringList:
737 ogrSubType = OFSTJSON;
741 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
742 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
744 ogrType = OFTStringList;
745 mSupportedListSubTypes.insert( QMetaType::Type::QString );
755 case QMetaType::Type::QVariantMap:
758 const char *pszDataSubTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
759 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
762 ogrSubType = OFSTJSON;
770 case QMetaType::Type::QVariantList:
775 ogrSubType = OFSTJSON;
780 if ( attrField.
subType() == QMetaType::Type::QString )
782 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
783 if ( pszDataTypes && strstr( pszDataTypes,
"StringList" ) )
785 ogrType = OFTStringList;
786 mSupportedListSubTypes.insert( QMetaType::Type::QString );
795 else if ( attrField.
subType() == QMetaType::Type::Int )
797 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
798 if ( pszDataTypes && strstr( pszDataTypes,
"IntegerList" ) )
800 ogrType = OFTIntegerList;
801 mSupportedListSubTypes.insert( QMetaType::Type::Int );
810 else if ( attrField.
subType() == QMetaType::Type::Double )
812 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
813 if ( pszDataTypes && strstr( pszDataTypes,
"RealList" ) )
815 ogrType = OFTRealList;
816 mSupportedListSubTypes.insert( QMetaType::Type::Double );
825 else if ( attrField.
subType() == QMetaType::Type::LongLong )
827 const char *pszDataTypes = GDALGetMetadataItem( poDriver, GDAL_DMD_CREATIONFIELDDATATYPES,
nullptr );
828 if ( pszDataTypes && strstr( pszDataTypes,
"Integer64List" ) )
830 ogrType = OFTInteger64List;
831 mSupportedListSubTypes.insert( QMetaType::Type::LongLong );
845 mErrorMessage = QObject::tr(
"Unsupported type for field %1" )
846 .arg( attrField.
name() );
851 if (
mOgrDriverName == QLatin1String(
"SQLite" ) && name.compare( QLatin1String(
"ogc_fid" ), Qt::CaseInsensitive ) == 0 )
854 for ( i = 0; i < 10; i++ )
856 name = QStringLiteral(
"ogc_fid%1" ).arg( i );
859 for ( j = 0; j < fields.
size() && name.compare( fields.
at( j ).
name(), Qt::CaseInsensitive ) != 0; j++ )
862 if ( j == fields.
size() )
868 mErrorMessage = QObject::tr(
"No available replacement for internal fieldname ogc_fid found" ).arg( attrField.
name() );
873 QgsMessageLog::logMessage( QObject::tr(
"Reserved attribute name ogc_fid replaced with %1" ).arg( name ), QObject::tr(
"OGR" ) );
880 OGR_Fld_SetWidth( fld.get(), ogrWidth );
883 if ( ogrPrecision >= 0 )
885 OGR_Fld_SetPrecision( fld.get(), ogrPrecision );
888 if ( ogrSubType != OFSTNone )
889 OGR_Fld_SetSubType( fld.get(), ogrSubType );
891#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)
892 if ( !attrField.
alias().isEmpty() )
894 QString alternativeName = attrField.
alias();
896 while ( usedAlternativeNames.contains( alternativeName ) )
899 alternativeName = attrField.
alias() + QStringLiteral(
" (%1)" ).arg( ++counter );
901 OGR_Fld_SetAlternativeName( fld.get(),
mCodec->fromUnicode( alternativeName ).constData() );
902 usedAlternativeNames.insert( alternativeName );
905#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
906 OGR_Fld_SetComment( fld.get(),
mCodec->fromUnicode( attrField.
comment() ).constData() );
913 OGR_Fld_SetNullable( fld.get(),
false );
917 OGR_Fld_SetUnique( fld.get(),
true );
920#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,5,0)
924 if ( !domainName.isEmpty() )
926 bool canSetFieldDomainName =
false;
927 if ( existingDestDomainNames.contains( domainName ) )
931 canSetFieldDomainName =
true;
933 else if ( GDALDatasetTestCapability(
mDS.get(), ODsCAddFieldDomain ) )
943 std::unique_ptr<QgsFieldDomain> domain( sourceDatabaseProviderConnection->
fieldDomain( domainName ) );
949 char *pszFailureReason =
nullptr;
950 if ( GDALDatasetAddFieldDomain(
mDS.get(), hFieldDomain, &pszFailureReason ) )
952 existingDestDomainNames.insert( domainName );
953 canSetFieldDomainName =
true;
957 QgsDebugError( QStringLiteral(
"cannot create field domain: %1" ).arg( pszFailureReason ) );
959 CPLFree( pszFailureReason );
960 OGR_FldDomain_Destroy( hFieldDomain );
966 QgsDebugError( QStringLiteral(
"Cannot retrieve field domain: %1" ).arg( domainName ) );
969 if ( canSetFieldDomainName )
971 OGR_Fld_SetDomainName( fld.get(), domainName.toUtf8().toStdString().c_str() );
979 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
980 " width " + QString::number( ogrWidth ) +
981 " precision " + QString::number( ogrPrecision ), 2 );
982 if ( OGR_L_CreateField(
mLayer, fld.get(),
true ) != OGRERR_NONE )
985 mErrorMessage = QObject::tr(
"Creation of field %1 (%2) failed (OGR error: %3)" )
986 .arg( attrField.
name(),
987 QVariant::typeToName( attrField.
type() ),
988 QString::fromUtf8( CPLGetLastErrorMsg() ) );
993 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
994 QgsDebugMsgLevel( QStringLiteral(
"returned field index for %1: %2" ).arg( name ).arg( ogrIdx ), 2 );
995 if ( ogrIdx < 0 || existingIdxs.contains( ogrIdx ) )
998 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
1003 mErrorMessage = QObject::tr(
"Created field %1 not found (OGR error: %2)" )
1004 .arg( attrField.
name(),
1005 QString::fromUtf8( CPLGetLastErrorMsg() ) );
1011 if ( promoteFidColumnToAttribute )
1013 if ( ogrFidColumnName.compare( attrField.
name(), Qt::CaseInsensitive ) == 0 )
1016 offsetRoomForFid = 0;
1021 ogrIdx += offsetRoomForFid;
1025 existingIdxs.insert( ogrIdx );
1033 for (
int fldIdx = 0; fldIdx < fields.
count(); ++fldIdx )
1036 QString name( attrField.
name() );
1037 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( name ) );
1049 int fidIdx = fields.
lookupField( QStringLiteral(
"FID" ) );
1060 *newFilename = vectorFileName;
1063 mUsingTransaction =
true;
1064 if ( OGRERR_NONE != OGR_L_StartTransaction(
mLayer ) )
1066 mUsingTransaction =
false;
1076class QgsVectorFileWriterMetadataContainer
1080 QgsVectorFileWriterMetadataContainer()
1082 QMap<QString, QgsVectorFileWriter::Option *> datasetOptions;
1083 QMap<QString, QgsVectorFileWriter::Option *> layerOptions;
1086 datasetOptions.clear();
1087 layerOptions.clear();
1090 QObject::tr(
"Compression method." ),
1092 << QStringLiteral(
"UNCOMPRESSED" )
1093 << QStringLiteral(
"ZSTD" )
1094 << QStringLiteral(
"LZ4" ),
1095 QStringLiteral(
"LZ4" ),
1100 QObject::tr(
"Geometry encoding." ),
1102 << QStringLiteral(
"GEOARROW" )
1103 << QStringLiteral(
"WKB" )
1104 << QStringLiteral(
"WKT" ),
1105 QStringLiteral(
"GEOARROW" ),
1110 QObject::tr(
"Maximum number of rows per batch." ),
1115 QObject::tr(
"Name for the feature identifier column" ),
1120 QObject::tr(
"Name for the geometry column" ),
1121 QStringLiteral(
"geometry" )
1124 driverMetadata.insert( QStringLiteral(
"Arrow" ),
1126 QStringLiteral(
"(Geo)Arrow" ),
1127 QObject::tr(
"(Geo)Arrow" ),
1128 QStringLiteral(
"*.arrow *.feather *.arrows *.ipc" ),
1129 QStringLiteral(
"arrow" ),
1132 QStringLiteral(
"UTF-8" )
1137 datasetOptions.clear();
1138 layerOptions.clear();
1140 driverMetadata.insert( QStringLiteral(
"AVCE00" ),
1142 QStringLiteral(
"Arc/Info ASCII Coverage" ),
1143 QObject::tr(
"Arc/Info ASCII Coverage" ),
1144 QStringLiteral(
"*.e00" ),
1145 QStringLiteral(
"e00" ),
1152 datasetOptions.clear();
1153 layerOptions.clear();
1156 QObject::tr(
"By default when creating new .csv files they "
1157 "are created with the line termination conventions "
1158 "of the local platform (CR/LF on Win32 or LF on all other systems). "
1159 "This may be overridden through the use of the LINEFORMAT option." ),
1161 << QStringLiteral(
"CRLF" )
1162 << QStringLiteral(
"LF" ),
1168 QObject::tr(
"By default, the geometry of a feature written to a .csv file is discarded. "
1169 "It is possible to export the geometry in its WKT representation by "
1170 "specifying GEOMETRY=AS_WKT. It is also possible to export point geometries "
1171 "into their X,Y,Z components by specifying GEOMETRY=AS_XYZ, GEOMETRY=AS_XY "
1172 "or GEOMETRY=AS_YX." ),
1174 << QStringLiteral(
"AS_WKT" )
1175 << QStringLiteral(
"AS_XYZ" )
1176 << QStringLiteral(
"AS_XY" )
1177 << QStringLiteral(
"AS_YX" ),
1183 QObject::tr(
"Name of geometry column. Only used if GEOMETRY=AS_WKT. Defaults to 'WKT'." ),
1184 QStringLiteral(
"WKT" )
1188 QObject::tr(
"Create the associated .csvt file to describe the type of each "
1189 "column of the layer and its optional width and precision. "
1190 "This option also creates a .prj file which stores coordinate system information." ),
1195 QObject::tr(
"Field separator character." ),
1197 << QStringLiteral(
"COMMA" )
1198 << QStringLiteral(
"SEMICOLON" )
1199 << QStringLiteral(
"TAB" )
1200 << QStringLiteral(
"SPACE" )
1201#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,12,0)
1202 << QStringLiteral(
"PIPE" )
1204 , QStringLiteral(
"COMMA" )
1208 QObject::tr(
"Double-quote strings. IF_AMBIGUOUS means that string values that look like numbers will be quoted." ),
1210 << QStringLiteral(
"IF_NEEDED" )
1211 << QStringLiteral(
"IF_AMBIGUOUS" )
1212 << QStringLiteral(
"ALWAYS" ),
1213 QStringLiteral(
"IF_AMBIGUOUS" )
1217 QObject::tr(
"Write a UTF-8 Byte Order Mark (BOM) at the start of the file." ),
1221#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,12,0)
1223 QObject::tr(
"Whether to write a header line with the field names." ),
1228 driverMetadata.insert( QStringLiteral(
"CSV" ),
1230 QStringLiteral(
"Comma Separated Value [CSV]" ),
1231 QObject::tr(
"Comma Separated Value [CSV]" ),
1232 QStringLiteral(
"*.csv" ),
1233 QStringLiteral(
"csv" ),
1240 datasetOptions.clear();
1241 layerOptions.clear();
1243 driverMetadata.insert( QStringLiteral(
"FlatGeobuf" ),
1245 QStringLiteral(
"FlatGeobuf" ),
1246 QObject::tr(
"FlatGeobuf" ),
1247 QStringLiteral(
"*.fgb" ),
1248 QStringLiteral(
"fgb" ),
1251 QStringLiteral(
"UTF-8" )
1256 datasetOptions.clear();
1257 layerOptions.clear();
1260 QObject::tr(
"Override the type of shapefile created. "
1261 "Can be one of NULL for a simple .dbf file with no .shp file, POINT, "
1262 "ARC, POLYGON or MULTIPOINT for 2D, or POINTZ, ARCZ, POLYGONZ or "
1263 "MULTIPOINTZ for 3D;" ) +
1264 QObject::tr(
" POINTM, ARCM, POLYGONM or MULTIPOINTM for measured geometries"
1265 " and POINTZM, ARCZM, POLYGONZM or MULTIPOINTZM for 3D measured"
1267 QObject::tr(
" MULTIPATCH files are supported since GDAL 2.2." ) +
1270 << QStringLiteral(
"NULL" )
1271 << QStringLiteral(
"POINT" )
1272 << QStringLiteral(
"ARC" )
1273 << QStringLiteral(
"POLYGON" )
1274 << QStringLiteral(
"MULTIPOINT" )
1275 << QStringLiteral(
"POINTZ" )
1276 << QStringLiteral(
"ARCZ" )
1277 << QStringLiteral(
"POLYGONZ" )
1278 << QStringLiteral(
"MULTIPOINTZ" )
1279 << QStringLiteral(
"POINTM" )
1280 << QStringLiteral(
"ARCM" )
1281 << QStringLiteral(
"POLYGONM" )
1282 << QStringLiteral(
"MULTIPOINTM" )
1283 << QStringLiteral(
"POINTZM" )
1284 << QStringLiteral(
"ARCZM" )
1285 << QStringLiteral(
"POLYGONZM" )
1286 << QStringLiteral(
"MULTIPOINTZM" )
1287 << QStringLiteral(
"MULTIPATCH" )
1297 QObject::tr(
"Set the encoding value in the DBF file. "
1298 "The default value is LDID/87. It is not clear "
1299 "what other values may be appropriate." ),
1307 QObject::tr(
"Set to YES to resize fields to their optimal size." ),
1311 driverMetadata.insert( QStringLiteral(
"ESRI" ),
1313 QStringLiteral(
"ESRI Shapefile" ),
1314 QObject::tr(
"ESRI Shapefile" ),
1315 QStringLiteral(
"*.shp" ),
1316 QStringLiteral(
"shp" ),
1323 datasetOptions.clear();
1324 layerOptions.clear();
1326 driverMetadata.insert( QStringLiteral(
"DBF File" ),
1328 QStringLiteral(
"DBF File" ),
1329 QObject::tr(
"DBF File" ),
1330 QStringLiteral(
"*.dbf" ),
1331 QStringLiteral(
"dbf" ),
1338 datasetOptions.clear();
1339 layerOptions.clear();
1342 QObject::tr(
"Set to YES to write a bbox property with the bounding box "
1343 "of the geometries at the feature and feature collection level." ),
1348 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1349 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1354 QObject::tr(
"Whether to use RFC 7946 standard. "
1355 "If disabled GeoJSON 2008 initial version will be used. "
1356 "Default is NO (thus GeoJSON 2008). See also Documentation (via Help button)" ),
1360 driverMetadata.insert( QStringLiteral(
"GeoJSON" ),
1362 QStringLiteral(
"GeoJSON" ),
1363 QObject::tr(
"GeoJSON" ),
1364 QStringLiteral(
"*.geojson" ),
1365 QStringLiteral(
"geojson" ),
1368 QStringLiteral(
"UTF-8" )
1373 datasetOptions.clear();
1374 layerOptions.clear();
1377 QObject::tr(
"Maximum number of figures after decimal separator to write in coordinates. "
1378 "Defaults to 15. Truncation will occur to remove trailing zeros." ),
1383 QObject::tr(
"Whether to start records with the RS=0x1E character (RFC 8142 standard). "
1384 "Defaults to NO: Newline Delimited JSON (geojsonl). \n"
1385 "If set to YES: RFC 8142 standard: GeoJSON Text Sequences (geojsons)." ),
1389 driverMetadata.insert( QStringLiteral(
"GeoJSONSeq" ),
1391 QStringLiteral(
"GeoJSON - Newline Delimited" ),
1392 QObject::tr(
"GeoJSON - Newline Delimited" ),
1393 QStringLiteral(
"*.geojsonl *.geojsons *.json" ),
1394 QStringLiteral(
"geojsonl geojsons json" ),
1397 QStringLiteral(
"UTF-8" )
1402 datasetOptions.clear();
1403 layerOptions.clear();
1406 QObject::tr(
"whether the document must be in RSS 2.0 or Atom 1.0 format. "
1407 "Default value : RSS" ),
1409 << QStringLiteral(
"RSS" )
1410 << QStringLiteral(
"ATOM" ),
1411 QStringLiteral(
"RSS" )
1415 QObject::tr(
"The encoding of location information. Default value : SIMPLE. "
1416 "W3C_GEO only supports point geometries. "
1417 "SIMPLE or W3C_GEO only support geometries in geographic WGS84 coordinates." ),
1419 << QStringLiteral(
"SIMPLE" )
1420 << QStringLiteral(
"GML" )
1421 << QStringLiteral(
"W3C_GEO" ),
1422 QStringLiteral(
"SIMPLE" )
1426 QObject::tr(
"If defined to YES, extension fields will be written. "
1427 "If the field name not found in the base schema matches "
1428 "the foo_bar pattern, foo will be considered as the namespace "
1429 "of the element, and a <foo:bar> element will be written. "
1430 "Otherwise, elements will be written in the <ogr:> namespace." ),
1435 QObject::tr(
"If defined to NO, only <entry> or <item> elements will be written. "
1436 "The user will have to provide the appropriate header and footer of the document." ),
1441 QObject::tr(
"XML content that will be put between the <channel> element and the "
1442 "first <item> element for a RSS document, or between the xml tag and "
1443 "the first <entry> element for an Atom document." ),
1448 QObject::tr(
"Value put inside the <title> element in the header. "
1449 "If not provided, a dummy value will be used as that element is compulsory." ),
1454 QObject::tr(
"Value put inside the <description> element in the header. "
1455 "If not provided, a dummy value will be used as that element is compulsory." ),
1460 QObject::tr(
"Value put inside the <link> element in the header. "
1461 "If not provided, a dummy value will be used as that element is compulsory." ),
1466 QObject::tr(
"Value put inside the <updated> element in the header. "
1467 "Should be formatted as a XML datetime. "
1468 "If not provided, a dummy value will be used as that element is compulsory." ),
1473 QObject::tr(
"Value put inside the <author><name> element in the header. "
1474 "If not provided, a dummy value will be used as that element is compulsory." ),
1479 QObject::tr(
"Value put inside the <id> element in the header. "
1480 "If not provided, a dummy value will be used as that element is compulsory." ),
1484 driverMetadata.insert( QStringLiteral(
"GeoRSS" ),
1486 QStringLiteral(
"GeoRSS" ),
1487 QObject::tr(
"GeoRSS" ),
1488 QStringLiteral(
"*.xml" ),
1489 QStringLiteral(
"xml" ),
1492 QStringLiteral(
"UTF-8" )
1497 datasetOptions.clear();
1498 layerOptions.clear();
1501 QObject::tr(
"If provided, this URI will be inserted as the schema location. "
1502 "Note that the schema file isn't actually accessed by OGR, so it "
1503 "is up to the user to ensure it will match the schema of the OGR "
1504 "produced GML data file." ),
1509 QObject::tr(
"This writes a GML application schema file to a corresponding "
1510 ".xsd file (with the same basename). If INTERNAL is used the "
1511 "schema is written within the GML file, but this is experimental "
1512 "and almost certainly not valid XML. "
1513 "OFF disables schema generation (and is implicit if XSISCHEMAURI is used)." ),
1515 << QStringLiteral(
"EXTERNAL" )
1516 << QStringLiteral(
"INTERNAL" )
1517 << QStringLiteral(
"OFF" ),
1518 QStringLiteral(
"EXTERNAL" )
1522 QObject::tr(
"This is the prefix for the application target namespace." ),
1523 QStringLiteral(
"ogr" )
1527 QObject::tr(
"Can be set to TRUE to avoid writing the prefix of the "
1528 "application target namespace in the GML file." ),
1533 QObject::tr(
"Defaults to 'http://ogr.maptools.org/'. "
1534 "This is the application target namespace." ),
1535 QStringLiteral(
"http://ogr.maptools.org/" )
1539 QObject::tr(
"GML version to use." ),
1541 << QStringLiteral(
"GML2" )
1542 << QStringLiteral(
"GML3" )
1543 << QStringLiteral(
"GML3Deegree" )
1544 << QStringLiteral(
"GML3.2" ),
1545 QStringLiteral(
"GML3.2" )
1549 QObject::tr(
"Only valid when FORMAT=GML3/GML3Degree/GML3.2. Default to YES. "
1550 "If YES, SRS with EPSG authority will be written with the "
1551 "'urn:ogc:def:crs:EPSG::' prefix. In the case the SRS is a "
1552 "geographic SRS without explicit AXIS order, but that the same "
1553 "SRS authority code imported with ImportFromEPSGA() should be "
1554 "treated as lat/long, then the function will take care of coordinate "
1555 "order swapping. If set to NO, SRS with EPSG authority will be "
1556 "written with the 'EPSG:' prefix, even if they are in lat/long order." ),
1561 QObject::tr(
"only valid when FORMAT=GML3/GML3Degree/GML3.2) Default to YES. "
1562 "If set to NO, the <gml:boundedBy> element will not be written for "
1568 QObject::tr(
"Default to YES. If YES, the output will be indented with spaces "
1569 "for more readability, but at the expense of file size." ),
1574 driverMetadata.insert( QStringLiteral(
"GML" ),
1576 QStringLiteral(
"Geography Markup Language [GML]" ),
1577 QObject::tr(
"Geography Markup Language [GML]" ),
1578 QStringLiteral(
"*.gml" ),
1579 QStringLiteral(
"gml" ),
1582 QStringLiteral(
"UTF-8" )
1587 datasetOptions.clear();
1588 layerOptions.clear();
1591 QObject::tr(
"Human-readable identifier (e.g. short name) for the layer content" ),
1596 QObject::tr(
"Human-readable description for the layer content" ),
1601 QObject::tr(
"Name for the feature identifier column" ),
1602 QStringLiteral(
"fid" )
1606 QObject::tr(
"Name for the geometry column" ),
1607 QStringLiteral(
"geom" )
1611 QObject::tr(
"If a spatial index must be created." ),
1615 driverMetadata.insert( QStringLiteral(
"GPKG" ),
1617 QStringLiteral(
"GeoPackage" ),
1618 QObject::tr(
"GeoPackage" ),
1619#
if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,7,0)
1620 QStringLiteral(
"*.gpkg *.gpkg.zip" ),
1622 QStringLiteral(
"*.gpkg" ),
1624 QStringLiteral(
"gpkg" ),
1627 QStringLiteral(
"UTF-8" )
1632 datasetOptions.clear();
1633 layerOptions.clear();
1635 driverMetadata.insert( QStringLiteral(
"GMT" ),
1637 QStringLiteral(
"Generic Mapping Tools [GMT]" ),
1638 QObject::tr(
"Generic Mapping Tools [GMT]" ),
1639 QStringLiteral(
"*.gmt" ),
1640 QStringLiteral(
"gmt" ),
1647 datasetOptions.clear();
1648 layerOptions.clear();
1651 QObject::tr(
"By default when writing a layer whose features are of "
1652 "type wkbLineString, the GPX driver chooses to write "
1653 "them as routes. If FORCE_GPX_TRACK=YES is specified, "
1654 "they will be written as tracks." ),
1659 QObject::tr(
"By default when writing a layer whose features are of "
1660 "type wkbMultiLineString, the GPX driver chooses to write "
1661 "them as tracks. If FORCE_GPX_ROUTE=YES is specified, "
1662 "they will be written as routes, provided that the multilines "
1663 "are composed of only one single line." ),
1668 QObject::tr(
"If GPX_USE_EXTENSIONS=YES is specified, "
1669 "extra fields will be written inside the <extensions> tag." ),
1674 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS_URL "
1675 "is set. The namespace value used for extension tags. By default, 'ogr'." ),
1676 QStringLiteral(
"ogr" )
1680 QObject::tr(
"Only used if GPX_USE_EXTENSIONS=YES and GPX_EXTENSIONS_NS "
1681 "is set. The namespace URI. By default, 'http://osgeo.org/gdal'." ),
1682 QStringLiteral(
"http://osgeo.org/gdal" )
1686 QObject::tr(
"By default files are created with the line termination "
1687 "conventions of the local platform (CR/LF on win32 or LF "
1688 "on all other systems). This may be overridden through use "
1689 "of the LINEFORMAT layer creation option which may have a value "
1690 "of CRLF (DOS format) or LF (Unix format)." ),
1692 << QStringLiteral(
"CRLF" )
1693 << QStringLiteral(
"LF" ),
1698 driverMetadata.insert( QStringLiteral(
"GPX" ),
1700 QStringLiteral(
"GPS eXchange Format [GPX]" ),
1701 QObject::tr(
"GPS eXchange Format [GPX]" ),
1702 QStringLiteral(
"*.gpx" ),
1703 QStringLiteral(
"gpx" ),
1706 QStringLiteral(
"UTF-8" )
1711 datasetOptions.clear();
1712 layerOptions.clear();
1714 driverMetadata.insert( QStringLiteral(
"Interlis 1" ),
1716 QStringLiteral(
"INTERLIS 1" ),
1717 QObject::tr(
"INTERLIS 1" ),
1718 QStringLiteral(
"*.itf *.xml *.ili" ),
1719 QStringLiteral(
"ili" ),
1726 datasetOptions.clear();
1727 layerOptions.clear();
1729 driverMetadata.insert( QStringLiteral(
"Interlis 2" ),
1731 QStringLiteral(
"INTERLIS 2" ),
1732 QObject::tr(
"INTERLIS 2" ),
1733 QStringLiteral(
"*.xtf *.xml *.ili" ),
1734 QStringLiteral(
"ili" ),
1741 datasetOptions.clear();
1742 layerOptions.clear();
1745 QObject::tr(
"Allows you to specify the field to use for the KML <name> element." ),
1746 QStringLiteral(
"Name" )
1750 QObject::tr(
"Allows you to specify the field to use for the KML <description> element." ),
1751 QStringLiteral(
"Description" )
1755 QObject::tr(
"Allows you to specify the AltitudeMode to use for KML geometries. "
1756 "This will only affect 3D geometries and must be one of the valid KML options." ),
1758 << QStringLiteral(
"clampToGround" )
1759 << QStringLiteral(
"relativeToGround" )
1760 << QStringLiteral(
"absolute" ),
1761 QStringLiteral(
"relativeToGround" )
1765 QObject::tr(
"The DOCUMENT_ID datasource creation option can be used to specified "
1766 "the id of the root <Document> node. The default value is root_doc." ),
1767 QStringLiteral(
"root_doc" )
1770 driverMetadata.insert( QStringLiteral(
"KML" ),
1772 QStringLiteral(
"Keyhole Markup Language [KML]" ),
1773 QObject::tr(
"Keyhole Markup Language [KML]" ),
1774 QStringLiteral(
"*.kml" ),
1775 QStringLiteral(
"kml" ),
1778 QStringLiteral(
"UTF-8" )
1783 datasetOptions.clear();
1784 layerOptions.clear();
1786 auto insertMapInfoOptions = []( QMap<QString, QgsVectorFileWriter::Option *> &datasetOptions, QMap<QString, QgsVectorFileWriter::Option *> &layerOptions )
1789 QObject::tr(
"Use this to turn on 'quick spatial index mode'. "
1790 "In this mode writing files can be about 5 times faster, "
1791 "but spatial queries can be up to 30 times slower." ),
1793 << QStringLiteral(
"QUICK" )
1794 << QStringLiteral(
"OPTIMIZED" ),
1795 QStringLiteral(
"QUICK" ),
1800 QObject::tr(
"(multiples of 512): Block size for .map files. Defaults "
1801 "to 512. MapInfo 15.2 and above creates .tab files with a "
1802 "blocksize of 16384 bytes. Any MapInfo version should be "
1803 "able to handle block sizes from 512 to 32256." ),
1807 QObject::tr(
"xmin,ymin,xmax,ymax: Define custom layer bounds to increase the "
1808 "accuracy of the coordinates. Note: the geometry of written "
1809 "features must be within the defined box." ),
1813 insertMapInfoOptions( datasetOptions, layerOptions );
1815 driverMetadata.insert( QStringLiteral(
"MapInfo File" ),
1817 QStringLiteral(
"Mapinfo" ),
1818 QObject::tr(
"Mapinfo TAB" ),
1819 QStringLiteral(
"*.tab" ),
1820 QStringLiteral(
"tab" ),
1825 datasetOptions.clear();
1826 layerOptions.clear();
1827 insertMapInfoOptions( datasetOptions, layerOptions );
1830 driverMetadata.insert( QStringLiteral(
"MapInfo MIF" ),
1832 QStringLiteral(
"Mapinfo" ),
1833 QObject::tr(
"Mapinfo MIF" ),
1834 QStringLiteral(
"*.mif" ),
1835 QStringLiteral(
"mif" ),
1842 datasetOptions.clear();
1843 layerOptions.clear();
1846 QObject::tr(
"Determine whether 2D (seed_2d.dgn) or 3D (seed_3d.dgn) "
1847 "seed file should be used. This option is ignored if the SEED option is provided." ),
1852 QObject::tr(
"Override the seed file to use." ),
1857 QObject::tr(
"Indicate whether the whole seed file should be copied. "
1858 "If not, only the first three elements will be copied." ),
1863 QObject::tr(
"Indicates whether the color table should be copied from the seed file." ),
1868 QObject::tr(
"Override the master unit name from the seed file with "
1869 "the provided one or two character unit name." ),
1874 QObject::tr(
"Override the sub unit name from the seed file with the provided "
1875 "one or two character unit name." ),
1880 QObject::tr(
"Override the number of subunits per master unit. "
1881 "By default the seed file value is used." ),
1886 QObject::tr(
"Override the number of UORs (Units of Resolution) "
1887 "per sub unit. By default the seed file value is used." ),
1892 QObject::tr(
"ORIGIN=x,y,z: Override the origin of the design plane. "
1893 "By default the origin from the seed file is used." ),
1897 driverMetadata.insert( QStringLiteral(
"DGN" ),
1899 QStringLiteral(
"Microstation DGN" ),
1900 QObject::tr(
"Microstation DGN" ),
1901 QStringLiteral(
"*.dgn" ),
1902 QStringLiteral(
"dgn" ),
1909 datasetOptions.clear();
1910 layerOptions.clear();
1913 QObject::tr(
"Should update files be incorporated into the base data on the fly." ),
1915 << QStringLiteral(
"APPLY" )
1916 << QStringLiteral(
"IGNORE" ),
1917 QStringLiteral(
"APPLY" )
1921 QObject::tr(
"Should multipoint soundings be split into many single point sounding features. "
1922 "Multipoint geometries are not well handled by many formats, "
1923 "so it can be convenient to split single sounding features with many points "
1924 "into many single point features." ),
1929 QObject::tr(
"Should a DEPTH attribute be added on SOUNDG features and assign the depth "
1930 "of the sounding. This should only be enabled when SPLIT_MULTIPOINT is "
1936 QObject::tr(
"Should all the low level geometry primitives be returned as special "
1937 "IsolatedNode, ConnectedNode, Edge and Face layers." ),
1942 QObject::tr(
"If enabled, numeric attributes assigned an empty string as a value will "
1943 "be preserved as a special numeric value. This option should not generally "
1944 "be needed, but may be useful when translated S-57 to S-57 losslessly." ),
1949 QObject::tr(
"Should LNAM and LNAM_REFS fields be attached to features capturing "
1950 "the feature to feature relationships in the FFPT group of the S-57 file." ),
1955 QObject::tr(
"Should additional attributes relating features to their underlying "
1956 "geometric primitives be attached. These are the values of the FSPT group, "
1957 "and are primarily needed when doing S-57 to S-57 translations." ),
1962 QObject::tr(
"Should attribute values be recoded to UTF-8 from the character encoding "
1963 "specified in the S57 DSSI record." ),
1969 driverMetadata.insert( QStringLiteral(
"S57" ),
1971 QStringLiteral(
"S-57 Base file" ),
1972 QObject::tr(
"S-57 Base file" ),
1973 QStringLiteral(
"*.000" ),
1974 QStringLiteral(
"000" ),
1981 datasetOptions.clear();
1982 layerOptions.clear();
1984 driverMetadata.insert( QStringLiteral(
"SDTS" ),
1986 QStringLiteral(
"Spatial Data Transfer Standard [SDTS]" ),
1987 QObject::tr(
"Spatial Data Transfer Standard [SDTS]" ),
1988 QStringLiteral(
"*catd.ddf" ),
1989 QStringLiteral(
"ddf" ),
1996 datasetOptions.clear();
1997 layerOptions.clear();
2000 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2001 "tables in a new database. By default these metadata tables are created "
2002 "when a new database is created." ),
2008 QStringLiteral(
"NO" )
2013 QStringLiteral(
"NO" )
2017 QObject::tr(
"Controls the format used for the geometry column. Defaults to WKB. "
2018 "This is generally more space and processing efficient, but harder "
2019 "to inspect or use in simple applications than WKT (Well Known Text)." ),
2021 << QStringLiteral(
"WKB" )
2022 << QStringLiteral(
"WKT" ),
2023 QStringLiteral(
"WKB" )
2027 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2028 "in SQLite. Laundered names will be converted to lower case and some special "
2029 "characters(' - #) will be changed to underscores." ),
2034 QStringLiteral(
"NO" )
2038 QStringLiteral(
"NO" )
2046 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2047 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2048 "for databases that have big string blobs. However, use with care, since "
2049 "the value of such columns will be seen as compressed binary content with "
2050 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2051 "modifying or querying compressed columns, compression/decompression is "
2052 "done transparently. However, such columns cannot be (easily) queried with "
2053 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2054 "have the 'VARCHAR_deflate' declaration type." ),
2058 driverMetadata.insert( QStringLiteral(
"SQLite" ),
2060 QStringLiteral(
"SQLite" ),
2061 QObject::tr(
"SQLite" ),
2062 QStringLiteral(
"*.sqlite" ),
2063 QStringLiteral(
"sqlite" ),
2066 QStringLiteral(
"UTF-8" )
2071 datasetOptions.clear();
2072 layerOptions.clear();
2075 QObject::tr(
"Can be used to avoid creating the geometry_columns and spatial_ref_sys "
2076 "tables in a new database. By default these metadata tables are created "
2077 "when a new database is created." ),
2082 QStringLiteral(
"YES" )
2086 QObject::tr(
"Insert the content of the EPSG CSV files into the spatial_ref_sys table. "
2087 "Set to NO for regular SQLite databases." ),
2092 QStringLiteral(
"SPATIALITE" )
2096 QObject::tr(
"Controls whether layer and field names will be laundered for easier use "
2097 "in SQLite. Laundered names will be converted to lower case and some special "
2098 "characters(' - #) will be changed to underscores." ),
2103 QObject::tr(
"If the database is of the SpatiaLite flavor, and if OGR is linked "
2104 "against libspatialite, this option can be used to control if a spatial "
2105 "index must be created." ),
2110 QObject::tr(
"If the format of the geometry BLOB is of the SpatiaLite flavor, "
2111 "this option can be used to control if the compressed format for "
2112 "geometries (LINESTRINGs, POLYGONs) must be used." ),
2117 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2118 "When this option isn't specified and that a SRS is associated with the "
2119 "layer, a search is made in the spatial_ref_sys to find a match for the "
2120 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2121 "the spatial_ref_sys table. When the SRID option is specified, this "
2122 "search (and the eventual insertion of a new entry) will not be done: "
2123 "the specified SRID is used as such." ),
2128 QObject::tr(
"column_name1[,column_name2, …] A list of (String) columns that "
2129 "must be compressed with ZLib DEFLATE algorithm. This might be beneficial "
2130 "for databases that have big string blobs. However, use with care, since "
2131 "the value of such columns will be seen as compressed binary content with "
2132 "other SQLite utilities (or previous OGR versions). With OGR, when inserting, "
2133 "modifying or queryings compressed columns, compression/decompression is "
2134 "done transparently. However, such columns cannot be (easily) queried with "
2135 "an attribute filter or WHERE clause. Note: in table definition, such columns "
2136 "have the 'VARCHAR_deflate' declaration type." ),
2140 driverMetadata.insert( QStringLiteral(
"SpatiaLite" ),
2142 QStringLiteral(
"SpatiaLite" ),
2143 QObject::tr(
"SpatiaLite" ),
2144 QStringLiteral(
"*.sqlite" ),
2145 QStringLiteral(
"sqlite" ),
2148 QStringLiteral(
"UTF-8" )
2152 datasetOptions.clear();
2153 layerOptions.clear();
2156 QObject::tr(
"Override the header file used - in place of header.dxf." ),
2161 QObject::tr(
"Override the trailer file used - in place of trailer.dxf." ),
2165#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,11,0)
2167 QObject::tr(
"Drawing units for the model space ($INSUNITS system variable)." ),
2169 << QStringLiteral(
"AUTO" )
2170 << QStringLiteral(
"HEADER_VALUE" )
2171 << QStringLiteral(
"UNITLESS" )
2172 << QStringLiteral(
"INCHES" )
2173 << QStringLiteral(
"FEET" )
2174 << QStringLiteral(
"MILLIMETERS" )
2175 << QStringLiteral(
"CENTIMETERS" )
2176 << QStringLiteral(
"METERS" )
2177 << QStringLiteral(
"US_SURVEY_FEET" ),
2178 QStringLiteral(
"AUTO" )
2182 QObject::tr(
"Whether the current drawing uses imperial or metric hatch "
2183 "pattern and linetype ($MEASUREMENT system variable)." ),
2185 << QStringLiteral(
"HEADER_VALUE" )
2186 << QStringLiteral(
"IMPERIAL" )
2187 << QStringLiteral(
"METRIC" ),
2188 QStringLiteral(
"HEADER_VALUE" )
2192 driverMetadata.insert( QStringLiteral(
"DXF" ),
2194 QStringLiteral(
"AutoCAD DXF" ),
2195 QObject::tr(
"AutoCAD DXF" ),
2196 QStringLiteral(
"*.dxf" ),
2197 QStringLiteral(
"dxf" ),
2204 datasetOptions.clear();
2205 layerOptions.clear();
2208 QObject::tr(
"Indicates the GeoConcept export file extension. "
2209 "TXT was used by earlier releases of GeoConcept. GXT is currently used." ),
2211 << QStringLiteral(
"GXT" )
2212 << QStringLiteral(
"TXT" ),
2213 QStringLiteral(
"GXT" )
2217 QObject::tr(
"Path to the GCT: the GCT file describes the GeoConcept types definitions: "
2218 "In this file, every line must start with //# followed by a keyword. "
2219 "Lines starting with // are comments." ),
2224 QObject::tr(
"Defines the feature to be created. The TYPE corresponds to one of the Name "
2225 "found in the GCT file for a type section. The SUBTYPE corresponds to one of "
2226 "the Name found in the GCT file for a sub-type section within the previous "
2231 driverMetadata.insert( QStringLiteral(
"Geoconcept" ),
2233 QStringLiteral(
"Geoconcept" ),
2234 QObject::tr(
"Geoconcept" ),
2235 QStringLiteral(
"*.gxt *.txt" ),
2236 QStringLiteral(
"gxt" ),
2243 datasetOptions.clear();
2244 layerOptions.clear();
2246#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,9,0)
2248 QObject::tr(
"Selects which ArcGIS version this dataset should be compatible with. ALL is used by default and means any ArcGIS 10.x or ArcGIS Pro version. Using ARCGIS_PRO_3_2_OR_LATER is required to export 64-bit integer fields as such, otherwise they will be converted as Real fields. ARCGIS_PRO_3_2_OR_LATER also supports proper Date and Time field types." ),
2250 << QStringLiteral(
"ALL" )
2251 << QStringLiteral(
"ARCGIS_PRO_3_2_OR_LATER" ),
2252 QStringLiteral(
"ALL" )
2257 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2258 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2263 QObject::tr(
"Set layer name alias." ),
2268 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2269 QStringLiteral(
"SHAPE" )
2273 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'." ),
2278 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2279 QStringLiteral(
"OBJECTID" )
2295 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." ),
2300 QObject::tr(
"XML documentation for the layer." ),
2304 QObject::tr(
"Customize how data is stored. By default text in UTF-8 and data up to 1TB." ),
2305 {QStringLiteral(
"DEFAULTS" ), QStringLiteral(
"MAX_FILE_SIZE_4GB" ), QStringLiteral(
"MAX_FILE_SIZE_256TB" )},
2306 QStringLiteral(
"DEFAULTS" ),
2311 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." ),
2315 driverMetadata.insert( QStringLiteral(
"OpenFileGDB" ),
2317 QStringLiteral(
"ESRI File Geodatabase" ),
2318 QObject::tr(
"ESRI File Geodatabase" ),
2319 QStringLiteral(
"*.gdb" ),
2320 QStringLiteral(
"gdb" ),
2323 QStringLiteral(
"UTF-8" )
2327#if GDAL_VERSION_NUM < GDAL_COMPUTE_VERSION(3,11,0)
2329 datasetOptions.clear();
2330 layerOptions.clear();
2333 QObject::tr(
"When this option is set, the new layer will be created inside the named "
2334 "FeatureDataset folder. If the folder does not already exist, it will be created." ),
2339 QObject::tr(
"Set name of geometry column in new layer. Defaults to 'SHAPE'." ),
2340 QStringLiteral(
"SHAPE" )
2344 QObject::tr(
"Name of the OID column to create. Defaults to 'OBJECTID'." ),
2345 QStringLiteral(
"OBJECTID" )
2348 driverMetadata.insert( QStringLiteral(
"FileGDB" ),
2350 QStringLiteral(
"ESRI FileGDB" ),
2351 QObject::tr(
"ESRI FileGDB" ),
2352 QStringLiteral(
"*.gdb" ),
2353 QStringLiteral(
"gdb" ),
2356 QStringLiteral(
"UTF-8" )
2362 datasetOptions.clear();
2363 layerOptions.clear();
2366 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2367 "to STRING, all fields will be of String type." ),
2369 << QStringLiteral(
"AUTO" )
2370 << QStringLiteral(
"STRING" ),
2371 QStringLiteral(
"AUTO" ),
2376 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2377 "if the first line might be the name of columns. If set to FORCE, the driver "
2378 "will consider the first line as the header line. If set to "
2379 "DISABLE, it will be considered as the first feature. Otherwise "
2380 "auto-detection will occur." ),
2382 << QStringLiteral(
"FORCE" )
2383 << QStringLiteral(
"DISABLE" )
2384 << QStringLiteral(
"AUTO" ),
2385 QStringLiteral(
"AUTO" ),
2389 driverMetadata.insert( QStringLiteral(
"XLSX" ),
2391 QStringLiteral(
"MS Office Open XML spreadsheet" ),
2392 QObject::tr(
"MS Office Open XML spreadsheet [XLSX]" ),
2393 QStringLiteral(
"*.xlsx" ),
2394 QStringLiteral(
"xlsx" ),
2397 QStringLiteral(
"UTF-8" )
2402 datasetOptions.clear();
2403 layerOptions.clear();
2406 QObject::tr(
"By default, the driver will try to detect the data type of fields. If set "
2407 "to STRING, all fields will be of String type." ),
2409 << QStringLiteral(
"AUTO" )
2410 << QStringLiteral(
"STRING" ),
2411 QStringLiteral(
"AUTO" ),
2416 QObject::tr(
"By default, the driver will read the first lines of each sheet to detect "
2417 "if the first line might be the name of columns. If set to FORCE, the driver "
2418 "will consider the first line as the header line. If set to "
2419 "DISABLE, it will be considered as the first feature. Otherwise "
2420 "auto-detection will occur." ),
2422 << QStringLiteral(
"FORCE" )
2423 << QStringLiteral(
"DISABLE" )
2424 << QStringLiteral(
"AUTO" ),
2425 QStringLiteral(
"AUTO" ),
2429 driverMetadata.insert( QStringLiteral(
"ODS" ),
2431 QStringLiteral(
"Open Document Spreadsheet" ),
2432 QObject::tr(
"Open Document Spreadsheet [ODS]" ),
2433 QStringLiteral(
"*.ods" ),
2434 QStringLiteral(
"ods" ),
2437 QStringLiteral(
"UTF-8" )
2442 datasetOptions.clear();
2443 layerOptions.clear();
2445 QStringList compressionMethods;
2446 const QStringList searchCompressions =
2448 QStringLiteral(
"NONE" ),
2449 QStringLiteral(
"SNAPPY" ),
2450 QStringLiteral(
"BROTLI" ),
2451 QStringLiteral(
"ZSTD" )
2454 if ( GDALDriverH hParquetDrv = GDALGetDriverByName(
"PARQUET" ) )
2456 if (
const char *xml = GDALGetMetadataItem( hParquetDrv, GDAL_DS_LAYER_CREATIONOPTIONLIST,
nullptr ) )
2458 for (
const QString &
comp : searchCompressions )
2460 QRegularExpression re(
"<Value[^>]*>\\s*" +
comp +
"\\s*</Value>" );
2461 if ( re.match( QString::fromUtf8( xml ) ).hasMatch() )
2463 compressionMethods <<
comp;
2470 QObject::tr(
"Compression method." ),
2472 QStringLiteral(
"SNAPPY" ),
2476#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,12,0)
2478 QObject::tr(
"Compression level." ),
2483#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,9,0)
2485 QObject::tr(
"Whether to sort by spatial location. Enables faster spatial filtering on reading." ),
2490 QObject::tr(
"Whether to write the bounding box of geometries into columns." ),
2496 QObject::tr(
"Geometry encoding." ),
2498 << QStringLiteral(
"WKB" )
2499 << QStringLiteral(
"WKT" )
2500 << QStringLiteral(
"GEOARROW" ),
2501 QStringLiteral(
"WKB" ),
2506 QObject::tr(
"Maximum number of rows per group." ),
2511 QObject::tr(
"Name for the feature identifier column" ),
2516 QObject::tr(
"Name for the geometry column" ),
2517 QStringLiteral(
"geometry" )
2521 QObject::tr(
"Name of the coordinate system for the edges." ),
2523 << QStringLiteral(
"PLANAR" )
2524 << QStringLiteral(
"SPHERICAL" ),
2525 QStringLiteral(
"PLANAR" ),
2529 driverMetadata.insert( QStringLiteral(
"Parquet" ),
2531 QStringLiteral(
"(Geo)Parquet" ),
2532 QObject::tr(
"(Geo)Parquet" ),
2533 QStringLiteral(
"*.parquet" ),
2534 QStringLiteral(
"parquet" ),
2537 QStringLiteral(
"UTF-8" )
2542 datasetOptions.clear();
2543 layerOptions.clear();
2546 QObject::tr(
"Line termination character sequence." ),
2548 << QStringLiteral(
"CRLF" )
2549 << QStringLiteral(
"LF" ),
2550 QStringLiteral(
"LF" ),
2556 QObject::tr(
"Format of geometry columns." ),
2558 << QStringLiteral(
"geometry" )
2559 << QStringLiteral(
"geography" ),
2560 QStringLiteral(
"geometry" ),
2565 QObject::tr(
"Controls whether layer and field names will be laundered for easier use. "
2566 "Laundered names will be converted to lower case and some special "
2567 "characters(' - #) will be changed to underscores." ),
2572 QObject::tr(
"Name for the geometry column. Defaults to wkb_geometry "
2573 "for GEOM_TYPE=geometry or the_geog for GEOM_TYPE=geography" ) ) );
2576 QObject::tr(
"Name of schema into which to create the new table" ) ) );
2579 QObject::tr(
"Whether to explicitly emit the CREATE SCHEMA statement to create the specified schema." ),
2584 QObject::tr(
"Whether to explicitly recreate the table if necessary." ),
2589 QObject::tr(
"Whether to explicitly destroy tables before recreating them." ),
2591 << QStringLiteral(
"YES" )
2592 << QStringLiteral(
"NO" )
2593 << QStringLiteral(
"IF_EXISTS" ),
2594 QStringLiteral(
"YES" ),
2599 QObject::tr(
"Used to force the SRID number of the SRS associated with the layer. "
2600 "When this option isn't specified and that a SRS is associated with the "
2601 "layer, a search is made in the spatial_ref_sys to find a match for the "
2602 "SRS, and, if there is no match, a new entry is inserted for the SRS in "
2603 "the spatial_ref_sys table. When the SRID option is specified, this "
2604 "search (and the eventual insertion of a new entry) will not be done: "
2605 "the specified SRID is used as such." ),
2610 QObject::tr(
"Can be set to 2.0 or 2.2 for PostGIS 2.0/2.2 compatibility. "
2611 "Important to set it correctly if using non-linear geometry types" ),
2612 QStringLiteral(
"2.2" )
2615 driverMetadata.insert( QStringLiteral(
"PGDUMP" ),
2617 QStringLiteral(
"PostgreSQL SQL dump" ),
2618 QObject::tr(
"PostgreSQL SQL dump" ),
2619 QStringLiteral(
"*.sql" ),
2620 QStringLiteral(
"sql" ),
2623 QStringLiteral(
"UTF-8" )
2629 QgsVectorFileWriterMetadataContainer(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2630 QgsVectorFileWriterMetadataContainer &operator=(
const QgsVectorFileWriterMetadataContainer &other ) =
delete;
2631 ~QgsVectorFileWriterMetadataContainer()
2633 for (
auto it = driverMetadata.constBegin(); it != driverMetadata.constEnd(); ++it )
2635 for (
auto optionIt = it.value().driverOptions.constBegin(); optionIt != it.value().driverOptions.constEnd(); ++optionIt )
2636 delete optionIt.value();
2637 for (
auto optionIt = it.value().layerOptions.constBegin(); optionIt != it.value().layerOptions.constEnd(); ++optionIt )
2638 delete optionIt.value();
2642 QMap<QString, QgsVectorFileWriter::MetaData> driverMetadata;
2649 static QgsVectorFileWriterMetadataContainer sDriverMetadata;
2650 QMap<QString, MetaData>::ConstIterator it = sDriverMetadata.driverMetadata.constBegin();
2652 for ( ; it != sDriverMetadata.driverMetadata.constEnd(); ++it )
2654 if ( it.key() == QLatin1String(
"PGDUMP" ) &&
2655 driverName != QLatin1String(
"PGDUMP" ) &&
2656 driverName != QLatin1String(
"PostgreSQL SQL dump" ) )
2661 if ( it.key().startsWith( driverName ) || it.value().longName.startsWith( driverName ) )
2676 return QStringList();
2685 return QStringList();
2692 OGRwkbGeometryType ogrType =
static_cast<OGRwkbGeometryType
>( type );
2723 return mCapabilities;
2733 QgsFeatureList::iterator fIt = features.begin();
2735 for ( ; fIt != features.end(); ++fIt )
2760 QString styleString;
2761 QString currentStyle;
2763 QgsSymbolList::const_iterator symbolIt = symbols.constBegin();
2764 for ( ; symbolIt != symbols.constEnd(); ++symbolIt )
2766 int nSymbolLayers = ( *symbolIt )->symbolLayerCount();
2767 for (
int i = 0; i < nSymbolLayers; ++i )
2770 QMap< QgsSymbolLayer *, QString >::const_iterator it =
mSymbolLayerTable.find( ( *symbolIt )->symbolLayer( i ) );
2776 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2777 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), outputUnit );
2779 currentStyle = ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf );
2785 if ( symbolIt != symbols.constBegin() || i != 0 )
2787 styleString.append(
';' );
2789 styleString.append( currentStyle );
2794 OGR_F_SetStyleString( poFeature.get(), currentStyle.toLocal8Bit().constData() );
2795 if ( !writeFeature(
mLayer, poFeature.get() ) )
2807 OGR_F_SetStyleString( poFeature.get(), styleString.toLocal8Bit().constData() );
2815 if ( !writeFeature(
mLayer, poFeature.get() ) )
2839 int fldIdx = it.key();
2840 int ogrField = it.value();
2842 QVariant attrValue = feature.
attribute( fldIdx );
2847 OGR_F_UnsetField( poFeature.get(), ogrField );
2860 OGR_F_SetFieldNull( poFeature.get(), ogrField );
2875 mErrorMessage = QObject::tr(
"Error converting value (%1) for attribute field %2: %3" )
2876 .arg( feature.
attribute( fldIdx ).toString(),
2883 switch ( field.
type() )
2885 case QMetaType::Type::Int:
2886 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2888 case QMetaType::Type::LongLong:
2889 OGR_F_SetFieldInteger64( poFeature.get(), ogrField, attrValue.toLongLong() );
2891 case QMetaType::Type::Bool:
2892 OGR_F_SetFieldInteger( poFeature.get(), ogrField, attrValue.toInt() );
2894 case QMetaType::Type::QString:
2895 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2897 case QMetaType::Type::Double:
2898 OGR_F_SetFieldDouble( poFeature.get(), ogrField, attrValue.toDouble() );
2900 case QMetaType::Type::QDate:
2901 OGR_F_SetFieldDateTime( poFeature.get(), ogrField,
2902 attrValue.toDate().year(),
2903 attrValue.toDate().month(),
2904 attrValue.toDate().day(),
2907 case QMetaType::Type::QDateTime:
2910 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toDateTime().toString( QStringLiteral(
"yyyy/MM/dd hh:mm:ss.zzz" ) ) ).constData() );
2914 const QDateTime dt = attrValue.toDateTime();
2915 const QDate date = dt.date();
2916 const QTime time = dt.time();
2917 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2923 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2927 case QMetaType::Type::QTime:
2930 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( attrValue.toString() ).constData() );
2934 const QTime time = attrValue.toTime();
2935 OGR_F_SetFieldDateTimeEx( poFeature.get(), ogrField,
2939 static_cast<float>( time.second() +
static_cast< double >( time.msec() ) / 1000 ),
2944 case QMetaType::Type::QByteArray:
2946 const QByteArray ba = attrValue.toByteArray();
2947 OGR_F_SetFieldBinary( poFeature.get(), ogrField, ba.size(),
const_cast< GByte *
>(
reinterpret_cast< const GByte *
>( ba.data() ) ) );
2951 case QMetaType::Type::UnknownType:
2954 case QMetaType::Type::QStringList:
2959 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
2961 if ( !doc.isNull() )
2963 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).constData() );
2965 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
2969 QStringList list = attrValue.toStringList();
2970 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
2972 int count = list.count();
2973 char **lst =
new char *[count + 1];
2977 for (
const QString &
string : list )
2979 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
2983 lst[count] =
nullptr;
2984 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
2989 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
2994 case QMetaType::Type::QVariantList:
2998 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3000 if ( !doc.isNull() )
3002 jsonString = QString::fromUtf8( doc.toJson( QJsonDocument::Compact ).data() );
3004 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3009 if ( field.
subType() == QMetaType::Type::QString )
3011 QStringList list = attrValue.toStringList();
3012 if ( mSupportedListSubTypes.contains( QMetaType::Type::QString ) )
3014 int count = list.count();
3015 char **lst =
new char *[count + 1];
3019 for (
const QString &
string : list )
3021 lst[pos] = CPLStrdup(
mCodec->fromUnicode(
string ).data() );
3025 lst[count] =
nullptr;
3026 OGR_F_SetFieldStringList( poFeature.get(), ogrField, lst );
3031 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( list.join(
',' ) ).constData() );
3035 else if ( field.
subType() == QMetaType::Type::Int )
3037 const QVariantList list = attrValue.toList();
3038 if ( mSupportedListSubTypes.contains( QMetaType::Type::Int ) )
3040 const int count = list.count();
3041 int *lst =
new int[count];
3045 for (
const QVariant &value : list )
3047 lst[pos] = value.toInt();
3051 OGR_F_SetFieldIntegerList( poFeature.get(), ogrField, count, lst );
3056 QStringList strings;
3057 strings.reserve( list.size() );
3058 for (
const QVariant &value : list )
3060 strings << QString::number( value.toInt() );
3062 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3066 else if ( field.
subType() == QMetaType::Type::Double )
3068 const QVariantList list = attrValue.toList();
3069 if ( mSupportedListSubTypes.contains( QMetaType::Type::Double ) )
3071 const int count = list.count();
3072 double *lst =
new double[count];
3076 for (
const QVariant &value : list )
3078 lst[pos] = value.toDouble();
3082 OGR_F_SetFieldDoubleList( poFeature.get(), ogrField, count, lst );
3087 QStringList strings;
3088 strings.reserve( list.size() );
3089 for (
const QVariant &value : list )
3091 strings << QString::number( value.toDouble() );
3093 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3097 else if ( field.
subType() == QMetaType::Type::LongLong )
3099 const QVariantList list = attrValue.toList();
3100 if ( mSupportedListSubTypes.contains( QMetaType::Type::LongLong ) )
3102 const int count = list.count();
3103 long long *lst =
new long long[count];
3107 for (
const QVariant &value : list )
3109 lst[pos] = value.toLongLong();
3113 OGR_F_SetFieldInteger64List( poFeature.get(), ogrField, count, lst );
3118 QStringList strings;
3119 strings.reserve( list.size() );
3120 for (
const QVariant &value : list )
3122 strings << QString::number( value.toLongLong() );
3124 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( strings.join(
',' ) ).constData() );
3131 case QMetaType::Type::QVariantMap:
3134 const char *pszDataSubTypes = GDALGetMetadataItem( OGRGetDriverByName(
mOgrDriverName.toLocal8Bit().constData() ), GDAL_DMD_CREATIONFIELDDATASUBTYPES,
nullptr );
3135 if ( pszDataSubTypes && strstr( pszDataSubTypes,
"JSON" ) )
3137 const QJsonDocument doc = QJsonDocument::fromVariant( attrValue );
3139 if ( !doc.isNull() )
3141 const QByteArray json { doc.toJson( QJsonDocument::Compact ) };
3142 jsonString = QString::fromUtf8( json.data() );
3144 OGR_F_SetFieldString( poFeature.get(), ogrField,
mCodec->fromUnicode( jsonString.constData() ) );
3154 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
3157 .arg( attrValue.typeName(),
3158 attrValue.toString() );
3171 if ( mCoordinateTransform )
3176 geom.
transform( *mCoordinateTransform );
3194 OGRGeometryH mGeom2 =
nullptr;
3223 geom.
get()->
addZValue( std::numeric_limits<double>::quiet_NaN() );
3230 geom.
get()->
addMValue( std::numeric_limits<double>::quiet_NaN() );
3250 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3251 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3261 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3262 OGRErr err = OGR_G_ImportFromWkb( mGeom2,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3263 if ( err != OGRERR_NONE )
3265 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3266 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3273 OGR_F_SetGeometryDirectly( poFeature.get(), mGeom2 );
3281 QByteArray wkb( geom.
asWkb( wkbFlags ) );
3283 OGRErr err = OGR_G_ImportFromWkb( ogrGeom,
reinterpret_cast<unsigned char *
>(
const_cast<char *
>( wkb.constData() ) ), wkb.length() );
3284 if ( err != OGRERR_NONE )
3286 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
3287 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3294 OGR_F_SetGeometryDirectly( poFeature.get(), ogrGeom );
3309 for (
int i = 0; i < attributes.size(); i++ )
3311 if ( omap.find( i ) != omap.end() )
3316bool QgsVectorFileWriter::writeFeature( OGRLayerH layer, OGRFeatureH feature )
3318 if ( OGR_L_CreateFeature( layer, feature ) != OGRERR_NONE )
3320 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
3330 if ( mUsingTransaction )
3332 if ( OGRERR_NONE != OGR_L_CommitTransaction(
mLayer ) )
3334 QgsDebugError( QStringLiteral(
"Error while committing transaction on OGRLayer." ) );
3347 const QString &fileName,
3348 const QString &fileEncoding,
3350 const QString &driverName,
3352 QString *errorMessage,
3353 const QStringList &datasourceOptions,
3354 const QStringList &layerOptions,
3355 bool skipAttributeCreation,
3356 QString *newFilename,
3358 double symbologyScale,
3368 if ( destCRS.
isValid() && layer )
3394 const QString &fileName,
3395 const QString &fileEncoding,
3397 const QString &driverName,
3399 QString *errorMessage,
3400 const QStringList &datasourceOptions,
3401 const QStringList &layerOptions,
3402 bool skipAttributeCreation,
3403 QString *newFilename,
3405 double symbologyScale,
3436 : driverName( QStringLiteral(
"GPKG" ) )
3444 if ( !layer || !layer->
isValid() )
3451 details.sourceCrs = layer->
crs();
3452 details.sourceWkbType = layer->
wkbType();
3453 details.sourceFields = layer->
fields();
3462 if ( details.storageType == QLatin1String(
"ESRI Shapefile" ) )
3470 details.geometryTypeScanIterator = layer->
getFeatures( req );
3474 details.renderContext.setExpressionContext( details.expressionContext );
3475 details.renderContext.setRendererScale( options.
symbologyScale );
3477 details.shallTransform =
false;
3482 details.shallTransform =
true;
3487 details.outputCrs = details.sourceCrs;
3490 details.destWkbType = details.sourceWkbType;
3504 details.attributes.clear();
3505 else if ( details.attributes.isEmpty() )
3507 const QgsAttributeList allAttributes = details.sourceFields.allAttributesList();
3508 for (
int idx : allAttributes )
3510 QgsField fld = details.sourceFields.at( idx );
3511 if ( details.providerType == QLatin1String(
"oracle" ) && fld.
typeName().contains( QLatin1String(
"SDO_GEOMETRY" ) ) )
3513 details.attributes.append( idx );
3517 if ( !details.attributes.isEmpty() )
3519 for (
int attrIdx : std::as_const( details.attributes ) )
3521 if ( details.sourceFields.exists( attrIdx ) )
3523 QgsField field = details.sourceFields.at( attrIdx );
3525 details.outputFields.append( field );
3529 QgsDebugError( QStringLiteral(
"No such source field with index '%1' available." ).arg( attrIdx ) );
3536 if ( details.providerType == QLatin1String(
"spatialite" ) )
3538 for (
int i = 0; i < details.outputFields.size(); i++ )
3540 if ( details.outputFields.at( i ).type() == QMetaType::Type::LongLong )
3545 if ( std::max( std::llabs( min.toLongLong() ), std::llabs( max.toLongLong() ) ) < std::numeric_limits<int>::max() )
3547 details.outputFields[i].setType( QMetaType::Type::Int );
3555 addRendererAttributes( details.renderer.get(), details.renderContext, details.sourceFields, details.attributes );
3565 bool useFilterRect =
true;
3566 if ( details.shallTransform )
3577 useFilterRect =
false;
3580 if ( useFilterRect )
3586 details.filterRectEngine->prepareGeometry();
3588 details.sourceFeatureIterator = layer->
getFeatures( req );
3607 int lastProgressReport = 0;
3608 long long total = details.featureCount;
3611 if ( details.providerType == QLatin1String(
"ogr" ) && !details.dataSourceUri.isEmpty() )
3613 QString srcFileName( details.providerUriParams.value( QStringLiteral(
"path" ) ).toString() );
3614 if ( QFile::exists( srcFileName ) && QFileInfo( fileName ).canonicalFilePath() == QFileInfo( srcFileName ).canonicalFilePath() )
3618 if ( !( ( options.
driverName == QLatin1String(
"GPKG" ) ||
3619 options.
driverName == QLatin1String(
"SpatiaLite" ) ||
3620 options.
driverName == QLatin1String(
"SQLite" ) ) &&
3621 options.
layerName != details.providerUriParams.value( QStringLiteral(
"layerName" ) ) ) )
3624 *
errorMessage = QObject::tr(
"Cannot overwrite an OGR layer in place" );
3644 int newProgress =
static_cast<int>( ( 5.0 * scanned ) / total );
3645 if ( newProgress != lastProgressReport )
3647 lastProgressReport = newProgress;
3662 QString tempNewFilename;
3663 QString tempNewLayer;
3671 std::unique_ptr< QgsVectorFileWriter > writer(
create( fileName, details.outputFields, destWkbType, details.outputCrs, transformContext, newOptions, sinkFlags, &tempNewFilename, &tempNewLayer ) );
3675 *newFilename = tempNewFilename;
3678 *newLayer = tempNewLayer;
3707 switch ( writer->symbologyExport() )
3725 int n = 0, errors = 0;
3734 writer->startRender( details.renderer.get(), details.sourceFields );
3736 writer->resetMap( details.attributes );
3738 writer->mFields = details.sourceFields;
3742 int initialProgress = lastProgressReport;
3743 while ( details.sourceFeatureIterator.nextFeature( fet ) )
3754 int newProgress =
static_cast<int>( initialProgress + ( ( 100.0 - initialProgress ) * saved ) / total );
3755 if ( newProgress < 100 && newProgress != lastProgressReport )
3757 lastProgressReport = newProgress;
3762 if ( details.shallTransform )
3775 const QString msg = QObject::tr(
"Failed to transform feature with ID '%1'. Writing stopped. (Exception: %2)" )
3776 .arg( fet.
id() ).arg( e.
what() );
3793 if ( !writer->addFeatureWithStyle( fet, writer->mRenderer.get(), mapUnits ) )
3800 *
errorMessage = QObject::tr(
"Feature write errors:" );
3806 if ( errors > 1000 )
3810 *
errorMessage += QObject::tr(
"Stopping after %n error(s)",
nullptr, errors );
3820 writer->stopRender();
3824 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
3829 bool metadataFailure =
false;
3834 {QStringLiteral(
"path" ), tempNewFilename },
3835 {QStringLiteral(
"layerName" ), tempNewLayer }
3849 metadataFailure =
true;
3860 metadataFailure =
true;
3868 const QString &fileName,
3870 QString *newFilename,
3874 QgsVectorFileWriter::PreparedWriterDetails details;
3875 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3883 const QString &fileName,
3886 QString *newFilename,
3890 QgsVectorFileWriter::PreparedWriterDetails details;
3891 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3900 QgsVectorFileWriter::PreparedWriterDetails details;
3901 WriterError err = prepareWriteAsVectorFormat( layer, options, details );
3910 QFileInfo fi( fileName );
3911 QDir dir = fi.dir();
3914 for (
const char *suffix : {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj",
".cpg",
".sbn",
".sbx",
".idm",
".ind" } )
3916 filter << fi.completeBaseName() + suffix;
3920 const auto constEntryList = dir.entryList( filter );
3921 for (
const QString &file : constEntryList )
3923 QFile f( dir.canonicalPath() +
'/' + file );
3926 QgsDebugError( QStringLiteral(
"Removing file %1 failed: %2" ).arg( file, f.errorString() ) );
3942 QStringList driverNames;
3945 for (
int i = 0; i < GDALGetDriverCount(); ++i )
3947 GDALDriverH
driver = GDALGetDriver( i );
3954 const QString driverExtensions = GDALGetMetadataItem(
driver, GDAL_DMD_EXTENSIONS,
"" );
3955 if ( driverExtensions.isEmpty() )
3958 const QSet< QString > splitExtensions = qgis::listToSet( driverExtensions.split(
' ', Qt::SkipEmptyParts ) );
3959 if ( splitExtensions.intersects( multiLayerExtensions ) )
3961 driverNames << GDALGetDescription(
driver );
3969 static QReadWriteLock sFilterLock;
3970 static QMap< VectorFormatOptions, QList< QgsVectorFileWriter::FilterFormatDetails > > sFilters;
3974 const auto it = sFilters.constFind( options );
3975 if ( it != sFilters.constEnd() )
3979 QList< QgsVectorFileWriter::FilterFormatDetails > results;
3982 int const drvCount = OGRGetDriverCount();
3986 for (
int i = 0; i < drvCount; ++i )
3988 OGRSFDriverH drv = OGRGetDriver( i );
3991 const QString drvName = GDALGetDescription( drv );
3995 if ( !multiLayerDrivers.contains( drvName ) )
3999 GDALDriverH gdalDriver = GDALGetDriverByName( drvName.toLocal8Bit().constData() );
4000 bool nonSpatialFormat =
false;
4003 nonSpatialFormat = GDALGetMetadataItem( gdalDriver, GDAL_DCAP_NONSPATIAL,
nullptr );
4006 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4011 if ( nonSpatialFormat )
4016 if ( filterString.isEmpty() )
4023 globs = metadata.
glob.toLower().split(
' ' );
4029 details.
globs = globs;
4038 if ( options & SortRecommended )
4040 if ( a.driverName == QLatin1String(
"GPKG" ) )
4042 else if ( b.driverName == QLatin1String(
"GPKG" ) )
4044 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
4046 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4053 sFilters.insert( options, results );
4060 QSet< QString > extensions;
4062 const thread_local QRegularExpression rx( QStringLiteral(
"\\*\\.(.*)$" ) );
4066 for (
const QString &glob : format.globs )
4068 const QRegularExpressionMatch match = rx.match( glob );
4069 if ( !match.hasMatch() )
4072 const QString matched = match.captured( 1 );
4073 extensions.insert( matched );
4077 QStringList extensionList( extensions.constBegin(), extensions.constEnd() );
4079 std::sort( extensionList.begin(), extensionList.end(), [options](
const QString & a,
const QString & b ) ->
bool
4081 if ( options & SortRecommended )
4083 if ( a == QLatin1String(
"gpkg" ) )
4085 else if ( b == QLatin1String(
"gpkg" ) )
4087 else if ( a == QLatin1String(
"shp" ) )
4089 else if ( b == QLatin1String(
"shp" ) )
4093 return a.toLower().localeAwareCompare( b.toLower() ) < 0;
4096 return extensionList;
4101 QList< QgsVectorFileWriter::DriverDetails > results;
4104 const int drvCount = OGRGetDriverCount();
4108 QStringList writableDrivers;
4109 for (
int i = 0; i < drvCount; ++i )
4111 OGRSFDriverH drv = OGRGetDriver( i );
4114 const QString drvName = GDALGetDescription( drv );
4118 if ( !multiLayerDrivers.contains( drvName ) )
4126 if ( drvName == QLatin1String(
"ODS" ) || drvName == QLatin1String(
"XLSX" ) || drvName == QLatin1String(
"XLS" ) )
4130 if ( drvName == QLatin1String(
"ESRI Shapefile" ) )
4132 writableDrivers << QStringLiteral(
"DBF file" );
4134 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
4137 if ( drvName == QLatin1String(
"MapInfo File" ) )
4139 writableDrivers << QStringLiteral(
"MapInfo MIF" );
4141 else if ( drvName == QLatin1String(
"SQLite" ) )
4148 QString option = QStringLiteral(
"SPATIALITE=YES" );
4149 char *options[2] = { CPLStrdup( option.toLocal8Bit().constData() ),
nullptr };
4150 OGRSFDriverH poDriver;
4152 poDriver = OGRGetDriverByName( drvName.toLocal8Bit().constData() );
4155 gdal::ogr_datasource_unique_ptr ds( OGR_Dr_CreateDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData(), options ) );
4158 writableDrivers << QStringLiteral(
"SpatiaLite" );
4159 OGR_Dr_DeleteDataSource( poDriver, QStringLiteral(
"/vsimem/spatialitetest.sqlite" ).toUtf8().constData() );
4162 CPLFree( options[0] );
4164 writableDrivers << drvName;
4169 results.reserve( writableDrivers.count() );
4170 for (
const QString &drvName : std::as_const( writableDrivers ) )
4184 if ( options & SortRecommended )
4186 if ( a.driverName == QLatin1String(
"GPKG" ) )
4188 else if ( b.driverName == QLatin1String(
"GPKG" ) )
4190 else if ( a.driverName == QLatin1String(
"ESRI Shapefile" ) )
4192 else if ( b.driverName == QLatin1String(
"ESRI Shapefile" ) )
4196 return a.
longName.toLower().localeAwareCompare( b.
longName.toLower() ) < 0;
4203 QString ext = extension.trimmed();
4204 if ( ext.isEmpty() )
4207 if ( ext.startsWith(
'.' ) )
4211 int const drvCount = GDALGetDriverCount();
4213 for (
int i = 0; i < drvCount; ++i )
4215 GDALDriverH drv = GDALGetDriver( i );
4221 QString drvName = GDALGetDriverShortName( drv );
4222 QStringList driverExtensions = QString( GDALGetMetadataItem( drv, GDAL_DMD_EXTENSIONS,
nullptr ) ).split(
' ' );
4224 const auto constDriverExtensions = driverExtensions;
4225 for (
const QString &
driver : constDriverExtensions )
4227 if (
driver.compare( ext, Qt::CaseInsensitive ) == 0 )
4238 QString filterString;
4242 if ( !filterString.isEmpty() )
4243 filterString += QLatin1String(
";;" );
4245 filterString += details.filterString;
4247 return filterString;
4256 return QStringLiteral(
"%1 (%2 %3)" ).arg( metadata.
trLongName,
4257 metadata.
glob.toLower(),
4258 metadata.
glob.toUpper() );
4263 if ( codecName == QLatin1String(
"System" ) )
4264 return QStringLiteral(
"LDID/0" );
4266 const thread_local QRegularExpression re( QRegularExpression::anchoredPattern( QString(
"(CP|windows-|ISO[ -])(.+)" ) ), QRegularExpression::CaseInsensitiveOption );
4267 const QRegularExpressionMatch match = re.match( codecName );
4268 if ( match.hasMatch() )
4270 QString
c = match.captured( 2 ).remove(
'-' );
4272 ( void )
c.toInt( &isNumber );
4300 OGRStyleTableH ogrStyleTable = OGR_STBL_Create();
4301 OGRStyleMgrH styleManager = OGR_SM_Create( ogrStyleTable );
4304 int nTotalLevels = 0;
4306 QgsSymbolList::iterator symbolIt = symbolList.begin();
4307 for ( ; symbolIt != symbolList.end(); ++symbolIt )
4309 double mmsf = mmScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4310 double musf = mapUnitScaleFactor(
mSymbologyScale, ( *symbolIt )->outputUnit(), mapUnits );
4312 int nLevels = ( *symbolIt )->symbolLayerCount();
4313 for (
int i = 0; i < nLevels; ++i )
4315 mSymbolLayerTable.insert( ( *symbolIt )->symbolLayer( i ), QString::number( nTotalLevels ) );
4316 OGR_SM_AddStyle( styleManager, QString::number( nTotalLevels ).toLocal8Bit(),
4317 ( *symbolIt )->symbolLayer( i )->ogrFeatureStyle( mmsf, musf ).toLocal8Bit() );
4321 OGR_DS_SetStyleTableDirectly( ds, ogrStyleTable );
4327 if ( !details.renderer )
4332 QHash< QgsSymbol *, QList<QgsFeature> > features;
4341 startRender( details.renderer.get(), details.sourceFields );
4361 QString msg = QObject::tr(
"Failed to transform, writing stopped. (Exception: %1)" )
4372 featureSymbol = mRenderer->symbolForFeature( fet, mRenderContext );
4373 if ( !featureSymbol )
4378 QHash< QgsSymbol *, QList<QgsFeature> >::iterator it = features.find( featureSymbol );
4379 if ( it == features.end() )
4381 it = features.insert( featureSymbol, QList<QgsFeature>() );
4383 it.value().append( fet );
4388 QgsSymbolList symbols = mRenderer->symbols( mRenderContext );
4389 for (
int i = 0; i < symbols.count(); i++ )
4395 if ( level < 0 || level >= 1000 )
4398 while ( level >= levels.count() )
4400 levels[level].append( item );
4405 int nTotalFeatures = 0;
4408 for (
int l = 0; l < levels.count(); l++ )
4411 for (
int i = 0; i < level.count(); i++ )
4414 QHash< QgsSymbol *, QList<QgsFeature> >::iterator levelIt = features.find( item.
symbol() );
4415 if ( levelIt == features.end() )
4421 double mmsf = mmScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4422 double musf = mapUnitScaleFactor(
mSymbologyScale, levelIt.key()->outputUnit(), mapUnits );
4424 int llayer = item.
layer();
4425 QList<QgsFeature> &featureList = levelIt.value();
4426 QList<QgsFeature>::iterator featureIt = featureList.begin();
4427 for ( ; featureIt != featureList.end(); ++featureIt )
4437 QString styleString = levelIt.key()->symbolLayer( llayer )->ogrFeatureStyle( mmsf, musf );
4438 if ( !styleString.isEmpty() )
4440 OGR_F_SetStyleString( ogrFeature.get(), styleString.toLocal8Bit().constData() );
4441 if ( !writeFeature(
mLayer, ogrFeature.get() ) )
4454 *
errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( nTotalFeatures - nErrors ).arg( nTotalFeatures );
4471 return 1000 / scale;
4488 return scale / 1000;
4496 mRenderer = createSymbologyRenderer( sourceRenderer );
4502 mRenderer->startRender( mRenderContext, fields );
4505void QgsVectorFileWriter::stopRender()
4512 mRenderer->stopRender( mRenderContext );
4515std::unique_ptr<QgsFeatureRenderer> QgsVectorFileWriter::createSymbologyRenderer(
QgsFeatureRenderer *sourceRenderer )
const
4528 if ( !sourceRenderer )
4533 return std::unique_ptr< QgsFeatureRenderer >( sourceRenderer->
clone() );
4540 const QSet<QString> rendererAttributes = renderer->
usedAttributes( context );
4541 for (
const QString &attr : rendererAttributes )
4546 attList.append( index );
4552QStringList QgsVectorFileWriter::concatenateOptions(
const QMap<QString, QgsVectorFileWriter::Option *> &options )
4555 QMap<QString, QgsVectorFileWriter::Option *>::ConstIterator it;
4557 for ( it = options.constBegin(); it != options.constEnd(); ++it )
4560 switch ( option->
type )
4567 list.append( QStringLiteral(
"%1=%2" ).arg( it.key() ).arg( opt->
defaultValue ) );
4577 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4587 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
defaultValue ) );
4594 if ( opt && !opt->
mValue.isEmpty() )
4596 list.append( QStringLiteral(
"%1=%2" ).arg( it.key(), opt->
mValue ) );
4607 OGRSFDriverH hDriver =
nullptr;
4611 const QString drvName = GDALGetDescription( hDriver );
4613 if ( OGR_DS_TestCapability( hDS.get(), ODsCCreateLayer ) )
4618 if ( !( drvName == QLatin1String(
"ESRI Shapefile" ) && QFile::exists( datasetName ) ) )
4621 if ( OGR_DS_TestCapability( hDS.get(), ODsCDeleteLayer ) )
4625 int layer_count = OGR_DS_GetLayerCount( hDS.get() );
4628 OGRLayerH hLayer = OGR_DS_GetLayer( hDS.get(), 0 );
4631 if ( OGR_L_TestCapability( hLayer, OLCSequentialWrite ) )
4634 if ( OGR_L_TestCapability( hLayer, OLCCreateField ) )
4645 const QString &layerNameIn )
4647 OGRSFDriverH hDriver =
nullptr;
4652 QString layerName( layerNameIn );
4653 if ( layerName.isEmpty() )
4654 layerName = QFileInfo( datasetName ).baseName();
4656 return OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4661 const QString &layerName,
4665 OGRSFDriverH hDriver =
nullptr;
4669 OGRLayerH hLayer = OGR_DS_GetLayerByName( hDS.get(), layerName.toUtf8().constData() );
4675 OGRFeatureDefnH defn = OGR_L_GetLayerDefn( hLayer );
4676 const auto constAttributes = attributes;
4677 for (
int idx : constAttributes )
4680 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)
Provides common functionality for database based connections.
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.
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.
Stores the component parts of a 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.
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.
Qgis::WkbType wkbType() const
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Sets the current locale to the c locale for the lifetime of the object.
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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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.
Custom exception class for provider connection related exceptions.
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.
A convenience class that simplifies locking and unlocking QReadWriteLocks.
void changeMode(Mode mode)
Change the mode of the lock to mode.
A rectangle specified with double values.
Contains information about the context of a rendering operation.
QgsExpressionContext & expressionContext()
Gets the expression context.
void setRendererScale(double scale)
Sets the renderer map scale.
Stores settings for use within QGIS.
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.
Represents a symbol level during vector rendering operations.
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.
An available option for configuring file writing for a particular output format, presenting an boolea...
Interface to convert raw field values to their user-friendly values.
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.
A hidden option for file writing for a particular output format.
An available option for configuring file writing for a particular output format, presenting an intege...
Describes an available option for configuring file writing for a particular output format.
QgsVectorFileWriter::OptionType type
Options to pass to QgsVectorFileWriter::writeAsVectorFormat().
QString fileEncoding
Encoding to use.
bool forceMulti
Sets to true to force creation of multipart geometries.
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.
QgsVectorFileWriter::FieldNameSource fieldNameSource
Source for exported field names.
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.
An available option for configuring file writing for a particular output format, presenting a choice ...
An available option for configuring file writing for a particular output format, presenting a freefor...
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 dataset.
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 Qgis::WkbType addZ(Qgis::WkbType type)
Adds the z dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Qgis::WkbType singleType(Qgis::WkbType type)
Returns the single type for a WKB type.
static Q_INVOKABLE 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.
static Q_INVOKABLE bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi 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.