[QGIS Commit] r13072 - in trunk/qgis: python/core src/app/legend
src/core
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Thu Mar 18 18:24:19 EDT 2010
Author: mhugent
Date: 2010-03-18 18:24:18 -0400 (Thu, 18 Mar 2010)
New Revision: 13072
Modified:
trunk/qgis/python/core/qgsvectorfilewriter.sip
trunk/qgis/src/app/legend/qgslegendlayer.cpp
trunk/qgis/src/app/legend/qgslegendlayer.h
trunk/qgis/src/core/qgsvectorfilewriter.cpp
trunk/qgis/src/core/qgsvectorfilewriter.h
Log:
Apply patch #2452 (save as vector)
Modified: trunk/qgis/python/core/qgsvectorfilewriter.sip
===================================================================
--- trunk/qgis/python/core/qgsvectorfilewriter.sip 2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/python/core/qgsvectorfilewriter.sip 2010-03-18 22:24:18 UTC (rev 13072)
@@ -31,13 +31,32 @@
const QgsCoordinateReferenceSystem*,
bool onlySelected = FALSE);
+ /** Write contents of vector layer to an (OGR supported) vector formt
+ @note: this method was added in version 1.5*/
+ static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
+ const QString& fileName,
+ const QString& fileEncoding,
+ const QgsCoordinateReferenceSystem *destCRS,
+ const QString& driverName = "ESRI Shapefile",
+ bool onlySelected = FALSE,
+ QString *errorMessage = 0 );
+
/** create shapefile and initialize it */
- QgsVectorFileWriter(const QString& shapefileName,
+ QgsVectorFileWriter(const QString& vectorFileName,
const QString& fileEncoding,
const QMap<int, QgsField>& fields,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* srs,
const QString& driverName = "ESRI Shapefile" );
+
+ /**Returns map with format filter string as key and OGR format key as value*/
+ static QMap< QString, QString> supportedFiltersAndFormats();
+
+ /**Returns filter string that can be used for dialogs*/
+ static QString fileFilterString();
+
+ /**Creates a filter for an OGR driver key*/
+ static QString filterForDriver( const QString& driverName );
/** checks whether there were any errors in constructor */
WriterError hasError();
Modified: trunk/qgis/src/app/legend/qgslegendlayer.cpp
===================================================================
--- trunk/qgis/src/app/legend/qgslegendlayer.cpp 2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/app/legend/qgslegendlayer.cpp 2010-03-18 22:24:18 UTC (rev 13072)
@@ -423,14 +423,14 @@
}
}
- // save as shapefile
- theMenu.addAction( tr( "Save as shapefile..." ), this, SLOT( saveAsShapefile() ) );
+ // save as vector file
+ theMenu.addAction( tr( "Save as..." ), this, SLOT( saveAsVectorFile() ) );
- // save selection as shapefile
- QAction* saveSelectionAction = theMenu.addAction( tr( "Save selection as shapefile..." ), this, SLOT( saveSelectionAsShapefile() ) );
+ // save selection as vector file
+ QAction* saveSelectionAsAction = theMenu.addAction( tr( "Save selection as..." ), this, SLOT( saveSelectionAsVectorFile() ) );
if ( vlayer->selectedFeatureCount() == 0 )
{
- saveSelectionAction->setEnabled( false );
+ saveSelectionAsAction->setEnabled( false );
}
theMenu.addSeparator();
@@ -460,6 +460,16 @@
saveAsShapefileGeneral( TRUE );
}
+void QgsLegendLayer::saveAsVectorFile()
+{
+ saveAsVectorFileGeneral( false );
+}
+
+void QgsLegendLayer::saveSelectionAsVectorFile()
+{
+ saveAsVectorFileGeneral( true );
+}
+
//////////
void QgsLegendLayer::setVisible( bool visible )
@@ -492,9 +502,83 @@
legend()->updateOverview();
}
+void QgsLegendLayer::saveAsVectorFileGeneral( bool saveOnlySelection )
+{
+ if ( mLyr.layer()->type() != QgsMapLayer::VectorLayer )
+ return;
+ QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mLyr.layer() );
+ //get output name and format
+ QSettings settings;
+ QString filter = QString( "Shapefiles (*.shp)" );
+ QString dirName = settings.value( "/UI/lastVectorfileDir", "." ).toString();
+ QString filterString = QgsVectorFileWriter::fileFilterString();
+ QString selectedFilter = settings.value( "/UI/lastVectorFilter", "[OGR] ESRI Shapefiles (*.shp *.SHP)" ).toString();
+ QString outputFile = QFileDialog::getSaveFileName( 0, tr( "Save layer as..." ), dirName, filterString, &selectedFilter );
+ if ( outputFile.isNull() )
+ {
+ return; //cancelled
+ }
+ settings.setValue( "/UI/lastVectorfileDir", QFileInfo( outputFile ).absolutePath() );
+ settings.setValue( "/UI/lastVectorFilter", selectedFilter );
+
+ QMap< QString, QString> filterDriverMap = QgsVectorFileWriter::supportedFiltersAndFormats();
+ QMap< QString, QString>::const_iterator it = filterDriverMap.find( selectedFilter + ";;" );
+ if ( it == filterDriverMap.constEnd() )
+ {
+ return; //unknown format
+ }
+
+ QString driverKey = *it;
+
+ //output CRS
+ QgsCoordinateReferenceSystem destCRS = vlayer->srs();
+ // Find out if we have projections enabled or not
+ if ( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() )
+ {
+ destCRS = QgisApp::instance()->mapCanvas()->mapRenderer()->destinationSrs();
+ }
+
+ QgsGenericProjectionSelector * mySelector = new QgsGenericProjectionSelector();
+ mySelector->setSelectedCrsId( destCRS.srsid() );
+ mySelector->setMessage( tr( "Select the coordinate reference system for the saved shapefile. "
+ "The data points will be transformed from the layer coordinate reference system." ) );
+
+ if ( mySelector->exec() )
+ {
+ QgsCoordinateReferenceSystem srs( mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::InternalCrsId );
+ destCRS = srs;
+ // destCRS->createFromId(mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::InternalCrsId)
+ }
+ else
+ {
+ // Aborted CS selection, don't save.
+ delete mySelector;
+ return;
+ }
+ delete mySelector;
+
+ // overwrite the file - user will already have been prompted
+ // to verify they want to overwrite by the file dialog above
+ // might not even exists in the given case.
+ if ( driverKey == "ESRI Shapefile" )
+ {
+ // add the extension if not present
+ if ( !outputFile.endsWith( ".shp", Qt::CaseInsensitive ) )
+ {
+ outputFile += ".shp";
+ }
+ QgsVectorFileWriter::deleteShapeFile( outputFile );
+ }
+
+ QString errorMessage;
+ QgsVectorFileWriter::WriterError error;
+ error = QgsVectorFileWriter::writeAsVectorFormat( vlayer, outputFile, "utf-8", &destCRS, driverKey, saveOnlySelection, &errorMessage );
+}
+
+
void QgsLegendLayer::saveAsShapefileGeneral( bool saveOnlySelection )
{
QgsCoordinateReferenceSystem destCRS;
Modified: trunk/qgis/src/app/legend/qgslegendlayer.h
===================================================================
--- trunk/qgis/src/app/legend/qgslegendlayer.h 2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/app/legend/qgslegendlayer.h 2010-03-18 22:24:18 UTC (rev 13072)
@@ -87,6 +87,9 @@
void saveAsShapefile();
void saveSelectionAsShapefile();
+ void saveAsVectorFile();
+ void saveSelectionAsVectorFile();
+
/**update the layer's icon to show whether is in editing mode or in overview */
void updateIcon();
@@ -111,6 +114,8 @@
/**Save as shapefile (called from saveAsShapefile and saveSelectionAsShapefile)*/
void saveAsShapefileGeneral( bool saveOnlySelection );
+ void saveAsVectorFileGeneral( bool saveOnlySelection );
+
private:
/** Helper method to make the font bold from all ctors.
* Not to be confused with setFont() which is inherited
Modified: trunk/qgis/src/core/qgsvectorfilewriter.cpp
===================================================================
--- trunk/qgis/src/core/qgsvectorfilewriter.cpp 2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/core/qgsvectorfilewriter.cpp 2010-03-18 22:24:18 UTC (rev 13072)
@@ -41,7 +41,7 @@
#include <cpl_error.h>
-QgsVectorFileWriter::QgsVectorFileWriter( const QString& shapefileName,
+QgsVectorFileWriter::QgsVectorFileWriter( const QString& vectorFileName,
const QString& fileEncoding,
const QgsFieldMap& fields,
QGis::WkbType geometryType,
@@ -85,7 +85,7 @@
}
// create the data source
- mDS = OGR_Dr_CreateDataSource( poDriver, shapefileName.toLocal8Bit().data(), NULL );
+ mDS = OGR_Dr_CreateDataSource( poDriver, vectorFileName.toLocal8Bit().data(), NULL );
if ( mDS == NULL )
{
mError = ErrCreateDataSource;
@@ -121,7 +121,7 @@
}
// datasource created, now create the output layer
- QString layerName = shapefileName.left( shapefileName.indexOf( ".shp", Qt::CaseInsensitive ) );
+ QString layerName = QFileInfo( vectorFileName ).baseName();
OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>( geometryType );
mLayer = OGR_DS_CreateLayer( mDS, QFile::encodeName( layerName ).data(), ogrRef, wkbType, NULL );
@@ -386,7 +386,8 @@
bool onlySelected,
QString *errorMessage )
{
-
+ return writeAsVectorFormat( layer, shapefileName, fileEncoding, destCRS, "ESRI Shapefile", onlySelected, errorMessage );
+#if 0
const QgsCoordinateReferenceSystem* outputCRS;
QgsCoordinateTransform* ct = 0;
int shallTransform = false;
@@ -471,9 +472,105 @@
}
return NoError;
+#endif //0
}
+QgsVectorFileWriter::WriterError
+QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
+ const QString& fileName,
+ const QString& fileEncoding,
+ const QgsCoordinateReferenceSystem *destCRS,
+ const QString& driverName,
+ bool onlySelected,
+ QString *errorMessage )
+{
+ const QgsCoordinateReferenceSystem* outputCRS;
+ QgsCoordinateTransform* ct = 0;
+ int shallTransform = false;
+ if ( destCRS && destCRS->isValid() )
+ {
+ // This means we should transform
+ outputCRS = destCRS;
+ shallTransform = true;
+ }
+ else
+ {
+ // This means we shouldn't transform, use source CRS as output (if defined)
+ outputCRS = &layer->srs();
+ }
+ QgsVectorFileWriter* writer =
+ new QgsVectorFileWriter( fileName, fileEncoding, layer->pendingFields(), layer->wkbType(), outputCRS, driverName );
+
+ // check whether file creation was successful
+ WriterError err = writer->hasError();
+ if ( err != NoError )
+ {
+ if ( errorMessage )
+ *errorMessage = writer->errorMessage();
+ delete writer;
+ return err;
+ }
+
+ QgsAttributeList allAttr = layer->pendingAllAttributesList();
+ QgsFeature fet;
+
+ layer->select( allAttr, QgsRectangle(), true );
+
+ const QgsFeatureIds& ids = layer->selectedFeaturesIds();
+
+ // Create our transform
+ if ( destCRS )
+ {
+ ct = new QgsCoordinateTransform( layer->srs(), *destCRS );
+ }
+
+ // Check for failure
+ if ( ct == NULL )
+ {
+ shallTransform = false;
+ }
+
+ // write all features
+ while ( layer->nextFeature( fet ) )
+ {
+ if ( onlySelected && !ids.contains( fet.id() ) )
+ continue;
+
+ if ( shallTransform )
+ {
+ try
+ {
+ fet.geometry()->transform( *ct );
+ }
+ catch ( QgsCsException &e )
+ {
+ delete ct;
+ delete writer;
+
+ QString msg = QObject::tr( "Failed to transform a point while drawing a feature of type '%1'. Writing stopped. (Exception: %2)" )
+ .arg( fet.typeName() ).arg( e.what() );
+ QgsLogger::warning( msg );
+ if ( errorMessage )
+ *errorMessage = msg;
+
+ return ErrProjection;
+ }
+ }
+ writer->addFeature( fet );
+ }
+
+ delete writer;
+
+ if ( shallTransform )
+ {
+ delete ct;
+ }
+
+ return NoError;
+}
+
+
bool QgsVectorFileWriter::deleteShapeFile( QString theFileName )
{
QFileInfo fi( theFileName );
@@ -498,3 +595,157 @@
return ok;
}
+
+QMap< QString, QString> QgsVectorFileWriter::supportedFiltersAndFormats()
+{
+ QMap<QString, QString> resultMap;
+
+ QgsApplication::registerOgrDrivers();
+ int const drvCount = OGRGetDriverCount();
+
+ QString drvName;
+ QString filterString;
+ for ( int i = 0; i < drvCount; ++i )
+ {
+ OGRSFDriverH drv = OGRGetDriver( i );
+ if ( drv )
+ {
+ drvName = OGR_Dr_GetName( drv );
+ if ( OGR_Dr_TestCapability( drv, ODrCCreateDataSource ) != 0 )
+ {
+ //add driver name and filter to map
+ filterString = QgsVectorFileWriter::filterForDriver( drvName );
+ if ( !filterString.isEmpty() )
+ {
+ resultMap.insert( filterString, drvName );
+ }
+ }
+ }
+ }
+
+ return resultMap;
+}
+
+QString QgsVectorFileWriter::fileFilterString()
+{
+ QString filterString;
+ QMap< QString, QString> driverFormatMap = QgsVectorFileWriter::supportedFiltersAndFormats();
+ QMap< QString, QString>::const_iterator it = driverFormatMap.constBegin();
+ for ( ; it != driverFormatMap.constEnd(); ++it )
+ {
+ filterString += it.key();
+ }
+ return filterString;
+}
+
+QString QgsVectorFileWriter::filterForDriver( const QString& driverName )
+{
+ QString longName;
+ QString glob;
+
+ if ( driverName.startsWith( "AVCE00" ) )
+ {
+ longName = "Arc/Info ASCII Coverage";
+ glob = "*.e00";
+ }
+ else if ( driverName.startsWith( "BNA" ) )
+ {
+ longName = "Atlas BNA";
+ glob = "*.bna";
+ }
+ else if ( driverName.startsWith( "CSV" ) )
+ {
+ longName = "Comma Separated Value";
+ glob = "*.csv";
+ }
+ else if ( driverName.startsWith( "ESRI" ) )
+ {
+ longName = "ESRI Shapefiles";
+ glob = "*.shp";
+ }
+ else if ( driverName.startsWith( "FMEObjects Gateway" ) )
+ {
+ longName = "FMEObjects Gateway";
+ glob = "*.fdd";
+ }
+ else if ( driverName.startsWith( "GeoJSON" ) )
+ {
+ longName = "GeoJSON";
+ glob = "*.geojson";
+ }
+ else if ( driverName.startsWith( "GeoRSS" ) )
+ {
+ longName = "GeoRSS";
+ glob = "*.xml";
+ }
+ else if ( driverName.startsWith( "GML" ) )
+ {
+ longName = "Geography Markup Language";
+ glob = "*.gml";
+ }
+ else if ( driverName.startsWith( "GMT" ) )
+ {
+ longName = "GMT";
+ glob = "*.gmt";
+ }
+ else if ( driverName.startsWith( "GPX" ) )
+ {
+ longName = "GPX";
+ glob = "*.gpx";
+ }
+ else if ( driverName.startsWith( "Interlis 1" ) )
+ {
+ longName = "INTERLIS 1";
+ glob = "*.itf *.xml *.ili";
+ }
+ else if ( driverName.startsWith( "Interlis 2" ) )
+ {
+ longName = "INTERLIS 2";
+ glob = "*.itf *.xml *.ili";
+ }
+ else if ( driverName.startsWith( "KML" ) )
+ {
+ longName = "KML";
+ glob = "*.kml" ;
+ }
+ else if ( driverName.startsWith( "MapInfo File" ) )
+ {
+ longName = "Mapinfo File";
+ glob = "*.mif *.tab";
+ }
+ else if ( driverName.startsWith( "DGN" ) )
+ {
+ longName = "Microstation DGN";
+ glob = "*.dgn";
+ }
+ else if ( driverName.startsWith( "S57" ) )
+ {
+ longName = "S-57 Base file";
+ glob = "*.000";
+ }
+ else if ( driverName.startsWith( "SDTS" ) )
+ {
+ longName = "Spatial Data Transfer Standard";
+ glob = "*catd.ddf";
+ }
+ else if ( driverName.startsWith( "SQLite" ) )
+ {
+ longName = "SQLite";
+ glob = "*.sqlite";
+ }
+ else if ( driverName.startsWith( "VRT" ) )
+ {
+ longName = "VRT - Virtual Datasource ";
+ glob = "*.vrt";
+ }
+ else if ( driverName.startsWith( "XPlane" ) )
+ {
+ longName = "X-Plane/Flighgear";
+ glob = "apt.dat nav.dat fix.dat awy.dat";
+ }
+ else
+ {
+ return QString();
+ }
+ return "[OGR] " + longName + " (" + glob.toLower() + " " + glob.toUpper() + ");;";
+}
Modified: trunk/qgis/src/core/qgsvectorfilewriter.h
===================================================================
--- trunk/qgis/src/core/qgsvectorfilewriter.h 2010-03-18 18:12:04 UTC (rev 13071)
+++ trunk/qgis/src/core/qgsvectorfilewriter.h 2010-03-18 22:24:18 UTC (rev 13072)
@@ -53,7 +53,8 @@
ErrProjection // added in 1.5
};
- /** Write contents of vector layer to a shapefile */
+ /** Write contents of vector layer to a shapefile
+ @note: deprecated. Use writeAsVectorFormat instead*/
static WriterError writeAsShapefile( QgsVectorLayer* layer,
const QString& shapefileName,
const QString& fileEncoding,
@@ -61,14 +62,33 @@
bool onlySelected = FALSE,
QString *errorMessage = 0 );
+ /** Write contents of vector layer to an (OGR supported) vector formt
+ @note: this method was added in version 1.5*/
+ static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
+ const QString& fileName,
+ const QString& fileEncoding,
+ const QgsCoordinateReferenceSystem *destCRS,
+ const QString& driverName = "ESRI Shapefile",
+ bool onlySelected = FALSE,
+ QString *errorMessage = 0 );
+
/** create shapefile and initialize it */
- QgsVectorFileWriter( const QString& shapefileName,
+ QgsVectorFileWriter( const QString& vectorFileName,
const QString& fileEncoding,
const QgsFieldMap& fields,
QGis::WkbType geometryType,
const QgsCoordinateReferenceSystem* srs,
const QString& driverName = "ESRI Shapefile" );
+ /**Returns map with format filter string as key and OGR format key as value*/
+ static QMap< QString, QString> supportedFiltersAndFormats();
+
+ /**Returns filter string that can be used for dialogs*/
+ static QString fileFilterString();
+
+ /**Creates a filter for an OGR driver key*/
+ static QString filterForDriver( const QString& driverName );
+
/** checks whether there were any errors in constructor */
WriterError hasError();
More information about the QGIS-commit
mailing list