Skip to content

Commit

Permalink
Fix #8898 (optional filter extent for vector save as)
Browse files Browse the repository at this point in the history
  • Loading branch information
wonder-sk committed Mar 4, 2014
1 parent 5c3d0dd commit 8ac3a94
Show file tree
Hide file tree
Showing 11 changed files with 454 additions and 28 deletions.
18 changes: 11 additions & 7 deletions python/core/qgsvectorfilewriter.sip
Expand Up @@ -123,6 +123,7 @@ class QgsVectorFileWriter
@param newFilename QString pointer which will contain the new file name created (in case it is different to fileName).
@param symbologyExport symbology to export
@param symbologyScale scale of symbology
@param filterExtent if not a null pointer, only features intersecting the extent will be saved
*/
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
const QString& fileName,
Expand All @@ -136,22 +137,25 @@ class QgsVectorFileWriter
bool skipAttributeCreation = false, // added in 1.6
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
double symbologyScale = 1.0 // added in 2.0
double symbologyScale = 1.0, // added in 2.0
const QgsRectangle* filterExtent = 0 // added in 2.4
);

//! @note added in v2.2
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
const QString& fileName,
const QString& fileEncoding,
const QgsCoordinateTransform* ct,
const QString& driverName = "ESRI Shapefile",
bool onlySelected = false,
QString *errorMessage = 0,
const QStringList &datasourceOptions = QStringList(), // added in 1.6
const QStringList &layerOptions = QStringList(), // added in 1.6
bool skipAttributeCreation = false, // added in 1.6
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
double symbologyScale = 1.0 // added in 2.0
const QStringList &datasourceOptions = QStringList(),
const QStringList &layerOptions = QStringList(),
bool skipAttributeCreation = false,
QString *newFilename = 0,
SymbologyExport symbologyExport = NoSymbology,
double symbologyScale = 1.0,
const QgsRectangle* filterExtent = 0 // added in 2.4
);

/** create shapefile and initialize it */
Expand Down
43 changes: 42 additions & 1 deletion src/app/ogr/qgsvectorlayersaveasdialog.cpp
Expand Up @@ -32,9 +32,10 @@ QgsVectorLayerSaveAsDialog::QgsVectorLayerSaveAsDialog( long srsid, QWidget* par
setup();
}

QgsVectorLayerSaveAsDialog::QgsVectorLayerSaveAsDialog( long srsid, int options, QWidget* parent, Qt::WFlags fl )
QgsVectorLayerSaveAsDialog::QgsVectorLayerSaveAsDialog( long srsid, const QgsRectangle& layerExtent, int options, QWidget* parent, Qt::WFlags fl )
: QDialog( parent, fl )
, mCRS( srsid )
, mLayerExtent( layerExtent )
{
setup();
if ( !( options & Symbology ) )
Expand Down Expand Up @@ -87,6 +88,14 @@ void QgsVectorLayerSaveAsDialog::setup()
mSymbologyExportComboBox->addItem( tr( "Feature symbology" ), QgsVectorFileWriter::FeatureSymbology );
mSymbologyExportComboBox->addItem( tr( "Symbol layer symbology" ), QgsVectorFileWriter::SymbolLayerSymbology );
on_mSymbologyExportComboBox_currentIndexChanged( mSymbologyExportComboBox->currentText() );

// extent group box
mExtentGroupBox->setOutputCrs( srs );
mExtentGroupBox->setOriginalExtent( mLayerExtent, srs );
mExtentGroupBox->setOutputExtentFromOriginal();
mExtentGroupBox->setCheckable( true );
mExtentGroupBox->setChecked( false );
mExtentGroupBox->setCollapsed( true );
}

QList<QPair<QLabel*, QWidget*> > QgsVectorLayerSaveAsDialog::createControls( const QMap<QString, QgsVectorFileWriter::Option*>& options )
Expand Down Expand Up @@ -175,6 +184,21 @@ void QgsVectorLayerSaveAsDialog::accept()
void QgsVectorLayerSaveAsDialog::on_mCRSSelection_currentIndexChanged( int idx )
{
leCRS->setEnabled( idx == 2 );

QgsCoordinateReferenceSystem crs;
if ( mCRSSelection->currentIndex() == 0 )
{
crs = mLayerCrs;
}
else if ( mCRSSelection->currentIndex() == 1 )
{
crs = mExtentGroupBox->currentCrs();
}
else // custom CRS
{
crs.createFromId( mCRS, QgsCoordinateReferenceSystem::InternalCrsId );
}
mExtentGroupBox->setOutputCrs( crs );
}

void QgsVectorLayerSaveAsDialog::on_mFormatComboBox_currentIndexChanged( int idx )
Expand Down Expand Up @@ -284,6 +308,8 @@ void QgsVectorLayerSaveAsDialog::on_browseCRS_clicked()
mCRS = srs.srsid();
leCRS->setText( srs.description() );
mCRSSelection->setCurrentIndex( 2 );

mExtentGroupBox->setOutputCrs( srs );
}

delete mySelector;
Expand Down Expand Up @@ -441,6 +467,21 @@ double QgsVectorLayerSaveAsDialog::scaleDenominator() const
return mScaleSpinBox->value();
}

void QgsVectorLayerSaveAsDialog::setCanvasExtent( const QgsRectangle& canvasExtent, const QgsCoordinateReferenceSystem& canvasCrs )
{
mExtentGroupBox->setCurrentExtent( canvasExtent, canvasCrs );
}

bool QgsVectorLayerSaveAsDialog::hasFilterExtent() const
{
return mExtentGroupBox->isChecked();
}

QgsRectangle QgsVectorLayerSaveAsDialog::filterExtent() const
{
return mExtentGroupBox->outputExtent();
}

void QgsVectorLayerSaveAsDialog::on_mSymbologyExportComboBox_currentIndexChanged( const QString& text )
{
bool scaleEnabled = true;
Expand Down
11 changes: 10 additions & 1 deletion src/app/ogr/qgsvectorlayersaveasdialog.h
Expand Up @@ -39,7 +39,7 @@ class QgsVectorLayerSaveAsDialog : public QDialog, private Ui::QgsVectorLayerSav
};

QgsVectorLayerSaveAsDialog( long srsid, QWidget* parent = 0, Qt::WFlags fl = 0 );
QgsVectorLayerSaveAsDialog( long srsid, int options = AllOptions, QWidget* parent = 0, Qt::WFlags fl = 0 );
QgsVectorLayerSaveAsDialog( long srsid, const QgsRectangle& layerExtent, int options = AllOptions, QWidget* parent = 0, Qt::WFlags fl = 0 );
~QgsVectorLayerSaveAsDialog();

QString format() const;
Expand All @@ -57,6 +57,12 @@ class QgsVectorLayerSaveAsDialog : public QDialog, private Ui::QgsVectorLayerSav
int symbologyExport() const;
double scaleDenominator() const;

//! setup canvas extent - for the use in extent group box
void setCanvasExtent( const QgsRectangle& canvasExtent, const QgsCoordinateReferenceSystem& canvasCrs );

bool hasFilterExtent() const;
QgsRectangle filterExtent() const;

private slots:
void on_mFormatComboBox_currentIndexChanged( int idx );
void on_mCRSSelection_currentIndexChanged( int idx );
Expand All @@ -71,6 +77,9 @@ class QgsVectorLayerSaveAsDialog : public QDialog, private Ui::QgsVectorLayerSav
QList< QPair< QLabel*, QWidget* > > createControls( const QMap<QString, QgsVectorFileWriter::Option*>& options );

long mCRS;

QgsRectangle mLayerExtent;
QgsCoordinateReferenceSystem mLayerCrs;
};

#endif // QGSVECTORLAYERSAVEASDIALOG_H
8 changes: 6 additions & 2 deletions src/app/qgisapp.cpp
Expand Up @@ -4601,7 +4601,9 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection, QgsVectorLayer* v
options &= ~QgsVectorLayerSaveAsDialog::Symbology;
}

QgsVectorLayerSaveAsDialog *dialog = new QgsVectorLayerSaveAsDialog( vlayer->crs().srsid(), options, this );
QgsVectorLayerSaveAsDialog *dialog = new QgsVectorLayerSaveAsDialog( vlayer->crs().srsid(), vlayer->extent(), options, this );

dialog->setCanvasExtent( mMapCanvas->mapSettings().visibleExtent(), mMapCanvas->mapSettings().destinationCrs() );

if ( dialog->exec() == QDialog::Accepted )
{
Expand Down Expand Up @@ -4659,6 +4661,7 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection, QgsVectorLayer* v
QgsVectorFileWriter::WriterError error;
QString errorMessage;
QString newFilename;
QgsRectangle filterExtent = dialog->filterExtent();
error = QgsVectorFileWriter::writeAsVectorFormat(
vlayer, vectorFilename, encoding, ct, format,
saveOnlySelection,
Expand All @@ -4667,7 +4670,8 @@ void QgisApp::saveAsVectorFileGeneral( bool saveOnlySelection, QgsVectorLayer* v
dialog->skipAttributeCreation(),
&newFilename,
( QgsVectorFileWriter::SymbologyExport )( dialog->symbologyExport() ),
dialog->scaleDenominator() );
dialog->scaleDenominator(),
dialog->hasFilterExtent() ? &filterExtent : 0 );

delete ct;

Expand Down
23 changes: 14 additions & 9 deletions src/core/qgsvectorfilewriter.cpp
Expand Up @@ -1791,7 +1791,8 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
bool skipAttributeCreation,
QString *newFilename,
SymbologyExport symbologyExport,
double symbologyScale )
double symbologyScale,
const QgsRectangle* filterExtent )
{
QgsCoordinateTransform* ct = 0;
if ( destCRS && layer )
Expand All @@ -1800,7 +1801,7 @@ QgsVectorFileWriter::writeAsVectorFormat( QgsVectorLayer* layer,
}

QgsVectorFileWriter::WriterError error = writeAsVectorFormat( layer, fileName, fileEncoding, ct, driverName, onlySelected,
errorMessage, datasourceOptions, layerOptions, skipAttributeCreation, newFilename, symbologyExport, symbologyScale );
errorMessage, datasourceOptions, layerOptions, skipAttributeCreation, newFilename, symbologyExport, symbologyScale, filterExtent );
delete ct;
return error;
}
Expand All @@ -1812,13 +1813,13 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormat( QgsVe
const QString& driverName,
bool onlySelected,
QString *errorMessage,
const QStringList &datasourceOptions, // added in 1.6
const QStringList &layerOptions, // added in 1.6
bool skipAttributeCreation, // added in 1.6
QString *newFilename, // added in 1.9
SymbologyExport symbologyExport, //added in 2.0
double symbologyScale // added in 2.0
)
const QStringList &datasourceOptions,
const QStringList &layerOptions,
bool skipAttributeCreation,
QString *newFilename,
SymbologyExport symbologyExport,
double symbologyScale,
const QgsRectangle* filterExtent )
{
if ( !layer )
{
Expand Down Expand Up @@ -1960,6 +1961,10 @@ QgsVectorFileWriter::WriterError QgsVectorFileWriter::writeAsVectorFormat( QgsVe
return ErrProjection;
}
}

if ( fet.geometry() && filterExtent && !fet.geometry()->intersects( *filterExtent ) )
continue;

if ( allAttr.size() < 1 && skipAttributeCreation )
{
fet.initAttributes( 0 );
Expand Down
18 changes: 11 additions & 7 deletions src/core/qgsvectorfilewriter.h
Expand Up @@ -176,6 +176,7 @@ class CORE_EXPORT QgsVectorFileWriter
@param newFilename QString pointer which will contain the new file name created (in case it is different to fileName).
@param symbologyExport symbology to export
@param symbologyScale scale of symbology
@param filterExtent if not a null pointer, only features intersecting the extent will be saved
*/
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
const QString& fileName,
Expand All @@ -189,22 +190,25 @@ class CORE_EXPORT QgsVectorFileWriter
bool skipAttributeCreation = false, // added in 1.6
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
double symbologyScale = 1.0 // added in 2.0
double symbologyScale = 1.0, // added in 2.0
const QgsRectangle* filterExtent = 0 // added in 2.4
);

//! @note added in v2.2
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
const QString& fileName,
const QString& fileEncoding,
const QgsCoordinateTransform* ct,
const QString& driverName = "ESRI Shapefile",
bool onlySelected = false,
QString *errorMessage = 0,
const QStringList &datasourceOptions = QStringList(), // added in 1.6
const QStringList &layerOptions = QStringList(), // added in 1.6
bool skipAttributeCreation = false, // added in 1.6
QString *newFilename = 0, // added in 1.9
SymbologyExport symbologyExport = NoSymbology, //added in 2.0
double symbologyScale = 1.0 // added in 2.0
const QStringList &datasourceOptions = QStringList(),
const QStringList &layerOptions = QStringList(),
bool skipAttributeCreation = false,
QString *newFilename = 0,
SymbologyExport symbologyExport = NoSymbology,
double symbologyScale = 1.0,
const QgsRectangle* filterExtent = 0 // added in 2.4
);

/** create shapefile and initialize it */
Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -86,6 +86,7 @@ qgsexpressionbuilderdialog.cpp
qgsexpressionbuilderwidget.cpp
qgsexpressionhighlighter.cpp
qgsexpressionselectiondialog.cpp
qgsextentgroupbox.cpp
qgsfeatureselectiondlg.cpp
qgsfieldvalidator.cpp
qgsfiledropedit.cpp
Expand Down Expand Up @@ -224,6 +225,7 @@ qgserrordialog.h
qgsexpressionbuilderwidget.h
qgsexpressionhighlighter.h
qgsexpressionselectiondialog.h
qgsextentgroupbox.h
qgsfeatureselectiondlg.h
qgsfieldvalidator.h
qgsfilterlineedit.h
Expand Down
105 changes: 105 additions & 0 deletions src/gui/qgsextentgroupbox.cpp
@@ -0,0 +1,105 @@
#include "qgsextentgroupbox.h"

#include "qgscoordinatetransform.h"
#include "qgsrasterblock.h"

QgsExtentGroupBox::QgsExtentGroupBox( QWidget* parent )
: QgsCollapsibleGroupBox( parent )
{
setupUi( this );

mXMinLineEdit->setValidator( new QDoubleValidator( this ) );
mXMaxLineEdit->setValidator( new QDoubleValidator( this ) );
mYMinLineEdit->setValidator( new QDoubleValidator( this ) );
mYMaxLineEdit->setValidator( new QDoubleValidator( this ) );

connect( mCurrentExtentButton, SIGNAL( clicked() ), this, SLOT( setOutputExtentFromCurrent() ) );
connect( mOriginalExtentButton, SIGNAL( clicked() ), this, SLOT( setOutputExtentFromOriginal() ) );
}


void QgsExtentGroupBox::setOriginalExtent( const QgsRectangle& originalExtent, const QgsCoordinateReferenceSystem& originalCrs )
{
mOriginalExtent = originalExtent;
mOriginalCrs = originalCrs;
}


void QgsExtentGroupBox::setCurrentExtent( const QgsRectangle& currentExtent, const QgsCoordinateReferenceSystem& currentCrs )
{
mCurrentExtent = currentExtent;
mCurrentCrs = currentCrs;
}

void QgsExtentGroupBox::setOutputCrs( const QgsCoordinateReferenceSystem& outputCrs )
{
mOutputCrs = outputCrs;
}


void QgsExtentGroupBox::setOutputExtent( const QgsRectangle& r, const QgsCoordinateReferenceSystem& srcCrs, ExtentState state )
{
QgsRectangle extent;
if ( mOutputCrs == srcCrs )
{
extent = r;
}
else
{
QgsCoordinateTransform ct( srcCrs, mOutputCrs );
extent = ct.transformBoundingBox( r );
}

mXMinLineEdit->setText( QgsRasterBlock::printValue( extent.xMinimum() ) );
mXMaxLineEdit->setText( QgsRasterBlock::printValue( extent.xMaximum() ) );
mYMinLineEdit->setText( QgsRasterBlock::printValue( extent.yMinimum() ) );
mYMaxLineEdit->setText( QgsRasterBlock::printValue( extent.yMaximum() ) );

mExtentState = state;

updateExtentStateMsg();

emit extentChanged( extent );
}


void QgsExtentGroupBox::updateExtentStateMsg()
{
QString msg;
switch ( mExtentState )
{
case OriginalExtent:
msg = tr( "layer" );
break;
case CurrentExtent:
msg = tr( "map view" );
break;
case UserExtent:
msg = tr( "user defined" );
break;
default:
break;
}
msg = tr( "Extent (current: %1)" ).arg( msg );

setTitle( msg );
}


void QgsExtentGroupBox::setOutputExtentFromCurrent()
{
setOutputExtent( mCurrentExtent, mCurrentCrs, CurrentExtent );
}


void QgsExtentGroupBox::setOutputExtentFromOriginal()
{
setOutputExtent( mOriginalExtent, mOriginalCrs, OriginalExtent );
}


QgsRectangle QgsExtentGroupBox::outputExtent() const
{
return QgsRectangle( mXMinLineEdit->text().toDouble(), mYMinLineEdit->text().toDouble(),
mXMaxLineEdit->text().toDouble(), mYMaxLineEdit->text().toDouble() );
}

0 comments on commit 8ac3a94

Please sign in to comment.