[QGIS Commit] r14166 - in trunk/qgis: python/core
resources/context_help src/app src/app/ogr src/core src/ui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sat Aug 28 19:14:16 EDT 2010
Author: jef
Date: 2010-08-28 23:14:16 +0000 (Sat, 28 Aug 2010)
New Revision: 14166
Added:
trunk/qgis/resources/context_help/QgsVectorLayerSaveAsDialog-en_US
Modified:
trunk/qgis/python/core/qgsvectorfilewriter.sip
trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.cpp
trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.h
trunk/qgis/src/app/qgisapp.cpp
trunk/qgis/src/core/qgsvectorfilewriter.cpp
trunk/qgis/src/core/qgsvectorfilewriter.h
trunk/qgis/src/ui/qgsvectorlayersaveasdialogbase.ui
Log:
[FEATURE] add support for OGR creation options to and improve error handling of file writer
Modified: trunk/qgis/python/core/qgsvectorfilewriter.sip
===================================================================
--- trunk/qgis/python/core/qgsvectorfilewriter.sip 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/python/core/qgsvectorfilewriter.sip 2010-08-28 23:14:16 UTC (rev 14166)
@@ -29,7 +29,10 @@
const QString& shapefileName,
const QString& fileEncoding,
const QgsCoordinateReferenceSystem*,
- bool onlySelected = FALSE);
+ bool onlySelected = FALSE,
+ QString *errorMessage = 0,
+ const QStringList &datasourceOptions = QStringList(),
+ const QStringList &layerOptions = QStringList() );
/** Write contents of vector layer to an (OGR supported) vector formt
@note: this method was added in version 1.5*/
@@ -39,7 +42,9 @@
const QgsCoordinateReferenceSystem *destCRS,
const QString& driverName = "ESRI Shapefile",
bool onlySelected = FALSE,
- QString *errorMessage = 0 );
+ QString *errorMessage = 0,
+ const QStringList &datasourceOptions = QStringList(),
+ const QStringList &layerOptions = QStringList() );
/** create shapefile and initialize it */
QgsVectorFileWriter(const QString& vectorFileName,
@@ -47,7 +52,9 @@
const QMap<int, QgsField>& fields,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* srs,
- const QString& driverName = "ESRI Shapefile" );
+ const QString& driverName = "ESRI Shapefile",
+ const QStringList &datasourceOptions = QStringList(),
+ const QStringList &layerOptions = QStringList() );
/**Returns map with format filter string as key and OGR format key as value*/
static QMap< QString, QString> supportedFiltersAndFormats();
Added: trunk/qgis/resources/context_help/QgsVectorLayerSaveAsDialog-en_US
===================================================================
--- trunk/qgis/resources/context_help/QgsVectorLayerSaveAsDialog-en_US (rev 0)
+++ trunk/qgis/resources/context_help/QgsVectorLayerSaveAsDialog-en_US 2010-08-28 23:14:16 UTC (rev 14166)
@@ -0,0 +1,13 @@
+<h3>Save vector layer as...</h3>
+
+<p>This dialog allows you to save vector data in various formats using GDAL/OGR.
+
+<ul>
+<li>From the <label>Format</label> list you can select the destination format (as advertised by OGR).
+<li>At <label>Save as</label> you can enter a destination files name or select one using the <label>Browse</label> button.
+<li>In the <label>Encoding</label> list you can define in which encoding the data should be saved.
+<li>Using the <label>CRS</label> you can select a CRS into which the data about to be saved should be reprojected.
+<li>OGR also has various options for the different formats it supports. Use the <label>datasource</label> creation field to set the datasource options and the <label>layer</label> creation options. Enter one options per line (e.g. <code>SPATIALITE=yes</code> in the <label>datasource</label> to create a spatialite database using the SQLite driver).
+</ul>
+
+See <a href="http://gdal.org/ogr/ogr_formats.html">OGR Vector formats</a> for a list of supported formats and the available options.
Modified: trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.cpp
===================================================================
--- trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.cpp 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.cpp 2010-08-28 23:14:16 UTC (rev 14166)
@@ -137,3 +137,13 @@
{
return mCRS;
}
+
+QStringList QgsVectorLayerSaveAsDialog::datasourceOptions() const
+{
+ return mOgrDatasourceOptions->toPlainText().split( "\n" );
+}
+
+QStringList QgsVectorLayerSaveAsDialog::layerOptions() const
+{
+ return mOgrLayerOptions->toPlainText().split( "\n" );
+}
Modified: trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.h
===================================================================
--- trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.h 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/src/app/ogr/qgsvectorlayersaveasdialog.h 2010-08-28 23:14:16 UTC (rev 14166)
@@ -37,6 +37,8 @@
QString format() const;
QString encoding() const;
QString filename() const;
+ QStringList datasourceOptions() const;
+ QStringList layerOptions() const;
long crs() const;
private slots:
Modified: trunk/qgis/src/app/qgisapp.cpp
===================================================================
--- trunk/qgis/src/app/qgisapp.cpp 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/src/app/qgisapp.cpp 2010-08-28 23:14:16 UTC (rev 14166)
@@ -4000,7 +4000,11 @@
QgsVectorFileWriter::WriterError error;
QString errorMessage;
- error = QgsVectorFileWriter::writeAsVectorFormat( vlayer, vectorFilename, encoding, &destCRS, format, saveOnlySelection, &errorMessage );
+ error = QgsVectorFileWriter::writeAsVectorFormat(
+ vlayer, vectorFilename, encoding, &destCRS, format,
+ saveOnlySelection,
+ &errorMessage,
+ dialog->datasourceOptions(), dialog->layerOptions() );
QApplication::restoreOverrideCursor();
@@ -4010,7 +4014,10 @@
}
else
{
- QMessageBox::warning( 0, tr( "Save error" ), tr( "Export to vector file failed.\nError: %1" ).arg( errorMessage ) );
+ QgsMessageViewer *m = new QgsMessageViewer( 0 );
+ m->setWindowTitle( tr( "Save error" ) );
+ m->setMessageAsPlainText( tr( "Export to vector file failed.\nError: %1" ).arg( errorMessage ) );
+ m->exec();
}
}
Modified: trunk/qgis/src/core/qgsvectorfilewriter.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorfilewriter.cpp 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/src/core/qgsvectorfilewriter.cpp 2010-08-28 23:14:16 UTC (rev 14166)
@@ -40,6 +40,7 @@
#include <ogr_api.h>
#include <ogr_srs_api.h>
#include <cpl_error.h>
+#include <cpl_conv.h>
QgsVectorFileWriter::QgsVectorFileWriter(
@@ -48,7 +49,10 @@
const QgsFieldMap& fields,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* srs,
- const QString& driverName )
+ const QString& driverName,
+ const QStringList &datasourceOptions,
+ const QStringList &layerOptions
+)
: mDS( NULL )
, mLayer( NULL )
, mGeom( NULL )
@@ -116,8 +120,26 @@
QFile::remove( vectorFileName );
}
+ char **options = NULL;
+ if ( !datasourceOptions.isEmpty() )
+ {
+ options = new char *[ datasourceOptions.size()+1 ];
+ for ( int i = 0; i < datasourceOptions.size(); i++ )
+ {
+ options[i] = CPLStrdup( datasourceOptions[i].toLocal8Bit().data() );
+ }
+ options[ datasourceOptions.size()] = NULL;
+ }
+
// create the data source
- mDS = OGR_Dr_CreateDataSource( poDriver, vectorFileName.toLocal8Bit().data(), NULL );
+ mDS = OGR_Dr_CreateDataSource( poDriver, vectorFileName.toLocal8Bit().data(), options );
+
+ if ( options )
+ {
+ for ( int i = 0; i < datasourceOptions.size(); i++ )
+ CPLFree( options[i] );
+ }
+
if ( mDS == NULL )
{
mError = ErrCreateDataSource;
@@ -155,8 +177,25 @@
// datasource created, now create the output layer
QString layerName = QFileInfo( vectorFileName ).baseName();
OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>( geometryType );
- mLayer = OGR_DS_CreateLayer( mDS, QFile::encodeName( layerName ).data(), ogrRef, wkbType, NULL );
+ if ( !layerOptions.isEmpty() )
+ {
+ options = new char *[ layerOptions.size()+1 ];
+ for ( int i = 0; i < layerOptions.size(); i++ )
+ {
+ options[i] = CPLStrdup( layerOptions[i].toLocal8Bit().data() );
+ }
+ options[ layerOptions.size()] = NULL;
+ }
+
+ mLayer = OGR_DS_CreateLayer( mDS, QFile::encodeName( layerName ).data(), ogrRef, wkbType, options );
+
+ if ( options )
+ {
+ for ( int i = 0; i < layerOptions.size(); i++ )
+ CPLFree( options[i] );
+ }
+
if ( srs )
{
if ( driverName == "ESRI Shapefile" )
@@ -302,9 +341,6 @@
bool QgsVectorFileWriter::addFeature( QgsFeature& feature )
{
- if ( hasError() != NoError )
- return false;
-
QgsAttributeMap::const_iterator it;
// create the feature
@@ -342,10 +378,13 @@
OGR_F_SetFieldString( poFeature, ogrField, mCodec->fromUnicode( attrValue.toString() ).data() );
break;
default:
- QgsDebugMsg( "Invalid variant type for field " + QString( fldIt.value().name() ) + " "
- + QString::number( ogrField ) + ": Received Type " + QMetaType::typeName ( attrValue.type() )
- + " : With Value : " + attrValue.toString()
- );
+ mErrorMessage = QObject::tr( "Invalid variant type for field %1[%2]: received %3 with type %4" )
+ .arg( fldIt.value().name() )
+ .arg( ogrField )
+ .arg( QMetaType::typeName( attrValue.type() ) )
+ .arg( attrValue.toString() );
+ QgsDebugMsg( mErrorMessage );
+ mError = ErrFeatureWriteFailed;
return false;
}
}
@@ -355,6 +394,8 @@
if ( !geom )
{
QgsDebugMsg( "invalid geometry" );
+ mErrorMessage = QObject::tr( "Invalid feature geometry" );
+ mError = ErrFeatureWriteFailed;
OGR_F_Destroy( poFeature );
return false;
}
@@ -375,7 +416,10 @@
OGRErr err = OGR_G_ImportFromWkb( mGeom2, geom->asWkb(), geom->wkbSize() );
if ( err != OGRERR_NONE )
{
- QgsDebugMsg( "Failed to import geometry from WKB: " + QString::number( err ) );
+ QgsDebugMsg( QString( "Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
+ mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
+ .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
+ mError = ErrFeatureWriteFailed;
OGR_F_Destroy( poFeature );
return false;
}
@@ -388,7 +432,10 @@
OGRErr err = OGR_G_ImportFromWkb( mGeom, geom->asWkb(), geom->wkbSize() );
if ( err != OGRERR_NONE )
{
- QgsDebugMsg( "Failed to import geometry from WKB: " + QString::number( err ) );
+ QgsDebugMsg( QString( "Failed to import geometry from WKB: %1 (OGR error: %2)" ).arg( err ).arg( CPLGetLastErrorMsg() ) );
+ mErrorMessage = QObject::tr( "Feature geometry not imported (OGR error: %1)" )
+ .arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
+ mError = ErrFeatureWriteFailed;
OGR_F_Destroy( poFeature );
return false;
}
@@ -400,7 +447,10 @@
// put the created feature to layer
if ( OGR_L_CreateFeature( mLayer, poFeature ) != OGRERR_NONE )
{
- QgsDebugMsg( "Failed to create feature in shapefile" );
+ mErrorMessage = QObject::tr( "Feature creation error (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) );
+ mError = ErrFeatureWriteFailed;
+
+ QgsDebugMsg( mErrorMessage );
OGR_F_Destroy( poFeature );
return false;
}
@@ -432,9 +482,11 @@
const QString& fileEncoding,
const QgsCoordinateReferenceSystem* destCRS,
bool onlySelected,
- QString *errorMessage )
+ QString *errorMessage,
+ const QStringList &datasourceOptions,
+ const QStringList &layerOptions )
{
- return writeAsVectorFormat( layer, shapefileName, fileEncoding, destCRS, "ESRI Shapefile", onlySelected, errorMessage );
+ return writeAsVectorFormat( layer, shapefileName, fileEncoding, destCRS, "ESRI Shapefile", onlySelected, errorMessage, datasourceOptions, layerOptions );
}
QgsVectorFileWriter::WriterError
@@ -444,7 +496,9 @@
const QgsCoordinateReferenceSystem *destCRS,
const QString& driverName,
bool onlySelected,
- QString *errorMessage )
+ QString *errorMessage,
+ const QStringList &datasourceOptions,
+ const QStringList &layerOptions )
{
const QgsCoordinateReferenceSystem* outputCRS;
QgsCoordinateTransform* ct = 0;
@@ -462,7 +516,7 @@
outputCRS = &layer->srs();
}
QgsVectorFileWriter* writer =
- new QgsVectorFileWriter( fileName, fileEncoding, layer->pendingFields(), layer->wkbType(), outputCRS, driverName );
+ new QgsVectorFileWriter( fileName, fileEncoding, layer->pendingFields(), layer->wkbType(), outputCRS, driverName, datasourceOptions, layerOptions );
// check whether file creation was successful
WriterError err = writer->hasError();
@@ -474,6 +528,11 @@
return err;
}
+ if ( errorMessage )
+ {
+ errorMessage->clear();
+ }
+
QgsAttributeList allAttr = layer->pendingAllAttributesList();
QgsFeature fet;
@@ -493,6 +552,8 @@
shallTransform = false;
}
+ int n = 0, errors = 0;
+
// write all features
while ( layer->nextFeature( fet ) )
{
@@ -519,7 +580,31 @@
return ErrProjection;
}
}
- writer->addFeature( fet );
+ if ( !writer->addFeature( fet ) )
+ {
+ WriterError err = writer->hasError();
+ if ( err != NoError && errorMessage )
+ {
+ if ( errorMessage->isEmpty() )
+ {
+ *errorMessage = QObject::tr( "Feature write errors:" );
+ }
+ *errorMessage += "\n" + writer->errorMessage();
+ }
+ errors++;
+
+ if ( errors > 1000 )
+ {
+ if ( errorMessage )
+ {
+ *errorMessage += QObject::tr( "Stopping after %1 errors" ).arg( errors );
+ }
+
+ n = -1;
+ break;
+ }
+ }
+ n++;
}
delete writer;
@@ -529,7 +614,12 @@
delete ct;
}
- return NoError;
+ if ( errors > 0 && errorMessage && n > 0 )
+ {
+ *errorMessage += QObject::tr( "\nOnly %1 of %2 features written." ).arg( n - errors ).arg( n );
+ }
+
+ return errors == 0 ? NoError : ErrFeatureWriteFailed;
}
Modified: trunk/qgis/src/core/qgsvectorfilewriter.h
===================================================================
--- trunk/qgis/src/core/qgsvectorfilewriter.h 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/src/core/qgsvectorfilewriter.h 2010-08-28 23:14:16 UTC (rev 14166)
@@ -52,7 +52,8 @@
ErrCreateLayer,
ErrAttributeTypeUnsupported,
ErrAttributeCreationFailed,
- ErrProjection // added in 1.5
+ ErrProjection, // added in 1.5
+ ErrFeatureWriteFailed, // added in 1.6
};
/** Write contents of vector layer to a shapefile
@@ -62,7 +63,10 @@
const QString& fileEncoding,
const QgsCoordinateReferenceSystem *destCRS,
bool onlySelected = false,
- QString *errorMessage = 0 );
+ QString *errorMessage = 0,
+ const QStringList &datasourceOptions = QStringList(), // added in 1.6
+ const QStringList &layerOptions = QStringList() // added in 1.6
+ );
/** Write contents of vector layer to an (OGR supported) vector formt
@note: this method was added in version 1.5*/
@@ -72,7 +76,10 @@
const QgsCoordinateReferenceSystem *destCRS,
const QString& driverName = "ESRI Shapefile",
bool onlySelected = false,
- QString *errorMessage = 0 );
+ QString *errorMessage = 0,
+ const QStringList &datasourceOptions = QStringList(), // added in 1.6
+ const QStringList &layerOptions = QStringList() // added in 1.6
+ );
/** create shapefile and initialize it */
QgsVectorFileWriter( const QString& vectorFileName,
@@ -80,7 +87,10 @@
const QgsFieldMap& fields,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* srs,
- const QString& driverName = "ESRI Shapefile" );
+ const QString& driverName = "ESRI Shapefile",
+ const QStringList &datasourceOptions = QStringList(), // added in 1.6
+ const QStringList &layerOptions = QStringList() // added in 1.6
+ );
/**Returns map with format filter string as key and OGR format key as value*/
static QMap< QString, QString> supportedFiltersAndFormats();
Modified: trunk/qgis/src/ui/qgsvectorlayersaveasdialogbase.ui
===================================================================
--- trunk/qgis/src/ui/qgsvectorlayersaveasdialogbase.ui 2010-08-28 22:35:41 UTC (rev 14165)
+++ trunk/qgis/src/ui/qgsvectorlayersaveasdialogbase.ui 2010-08-28 23:14:16 UTC (rev 14166)
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>203</height>
+ <width>383</width>
+ <height>348</height>
</rect>
</property>
<property name="windowTitle">
@@ -38,7 +38,7 @@
</property>
</widget>
</item>
- <item row="6" column="0" colspan="3">
+ <item row="7" column="0" colspan="3">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -101,6 +101,41 @@
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="mFormatComboBox"/>
</item>
+ <item row="6" column="0" colspan="3">
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>OGR creation options</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="1">
+ <widget class="QTextEdit" name="mOgrDatasourceOptions"/>
+ </item>
+ <item row="1" column="1">
+ <widget class="QTextEdit" name="mOgrLayerOptions"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Data source</string>
+ </property>
+ <property name="buddy">
+ <cstring>mOgrDatasourceOptions</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Layer</string>
+ </property>
+ <property name="buddy">
+ <cstring>mOgrLayerOptions</cstring>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
<tabstops>
@@ -121,8 +156,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
- <x>257</x>
- <y>181</y>
+ <x>266</x>
+ <y>268</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@@ -137,8 +172,8 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
- <x>325</x>
- <y>181</y>
+ <x>334</x>
+ <y>268</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
More information about the QGIS-commit
mailing list