Skip to content

Commit

Permalink
[FEATURE] Background saving of raster layers
Browse files Browse the repository at this point in the history
Use the task manager framework to handle saving of raster layers
in the background
  • Loading branch information
nyalldawson committed Apr 6, 2017
1 parent 25d9936 commit 110828f
Show file tree
Hide file tree
Showing 13 changed files with 413 additions and 79 deletions.
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -298,6 +298,7 @@
%Include raster/qgsrasterdataprovider.sip
%Include raster/qgsrasterdrawer.sip
%Include raster/qgsrasterfilewriter.sip
%Include raster/qgsrasterfilewritertask.sip
%Include raster/qgsrasterhistogram.sip
%Include raster/qgsrasteridentifyresult.sip
%Include raster/qgsrasterinterface.sip
Expand Down
4 changes: 3 additions & 1 deletion python/core/raster/qgsrasterfilewriter.sip
Expand Up @@ -49,7 +49,9 @@ class QgsRasterFileWriter
@param crs crs to reproject to
@param p dialog to show progress in */
WriterError writeRaster( const QgsRasterPipe* pipe, int nCols, int nRows, const QgsRectangle& outputExtent,
const QgsCoordinateReferenceSystem& crs, QProgressDialog* p = 0 );
const QgsCoordinateReferenceSystem& crs, QgsRasterBlockFeedback *feedback = nullptr );

QString outputUrl() const;

void setOutputFormat( const QString& format );
QString outputFormat() const;
Expand Down
68 changes: 68 additions & 0 deletions python/core/raster/qgsrasterfilewritertask.sip
@@ -0,0 +1,68 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/raster/qgsrasterfilewritertask.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/




class QgsRasterFileWriterTask : QgsTask
{
%Docstring
QgsTask task which performs a QgsRasterFileWriter layer saving operation as a background
task. This can be used to save a raster layer out to a file without blocking the
QGIS interface.
\see QgsVectorFileWriterTask
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsrasterfilewritertask.h"
%End

public:

QgsRasterFileWriterTask( const QgsRasterFileWriter &writer, QgsRasterPipe *pipe /Transfer/,
int columns, int rows,
const QgsRectangle &outputExtent,
const QgsCoordinateReferenceSystem &crs );
%Docstring
Constructor for QgsRasterFileWriterTask. Takes a source writer,
columns, rows, outputExtent and destination crs.
Ownership of the pipe is transferred to the writer task, and will
be deleted when the task completes.
%End

virtual void cancel();

signals:

void writeComplete( const QString &outputUrl );
%Docstring
Emitted when writing the layer is successfully completed. The outputUrl
parameter indicates the file path for the written file(s).
%End

void errorOccurred( int error );
%Docstring
Emitted when an error occurs which prevented the file being written (or if
the task is canceled). The writing error will be reported.
%End

protected:

virtual bool run();
virtual void finished( bool result );

};

/************************************************************************
* This file has been generated automatically from *
* *
* src/core/raster/qgsrasterfilewritertask.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
50 changes: 30 additions & 20 deletions src/app/qgisapp.cpp
Expand Up @@ -219,6 +219,7 @@
#include "qgsquerybuilder.h"
#include "qgsrastercalcdialog.h"
#include "qgsrasterfilewriter.h"
#include "qgsrasterfilewritertask.h"
#include "qgsrasteriterator.h"
#include "qgsrasterlayer.h"
#include "qgsrasterlayerproperties.h"
Expand Down Expand Up @@ -6453,13 +6454,6 @@ void QgisApp::saveAsRasterFile()
fileWriter.setMaxTileHeight( d.maximumTileSizeY() );
}

QProgressDialog pd( QString(), tr( "Abort..." ), 0, 0 );
// Show the dialo immediately because cloning pipe can take some time (WCS)
pd.setLabelText( tr( "Reading raster" ) );
pd.setWindowTitle( tr( "Saving raster" ) );
pd.show();
pd.setWindowModality( Qt::WindowModal );

// TODO: show error dialogs
// TODO: this code should go somewhere else, but probably not into QgsRasterFileWriter
// clone pipe/provider is not really necessary, ready for threads
Expand Down Expand Up @@ -6525,35 +6519,51 @@ void QgisApp::saveAsRasterFile()
fileWriter.setPyramidsFormat( d.pyramidsFormat() );
fileWriter.setPyramidsConfigOptions( d.pyramidsConfigOptions() );

QgsRasterFileWriter::WriterError err = fileWriter.writeRaster( pipe.get(), d.nColumns(), d.nRows(), d.outputRectangle(), d.outputCrs(), &pd );
if ( err != QgsRasterFileWriter::NoError )
{
QMessageBox::warning( this, tr( "Error" ),
tr( "Cannot write raster error code: %1" ).arg( err ),
QMessageBox::Ok );
bool tileMode = d.tileMode();
bool addToCanvas = d.addToCanvas();
QPointer< QgsRasterLayer > rlWeakPointer( rasterLayer );

}
else
QgsRasterFileWriterTask *writerTask = new QgsRasterFileWriterTask( fileWriter, pipe.release(), d.nColumns(), d.nRows(),
d.outputRectangle(), d.outputCrs() );

// when writer is successful:

connect( writerTask, &QgsRasterFileWriterTask::writeComplete, this, [this, tileMode, addToCanvas, rlWeakPointer ]( const QString & newFilename )
{
QString fileName( d.outputFileName() );
if ( d.tileMode() )
QString fileName = newFilename;
if ( tileMode )
{
QFileInfo outputInfo( fileName );
fileName = QStringLiteral( "%1/%2.vrt" ).arg( fileName, outputInfo.fileName() );
}

if ( d.addToCanvas() )
if ( addToCanvas )
{
addRasterLayers( QStringList( fileName ) );
}
if ( rlWeakPointer )
emit layerSavedAs( rlWeakPointer, fileName );

emit layerSavedAs( rasterLayer, fileName );
messageBar()->pushMessage( tr( "Saving done" ),
tr( "Export to raster file has been completed" ),
QgsMessageBar::INFO, messageTimeout() );
}
} );

// when an error occurs:
connect( writerTask, &QgsRasterFileWriterTask::errorOccurred, this, [ = ]( int error )
{
if ( error != QgsRasterFileWriter::WriteCanceled )
{
QMessageBox::warning( this, tr( "Error" ),
tr( "Cannot write raster error code: %1" ).arg( error ),
QMessageBox::Ok );
}
} );

QgsApplication::taskManager()->addTask( writerTask );
}


void QgisApp::saveAsFile()
{
QgsMapLayer *layer = activeLayer();
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt 100644 → 100755
Expand Up @@ -336,6 +336,7 @@ SET(QGIS_CORE_SRCS
raster/qgsrasterblock.cpp
raster/qgsrasterchecker.cpp
raster/qgsrasterdataprovider.cpp
raster/qgsrasterfilewritertask.cpp
raster/qgsrasteridentifyresult.cpp
raster/qgsrasterinterface.cpp
raster/qgsrasteriterator.cpp
Expand Down Expand Up @@ -597,6 +598,7 @@ SET(QGIS_CORE_MOC_HDRS
processing/qgsprocessingfeedback.h
processing/qgsprocessingregistry.h

raster/qgsrasterfilewritertask.h
raster/qgsrasterlayer.h
raster/qgsrasterdataprovider.h

Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsvectorfilewritertask.cpp
Expand Up @@ -19,7 +19,7 @@


QgsVectorFileWriterTask::QgsVectorFileWriterTask( QgsVectorLayer *layer, const QString &fileName, const QgsVectorFileWriter::SaveVectorOptions &options )
: QgsTask( tr( "Saving %1 " ).arg( fileName ), QgsTask::CanCancel )
: QgsTask( tr( "Saving %1" ).arg( fileName ), QgsTask::CanCancel )
, mLayer( layer )
, mDestFileName( fileName )
, mOptions( options )
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsvectorfilewritertask.h
Expand Up @@ -30,6 +30,7 @@
* task. This can be used to save a vector layer out to a file without blocking the
* QGIS interface.
* \since QGIS 3.0
* \see QgsRasterFileWriterTask
*/
class CORE_EXPORT QgsVectorFileWriterTask : public QgsTask
{
Expand Down

0 comments on commit 110828f

Please sign in to comment.