Skip to content

Commit

Permalink
[FEATURE] allow saving vector layers as ogr vector files
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@13169 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
jef committed Mar 27, 2010
1 parent cc841bc commit 9ec2e42
Show file tree
Hide file tree
Showing 19 changed files with 538 additions and 578 deletions.
3 changes: 3 additions & 0 deletions python/core/qgsvectordataprovider.sip
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,7 @@ class QgsVectorDataProvider : QgsDataProvider
(e.g. no multipolygon in a polygon layer)
@note: added in version 1.4*/
bool doesStrictFeatureTypeCheck() const;

/** Returns a list of available encodings */
static const QStringList &availableEncodings();
};
2 changes: 2 additions & 0 deletions src/app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ SET(QGIS_APP_SRCS
ogr/qgsopenvectorlayerdialog.cpp
ogr/qgsnewogrconnection.cpp
ogr/qgsogrsublayersdialog.cpp
ogr/qgsvectorlayersaveasdialog.cpp

attributetable/qgsattributetabledialog.cpp
attributetable/qgsattributetablemodel.cpp
Expand Down Expand Up @@ -199,6 +200,7 @@ SET (QGIS_APP_MOC_HDRS
ogr/qgsopenvectorlayerdialog.h
ogr/qgsnewogrconnection.h
ogr/qgsogrsublayersdialog.h
ogr/qgsvectorlayersaveasdialog.h

attributetable/qgsattributetableview.h
attributetable/qgsattributetablemodel.h
Expand Down
221 changes: 54 additions & 167 deletions src/app/legend/qgslegendlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "qgsvectorfilewriter.h"
#include "qgsgenericprojectionselector.h"
#include "qgsattributetabledialog.h"
#include "qgsencodingfiledialog.h"
#include "ogr/qgsvectorlayersaveasdialog.h"

#include "qgsrendererv2.h"
#include "qgssymbolv2.h"
Expand All @@ -53,6 +53,7 @@
#include <QMessageBox>
#include <QPainter>
#include <QSettings>
#include <QFileDialog>


QgsLegendLayer::QgsLegendLayer( QgsMapLayer* layer )
Expand Down Expand Up @@ -450,16 +451,6 @@ void QgsLegendLayer::table()
// the dialog will be deleted by itself on close
}

void QgsLegendLayer::saveAsShapefile()
{
saveAsShapefileGeneral( FALSE );
}

void QgsLegendLayer::saveSelectionAsShapefile()
{
saveAsShapefileGeneral( TRUE );
}

void QgsLegendLayer::saveAsVectorFile()
{
saveAsVectorFileGeneral( false );
Expand Down Expand Up @@ -504,177 +495,73 @@ void QgsLegendLayer::showInOverview()

void QgsLegendLayer::saveAsVectorFileGeneral( bool saveOnlySelection )
{
QgsCoordinateReferenceSystem destCRS;

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 );
QgsVectorLayerSaveAsDialog *dialog = new QgsVectorLayerSaveAsDialog( QgisApp::instance() );

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
if( dialog->exec() == QDialog::Accepted )
{
// Aborted CS selection, don't save.
delete mySelector;
return;
}
delete mySelector;
QString encoding = dialog->encoding();
QString vectorFilename = dialog->filename();
QString format = dialog->format();

if( dialog->crs() < 0 )
{
// Find out if we have projections enabled or not
if ( QgisApp::instance()->mapCanvas()->mapRenderer()->hasCrsTransformEnabled() )
{
destCRS = QgisApp::instance()->mapCanvas()->mapRenderer()->destinationSrs();
}
else
{
destCRS = vlayer->srs();
}
}
else
{
destCRS = QgsCoordinateReferenceSystem( dialog->crs(), QgsCoordinateReferenceSystem::InternalCrsId );
}

// 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" )
{
// 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.
// add the extension if not present
if ( !outputFile.endsWith( ".shp", Qt::CaseInsensitive ) )
if( format == "ESRI Shapefile" )
{
outputFile += ".shp";
if ( !vectorFilename.endsWith( ".shp", Qt::CaseInsensitive ) )
{
vectorFilename += ".shp";
}
QgsVectorFileWriter::deleteShapeFile( vectorFilename );
}

// ok if the file existed it should be deleted now so we can continue...
QApplication::setOverrideCursor( Qt::WaitCursor );

QgsVectorFileWriter::WriterError error;
QString errorMessage;
error = QgsVectorFileWriter::writeAsVectorFormat( vlayer, vectorFilename, encoding, &destCRS, format, saveOnlySelection, &errorMessage );

QApplication::restoreOverrideCursor();

if ( error == QgsVectorFileWriter::NoError )
{
QMessageBox::information( 0, tr( "Saving done" ), tr( "Export to vector file has been completed" ) );
}
else
{
QMessageBox::warning( 0, tr( "Save error" ), tr( "Export to vector file failed.\nError: %1").arg( errorMessage ) );
}
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;

if ( mLyr.layer()->type() != QgsMapLayer::VectorLayer )
return;

QgsVectorLayer* vlayer = qobject_cast<QgsVectorLayer *>( mLyr.layer() );

// get a name for the shapefile
// Get a file to process, starting at the current directory
QSettings settings;
QString filter = QString( "Shapefiles (*.shp)" );
QString dirName = settings.value( "/UI/lastShapefileDir", "." ).toString();

QgsEncodingFileDialog* openFileDialog = new QgsEncodingFileDialog( 0,
tr( "Save layer as..." ),
dirName,
filter,
QString( "" ) );
openFileDialog->setAcceptMode( QFileDialog::AcceptSave );

// allow for selection of more than one file
//openFileDialog->setMode(QFileDialog::AnyFile);

if ( openFileDialog->exec() != QDialog::Accepted )
return;


QString encoding = openFileDialog->encoding();
QString shapefileName = openFileDialog->selectedFiles().first();
settings.setValue( "/UI/lastShapefileDir", QFileInfo( shapefileName ).absolutePath() );


if ( shapefileName.isNull() )
return;

// add the extension if not present
if ( !shapefileName.endsWith( ".shp", Qt::CaseInsensitive ) )
{
shapefileName += ".shp";
}

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.
QgsVectorFileWriter::deleteShapeFile( shapefileName );

// ok if the file existed it should be deleted now so we can continue...
QApplication::setOverrideCursor( Qt::WaitCursor );

QgsVectorFileWriter::WriterError error;
QString errorMessage;
error = QgsVectorFileWriter::writeAsShapefile( vlayer, shapefileName, encoding, &destCRS, saveOnlySelection, &errorMessage );

QApplication::restoreOverrideCursor();

if ( error == QgsVectorFileWriter::NoError )
{
QMessageBox::information( 0, tr( "Saving done" ), tr( "Export to Shapefile has been completed" ) );
}
else
{
QMessageBox::warning( 0, tr( "Save error" ), errorMessage );
}
delete dialog;
}



QString QgsLegendLayer::nameFromLayer( QgsMapLayer* layer )
{
QString sourcename = layer->publicSource(); //todo: move this duplicated code into a new function
Expand Down
10 changes: 2 additions & 8 deletions src/app/legend/qgslegendlayer.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/***************************************************************************
* Copyright (C) 2005 by Tim Sutton *
* aps02ts@macbuntu *
* Copyright (C) 2005 by Tim Sutton *
* aps02ts@macbuntu *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
Expand Down Expand Up @@ -84,9 +84,6 @@ class QgsLegendLayer : public QgsLegendItem
/**Show layer attribute table*/
void table();

void saveAsShapefile();
void saveSelectionAsShapefile();

void saveAsVectorFile();
void saveSelectionAsVectorFile();

Expand All @@ -111,9 +108,6 @@ class QgsLegendLayer : public QgsLegendItem

QPixmap getOriginalPixmap();

/**Save as shapefile (called from saveAsShapefile and saveSelectionAsShapefile)*/
void saveAsShapefileGeneral( bool saveOnlySelection );

void saveAsVectorFileGeneral( bool saveOnlySelection );

private:
Expand Down
8 changes: 6 additions & 2 deletions src/app/ogr/qgsopenvectorlayerdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
#include <QMessageBox>
#include <QInputDialog>
#include <QTextCodec>

#include "qgslogger.h"
#include "qgsencodingfiledialog.h"
#include "qgsopenvectorlayerdialog.h"
#include "qgsvectordataprovider.h"

#include <ogr_api.h>
#include "qgsproviderregistry.h"
#include "qgsnewogrconnection.h"
Expand All @@ -40,8 +42,10 @@ QgsOpenVectorLayerDialog::QgsOpenVectorLayerDialog( QWidget* parent, Qt::WFlags
cmbConnections->blockSignals( true );
radioSrcFile->setChecked( true );
mDataSourceType = "file";

//set encoding
// cmbEncodings->setItemText( cmbEncodings->currentIndex(), QString( QTextCodec::codecForLocale()->name() ) );
cmbEncodings->addItems( QgsVectorDataProvider::availableEncodings() );

QSettings settings;
QString enc = settings.value( "/UI/encoding", QString( "System" ) ).toString();

Expand Down
Loading

0 comments on commit 9ec2e42

Please sign in to comment.