Skip to content

Commit

Permalink
Geopackage import rasters with drag and drop
Browse files Browse the repository at this point in the history
This implementation uses GDALTranslate and
a QgsTask.
  • Loading branch information
elpaso committed Aug 24, 2017
1 parent 83b11d5 commit 8771e83
Show file tree
Hide file tree
Showing 7 changed files with 427 additions and 120 deletions.
4 changes: 4 additions & 0 deletions src/providers/ogr/CMakeLists.txt
Expand Up @@ -8,6 +8,8 @@ SET (OGR_SRCS
qgsogrsourceselect.cpp
qgsgeopackagedataitems.cpp
qgsgeopackageconnection.cpp
qgsgeopackagerasterwriter.cpp
qgsgeopackagerasterwritertask.cpp
)

SET(OGR_MOC_HDRS
Expand All @@ -17,6 +19,8 @@ SET(OGR_MOC_HDRS
qgsogrsourceselect.h
qgsgeopackagedataitems.h
qgsgeopackageconnection.h
qgsgeopackagerasterwriter.h
qgsgeopackagerasterwritertask.h
)

########################################################
Expand Down
276 changes: 156 additions & 120 deletions src/providers/ogr/qgsgeopackagedataitems.cpp

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions src/providers/ogr/qgsgeopackagedataitems.h
Expand Up @@ -82,6 +82,9 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
//! Return the layer type from \a geometryType
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );

//! Delete a geopackage layer
static bool deleteGeoPackageRasterLayer( const QString uri, QString &errCause );

public slots:
#ifdef HAVE_GUI
void editConnection();
Expand Down
74 changes: 74 additions & 0 deletions src/providers/ogr/qgsgeopackagerasterwriter.cpp
@@ -0,0 +1,74 @@
/***************************************************************************
qgsgeopackagerasterwriter.cpp - QgsGeoPackageRasterWriter
---------------------
begin : 23.8.2017
copyright : (C) 2017 by Alessandro Pasotti
email : apasotti at boundlessgeo dot com
***************************************************************************
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

///@cond PRIVATE

#include "gdal.h"
#include "gdal_utils.h"

#include "qgsgeopackagerasterwriter.h"
#include "qgscplerrorhandler.h"

#include <QMessageBox>

QgsGeoPackageRasterWriter::QgsGeoPackageRasterWriter( const QgsMimeDataUtils::Uri sourceUri, const QString outputUrl ):
mSourceUri( sourceUri ),
mOutputUrl( outputUrl )
{

}

QgsGeoPackageRasterWriter::WriterError QgsGeoPackageRasterWriter::writeRaster( QgsFeedback *feedback, QString *errorMessage )
{
const char *args[] = { "-of", "gpkg", "-co", QStringLiteral( "RASTER_TABLE=%1" ).arg( mSourceUri.name ).toUtf8().constData(), "-co", "APPEND_SUBDATASET=YES", nullptr };
// This sends OGR/GDAL errors to the message log
QgsCPLErrorHandler handler;
GDALTranslateOptions *psOptions = GDALTranslateOptionsNew( ( char ** )args, nullptr );

GDALTranslateOptionsSetProgress( psOptions, [ ]( double dfComplete, const char *pszMessage, void *pProgressData ) -> int
{
Q_UNUSED( pszMessage );
QgsFeedback *feedback = static_cast< QgsFeedback * >( pProgressData );
feedback->setProgress( dfComplete * 100 );
return ! feedback->isCanceled();
}, feedback );

GDALDatasetH hSrcDS = GDALOpen( mSourceUri.uri.toUtf8().constData(), GA_ReadOnly );
if ( ! hSrcDS )
{
*errorMessage = QObject::tr( "Failed to open source layer %1! See the OGR panel in the message logs for details.\n\n" ).arg( mSourceUri.name );
mHasError = true;
}
else
{
CPLErrorReset();
GDALDatasetH hOutDS = GDALTranslate( mOutputUrl.toUtf8().constData(), hSrcDS, psOptions, NULL );
if ( ! hOutDS )
{
*errorMessage = QObject::tr( "Failed to import layer %1! See the OGR panel in the message logs for details.\n\n" ).arg( mSourceUri.name );
mHasError = true;
}
else // All good!
{
GDALClose( hOutDS );
}
GDALClose( hSrcDS );
}
GDALTranslateOptionsFree( psOptions );
return ( feedback && feedback->isCanceled() ) ? ErrUserCanceled : ( mHasError ? WriteError : NoError ) ;
}

///@endcond
52 changes: 52 additions & 0 deletions src/providers/ogr/qgsgeopackagerasterwriter.h
@@ -0,0 +1,52 @@
/***************************************************************************
qgsgeopackagerasterwriter.h - QgsGeoPackageRasterWriter
---------------------
begin : 23.8.2017
copyright : (C) 2017 by Alessandro Pasotti
email : apasotti at boundlessgeo dot com
***************************************************************************
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGEOPACKAGERASTERWRITER_H
#define QGSGEOPACKAGERASTERWRITER_H

///@cond PRIVATE

#define SIP_NO_FILE

#include "qgsmimedatautils.h"
#include "qgsfeedback.h"

class QgsGeoPackageRasterWriter
{
public:

//! Error codes
enum WriterError
{
NoError = 0, //!< No errors were encountered
WriteError, //! Generic GDAL Translate error
ErrUserCanceled, //!< User canceled the export
};

QgsGeoPackageRasterWriter( const QgsMimeDataUtils::Uri sourceUri, const QString destinationPath );
WriterError writeRaster( QgsFeedback *feedback, QString *errorMessage );
const QString outputUrl() const { return mOutputUrl; }

private:
QgsMimeDataUtils::Uri mSourceUri;
QString mOutputUrl;
bool mHasError = false;
};


///@endcond

#endif // QGSGEOPACKAGERASTERWRITER_H

55 changes: 55 additions & 0 deletions src/providers/ogr/qgsgeopackagerasterwritertask.cpp
@@ -0,0 +1,55 @@
/***************************************************************************
qgsgeopackagerasterwritertask.cpp - QgsGeoPackageRasterWriterTask
---------------------
begin : 23.8.2017
copyright : (C) 2017 by Alessandro Pasotti
email : apasotti at boundlessgeo dot com
***************************************************************************
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsgeopackagerasterwritertask.h"


///@cond PRIVATE


QgsGeoPackageRasterWriterTask::QgsGeoPackageRasterWriterTask( const QgsMimeDataUtils::Uri sourceUri, const QString destinationPath )
: QgsTask( tr( "Saving %1" ).arg( destinationPath ), QgsTask::CanCancel )
, mWriter( sourceUri, destinationPath )
, mFeedback( new QgsFeedback() )
{

}

void QgsGeoPackageRasterWriterTask::cancel()
{
mError = QgsGeoPackageRasterWriter::WriterError::ErrUserCanceled;
mFeedback.get()->cancel();
}

bool QgsGeoPackageRasterWriterTask::run()
{
connect( mFeedback.get(), &QgsFeedback::progressChanged, this, &QgsGeoPackageRasterWriterTask::setProgress );
mError = mWriter.writeRaster( mFeedback.get(), &mErrorMessage );
return mError == QgsGeoPackageRasterWriter::WriterError::NoError;
}

void QgsGeoPackageRasterWriterTask::finished( bool result )
{
if ( result )
{
emit writeComplete( mWriter.outputUrl() );
}
else
{
emit errorOccurred( mError, mErrorMessage );
}
}

///@endcond
83 changes: 83 additions & 0 deletions src/providers/ogr/qgsgeopackagerasterwritertask.h
@@ -0,0 +1,83 @@
/***************************************************************************
qgsgeopackagerasterwritertask.h - QgsGeoPackageRasterWriterTask
---------------------
begin : 23.8.2017
copyright : (C) 2017 by Alessandro Pasotti
email : apasotti at boundlessgeo dot com
***************************************************************************
* *
* 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 *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSGEOPACKAGERASTERWRITERTASK_H
#define QGSGEOPACKAGERASTERWRITERTASK_H


///@cond PRIVATE

#define SIP_NO_FILE

#include "qgis_core.h"
#include "qgsgeopackagerasterwriter.h"
#include "qgstaskmanager.h"
#include "qgsfeedback.h"


/**
* \class QgsGeoPackageRasterWriterTask
* QgsTask task which performs a QgsGeoPackageRasterWriter 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.
* \since QGIS 3.0
* \see QgsGeoPackageRasterWriterTask
*/
class QgsGeoPackageRasterWriterTask : public QgsTask
{
Q_OBJECT

public:

/**
* Constructor for QgsVectorFileWriterTask. Takes a source \a layer, destination \a fileName
* and save \a options.
*/
QgsGeoPackageRasterWriterTask( const QgsMimeDataUtils::Uri sourceUri, const QString destinationPath );

virtual void cancel() override;

signals:

/**
* Emitted when writing the layer is successfully completed. The \a newFilename
* parameter indicates the file path for the written file.
*/
void writeComplete( const QString &newFilename );

/**
* Emitted when an error occurs which prevented the file being written (or if
* the task is canceled). The writing \a error and \a errorMessage will be reported.
*/
void errorOccurred( QgsGeoPackageRasterWriter::WriterError error, const QString &errorMessage );

protected:

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

private:

QgsGeoPackageRasterWriter mWriter;
std::unique_ptr< QgsFeedback > mFeedback;
QgsGeoPackageRasterWriter::WriterError mError = QgsGeoPackageRasterWriter::WriterError::NoError ;
QString mErrorMessage;

};


///@endcond

#endif // QGSGEOPACKAGERASTERWRITERTASK_H

0 comments on commit 8771e83

Please sign in to comment.