33 #include <QTextStream>
41 #include <ogr_srs_api.h>
42 #include <cpl_error.h>
45 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM >= 1800
46 #define TO8(x) (x).toUtf8().constData()
47 #define TO8F(x) (x).toUtf8().constData()
49 #define TO8(x) (x).toLocal8Bit().constData()
50 #define TO8F(x) QFile::encodeName( x ).constData()
55 const QString &theVectorFileName,
56 const QString &theFileEncoding,
60 const QString& driverName,
61 const QStringList &datasourceOptions,
62 const QStringList &layerOptions
69 QString vectorFileName = theVectorFileName;
70 QString fileEncoding = theFileEncoding;
73 OGRSFDriverH poDriver;
75 poDriver = OGRGetDriverByName( driverName.toLocal8Bit().data() );
77 if ( poDriver == NULL )
79 mErrorMessage = QObject::tr(
"OGR driver for '%1' not found (OGR error: %2)" )
81 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
86 if ( driverName ==
"ESRI Shapefile" )
88 if ( !vectorFileName.endsWith(
".shp", Qt::CaseInsensitive ) &&
89 !vectorFileName.endsWith(
".dbf", Qt::CaseInsensitive ) )
91 vectorFileName +=
".shp";
94 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM < 1700
96 QSet<QString> fieldNames;
97 QgsFieldMap::const_iterator fldIt;
98 for ( fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
100 QString name = fldIt.value().name().left( 10 );
101 if ( fieldNames.contains( name ) )
103 mErrorMessage = QObject::tr(
"trimming attribute name '%1' to ten significant characters produces duplicate column name." )
104 .arg( fldIt.value().name() );
114 else if ( driverName ==
"KML" )
116 if ( !vectorFileName.endsWith(
".kml", Qt::CaseInsensitive ) )
118 vectorFileName +=
".kml";
121 if ( fileEncoding.compare(
"UTF-8", Qt::CaseInsensitive ) != 0 )
124 fileEncoding =
"UTF-8";
127 QFile::remove( vectorFileName );
137 QStringList allExts = exts.split(
" ", QString::SkipEmptyParts );
139 foreach( QString ext, allExts )
141 if ( vectorFileName.endsWith(
"." + ext, Qt::CaseInsensitive ) )
150 vectorFileName +=
"." + allExts[0];
154 QFile::remove( vectorFileName );
157 char **options = NULL;
158 if ( !datasourceOptions.isEmpty() )
160 options =
new char *[ datasourceOptions.size()+1 ];
161 for (
int i = 0; i < datasourceOptions.size(); i++ )
163 options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().data() );
165 options[ datasourceOptions.size()] = NULL;
169 mDS = OGR_Dr_CreateDataSource( poDriver,
TO8( vectorFileName ), options );
173 for (
int i = 0; i < datasourceOptions.size(); i++ )
174 CPLFree( options[i] );
182 mErrorMessage = QObject::tr(
"creation of data source failed (OGR error:%1)" )
183 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
190 mCodec = QTextCodec::codecForName( fileEncoding.toLocal8Bit().data() );
194 QString enc = settings.value(
"/UI/encoding", QString(
"System" ) ).toString();
195 QgsDebugMsg(
"error finding QTextCodec for " + fileEncoding );
196 mCodec = QTextCodec::codecForName( enc.toLocal8Bit().data() );
199 QgsDebugMsg(
"error finding QTextCodec for " + enc );
200 mCodec = QTextCodec::codecForLocale();
205 OGRSpatialReferenceH ogrRef = NULL;
208 QString srsWkt = srs->
toWkt();
210 ogrRef = OSRNewSpatialReference( srsWkt.toLocal8Bit().data() );
214 QString layerName = QFileInfo( vectorFileName ).baseName();
215 OGRwkbGeometryType wkbType =
static_cast<OGRwkbGeometryType
>( geometryType );
217 if ( !layerOptions.isEmpty() )
219 options =
new char *[ layerOptions.size()+1 ];
220 for (
int i = 0; i < layerOptions.size(); i++ )
222 options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().data() );
224 options[ layerOptions.size()] = NULL;
227 mLayer = OGR_DS_CreateLayer(
mDS,
TO8F( layerName ), ogrRef, wkbType, options );
231 for (
int i = 0; i < layerOptions.size(); i++ )
232 CPLFree( options[i] );
239 if ( driverName ==
"ESRI Shapefile" )
241 QString layerName = vectorFileName.left( vectorFileName.indexOf(
".shp", Qt::CaseInsensitive ) );
242 QFile prjFile( layerName +
".qpj" );
243 if ( prjFile.open( QIODevice::WriteOnly ) )
245 QTextStream prjStream( &prjFile );
246 prjStream << srs->
toWkt().toLocal8Bit().data() << endl;
251 QgsDebugMsg(
"Couldn't open file " + layerName +
".qpj" );
255 OSRDestroySpatialReference( ogrRef );
260 mErrorMessage = QObject::tr(
"creation of layer failed (OGR error:%1)" )
261 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
266 OGRFeatureDefnH defn = OGR_L_GetLayerDefn(
mLayer );
271 QgsDebugMsg(
"creating " + QString::number( fields.size() ) +
" fields" );
276 QgsFieldMap::const_iterator fldIt;
277 for ( fldIt = fields.begin(); fldIt != fields.end(); ++fldIt )
279 const QgsField& attrField = fldIt.value();
281 OGRFieldType ogrType = OFTString;
282 int ogrWidth = fldIt->
length();
283 int ogrPrecision = fldIt->precision();
284 switch ( attrField.
type() )
286 case QVariant::LongLong:
288 ogrWidth = ogrWidth > 0 && ogrWidth <= 21 ? ogrWidth : 21;
292 case QVariant::String:
294 if ( ogrWidth < 0 || ogrWidth > 255 )
299 ogrType = OFTInteger;
300 ogrWidth = ogrWidth > 0 && ogrWidth <= 10 ? ogrWidth : 10;
304 case QVariant::Double:
310 mErrorMessage = QObject::tr(
"unsupported type for field %1" )
311 .arg( attrField.
name() );
317 OGRFieldDefnH fld = OGR_Fld_Create(
mCodec->fromUnicode( attrField.
name() ), ogrType );
320 OGR_Fld_SetWidth( fld, ogrWidth );
323 if ( ogrPrecision >= 0 )
325 OGR_Fld_SetPrecision( fld, ogrPrecision );
330 " type " + QString( QVariant::typeToName( attrField.
type() ) ) +
331 " width " + QString::number( ogrWidth ) +
332 " precision " + QString::number( ogrPrecision ) );
333 if ( OGR_L_CreateField(
mLayer, fld,
true ) != OGRERR_NONE )
336 mErrorMessage = QObject::tr(
"creation of field %1 failed (OGR error: %2)" )
337 .arg( attrField.
name() )
338 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
343 int ogrIdx = OGR_FD_GetFieldIndex( defn,
mCodec->fromUnicode( attrField.
name() ) );
346 #if defined(GDAL_VERSION_NUM) && GDAL_VERSION_NUM < 1700
349 int fieldCount = OGR_FD_GetFieldCount( defn );
351 OGRFieldDefnH fdefn = OGR_FD_GetFieldDefn( defn, fieldCount - 1 );
354 const char *fieldName = OGR_Fld_GetNameRef( fdefn );
356 if ( attrField.
name().left( strlen( fieldName ) ) == fieldName )
358 ogrIdx = fieldCount - 1;
363 ogrIdx = OGR_FD_GetFieldCount( defn ) - 1;
369 mErrorMessage = QObject::tr(
"created field %1 not found (OGR error: %2)" )
370 .arg( attrField.
name() )
371 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
392 return OGR_G_CreateGeometry(( OGRwkbGeometryType ) wkbType );
408 QgsAttributeMap::const_iterator it;
411 OGRFeatureH poFeature = OGR_F_Create( OGR_L_GetLayerDefn(
mLayer ) );
413 OGRErr err = OGR_F_SetFID( poFeature, feature.
id() );
414 if ( err != OGRERR_NONE )
416 QgsDebugMsg( QString(
"Failed to set feature id to %1: %2 (OGR error: %3)" )
418 .arg( err ).arg( CPLGetLastErrorMsg() )
423 QgsFieldMap::const_iterator fldIt;
428 QgsDebugMsg( QString(
"no attribute for field %1" ).arg( fldIt.key() ) );
434 QgsDebugMsg( QString(
"no ogr field for field %1" ).arg( fldIt.key() ) );
438 const QVariant& attrValue = feature.
attributeMap()[ fldIt.key()];
441 switch ( attrValue.type() )
444 OGR_F_SetFieldInteger( poFeature, ogrField, attrValue.toInt() );
446 case QVariant::Double:
447 OGR_F_SetFieldDouble( poFeature, ogrField, attrValue.toDouble() );
449 case QVariant::LongLong:
450 case QVariant::String:
451 OGR_F_SetFieldString( poFeature, ogrField,
mCodec->fromUnicode( attrValue.toString() ).data() );
453 case QVariant::Invalid:
456 mErrorMessage = QObject::tr(
"Invalid variant type for field %1[%2]: received %3 with type %4" )
457 .arg( fldIt.value().name() )
459 .arg( QMetaType::typeName( attrValue.type() ) )
460 .arg( attrValue.toString() );
486 QgsDebugMsg( QString(
"Failed to create empty geometry for type %1 (OGR error: %2)" ).arg( geom->
wkbType() ).arg( CPLGetLastErrorMsg() ) );
487 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
488 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
490 OGR_F_Destroy( poFeature );
494 OGRErr err = OGR_G_ImportFromWkb( mGeom2, geom->
asWkb(), geom->
wkbSize() );
495 if ( err != OGRERR_NONE )
497 QgsDebugMsg( QString(
"Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
498 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
499 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
501 OGR_F_Destroy( poFeature );
506 OGR_F_SetGeometryDirectly( poFeature, mGeom2 );
511 if ( err != OGRERR_NONE )
513 QgsDebugMsg( QString(
"Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
514 mErrorMessage = QObject::tr(
"Feature geometry not imported (OGR error: %1)" )
515 .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
517 OGR_F_Destroy( poFeature );
522 OGR_F_SetGeometry( poFeature,
mGeom );
527 if ( OGR_L_CreateFeature(
mLayer, poFeature ) != OGRERR_NONE )
529 mErrorMessage = QObject::tr(
"Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
533 OGR_F_Destroy( poFeature );
537 OGR_F_Destroy( poFeature );
546 OGR_G_DestroyGeometry(
mGeom );
551 OGR_DS_Destroy(
mDS );
560 const QString& shapefileName,
561 const QString& fileEncoding,
564 QString *errorMessage,
565 const QStringList &datasourceOptions,
566 const QStringList &layerOptions )
568 return writeAsVectorFormat( layer, shapefileName, fileEncoding, destCRS,
"ESRI Shapefile", onlySelected, errorMessage, datasourceOptions, layerOptions );
573 const QString& fileName,
574 const QString& fileEncoding,
576 const QString& driverName,
578 QString *errorMessage,
579 const QStringList &datasourceOptions,
580 const QStringList &layerOptions,
581 bool skipAttributeCreation )
585 int shallTransform =
false;
587 if ( destCRS && destCRS->
isValid() )
591 shallTransform =
true;
596 outputCRS = &layer->
crs();
613 errorMessage->clear();
632 shallTransform =
false;
635 int n = 0, errors = 0;
640 if ( onlySelected && !ids.contains( fet.
id() ) )
643 if ( shallTransform )
657 QString msg = QObject::tr(
"Failed to transform a point while drawing a feature of type '%1'. Writing stopped. (Exception: %2)" )
666 if ( skipAttributeCreation )
673 if ( err !=
NoError && errorMessage )
675 if ( errorMessage->isEmpty() )
677 *errorMessage = QObject::tr(
"Feature write errors:" );
687 *errorMessage += QObject::tr(
"Stopping after %1 errors" ).arg( errors );
699 if ( shallTransform )
704 if ( errors > 0 && errorMessage && n > 0 )
706 *errorMessage += QObject::tr(
"\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
715 QFileInfo fi( theFileName );
719 const char *suffixes[] = {
".shp",
".shx",
".dbf",
".prj",
".qix",
".qpj" };
720 for ( std::size_t i = 0; i <
sizeof( suffixes ) /
sizeof( *suffixes ); i++ )
722 filter << fi.completeBaseName() + suffixes[i];
726 foreach( QString file, dir.entryList( filter ) )
728 if ( !QFile::remove( dir.canonicalPath() +
"/" + file ) )
740 QMap<QString, QString> resultMap;
743 int const drvCount = OGRGetDriverCount();
745 for (
int i = 0; i < drvCount; ++i )
747 OGRSFDriverH drv = OGRGetDriver( i );
750 QString drvName = OGR_Dr_GetName( drv );
751 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
754 if ( filterString.isEmpty() )
757 resultMap.insert( filterString, drvName );
767 QMap<QString, QString> resultMap;
770 int const drvCount = OGRGetDriverCount();
772 for (
int i = 0; i < drvCount; ++i )
774 OGRSFDriverH drv = OGRGetDriver( i );
777 QString drvName = OGR_Dr_GetName( drv );
778 if ( OGR_Dr_TestCapability( drv,
"CreateDataSource" ) != 0 )
786 resultMap.insert( trLongName, drvName );
797 QString filterString;
799 QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
800 for ( ; it != driverFormatMap.constEnd(); ++it )
802 if ( filterString.isEmpty() )
803 filterString +=
";;";
805 filterString += it.key();
816 if ( !
driverMetadata( driverName, longName, trLongName, glob, exts ) || trLongName.isEmpty() || glob.isEmpty() )
819 return trLongName +
" [OGR] (" + glob.toLower() +
" " + glob.toUpper() +
")";
824 if ( driverName.startsWith(
"AVCE00" ) )
826 longName =
"Arc/Info ASCII Coverage";
827 trLongName = QObject::tr(
"Arc/Info ASCII Coverage" );
831 else if ( driverName.startsWith(
"BNA" ) )
833 longName =
"Atlas BNA";
834 trLongName = QObject::tr(
"Atlas BNA" );
838 else if ( driverName.startsWith(
"CSV" ) )
840 longName =
"Comma Separated Value";
841 trLongName = QObject::tr(
"Comma Separated Value" );
845 else if ( driverName.startsWith(
"ESRI" ) )
847 longName =
"ESRI Shapefile";
848 trLongName = QObject::tr(
"ESRI Shapefile" );
852 else if ( driverName.startsWith(
"FMEObjects Gateway" ) )
854 longName =
"FMEObjects Gateway";
855 trLongName = QObject::tr(
"FMEObjects Gateway" );
859 else if ( driverName.startsWith(
"GeoJSON" ) )
861 longName =
"GeoJSON";
862 trLongName = QObject::tr(
"GeoJSON" );
866 else if ( driverName.startsWith(
"GeoRSS" ) )
869 trLongName = QObject::tr(
"GeoRSS" );
873 else if ( driverName.startsWith(
"GML" ) )
875 longName =
"Geography Markup Language [GML]";
876 trLongName = QObject::tr(
"Geography Markup Language [GML]" );
880 else if ( driverName.startsWith(
"GMT" ) )
882 longName =
"Generic Mapping Tools [GMT]";
883 trLongName = QObject::tr(
"Generic Mapping Tools [GMT]" );
887 else if ( driverName.startsWith(
"GPX" ) )
889 longName =
"GPS eXchange Format [GPX]";
890 trLongName = QObject::tr(
"GPS eXchange Format [GPX]" );
894 else if ( driverName.startsWith(
"Interlis 1" ) )
896 longName =
"INTERLIS 1";
897 trLongName = QObject::tr(
"INTERLIS 1" );
898 glob =
"*.itf *.xml *.ili";
901 else if ( driverName.startsWith(
"Interlis 2" ) )
903 longName =
"INTERLIS 2";
904 trLongName = QObject::tr(
"INTERLIS 2" );
905 glob =
"*.itf *.xml *.ili";
908 else if ( driverName.startsWith(
"KML" ) )
910 longName =
"Keyhole Markup Language [KML]";
911 trLongName = QObject::tr(
"Keyhole Markup Language [KML]" );
915 else if ( driverName.startsWith(
"MapInfo File" ) )
917 longName =
"Mapinfo File";
918 trLongName = QObject::tr(
"Mapinfo File" );
919 glob =
"*.mif *.tab";
922 else if ( driverName.startsWith(
"DGN" ) )
924 longName =
"Microstation DGN";
925 trLongName = QObject::tr(
"Microstation DGN" );
929 else if ( driverName.startsWith(
"S57" ) )
931 longName =
"S-57 Base file";
932 trLongName = QObject::tr(
"S-57 Base file" );
936 else if ( driverName.startsWith(
"SDTS" ) )
938 longName =
"Spatial Data Transfer Standard [SDTS]";
939 trLongName = QObject::tr(
"Spatial Data Transfer Standard [SDTS]" );
943 else if ( driverName.startsWith(
"SQLite" ) )
946 trLongName = QObject::tr(
"SQLite" );
950 else if ( driverName.startsWith(
"DXF" ) )
952 longName =
"AutoCAD DXF";
953 trLongName = QObject::tr(
"AutoCAD DXF" );
957 else if ( driverName.startsWith(
"Geoconcept" ) )
959 longName =
"Geoconcept";
960 trLongName = QObject::tr(
"Geoconcept" );
961 glob =
"*.gxt *.txt";