Skip to content

Commit 8771e83

Browse files
committed
Geopackage import rasters with drag and drop
This implementation uses GDALTranslate and a QgsTask.
1 parent 83b11d5 commit 8771e83

7 files changed

+427
-120
lines changed

src/providers/ogr/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ SET (OGR_SRCS
88
qgsogrsourceselect.cpp
99
qgsgeopackagedataitems.cpp
1010
qgsgeopackageconnection.cpp
11+
qgsgeopackagerasterwriter.cpp
12+
qgsgeopackagerasterwritertask.cpp
1113
)
1214

1315
SET(OGR_MOC_HDRS
@@ -17,6 +19,8 @@ SET(OGR_MOC_HDRS
1719
qgsogrsourceselect.h
1820
qgsgeopackagedataitems.h
1921
qgsgeopackageconnection.h
22+
qgsgeopackagerasterwriter.h
23+
qgsgeopackagerasterwritertask.h
2024
)
2125

2226
########################################################

src/providers/ogr/qgsgeopackagedataitems.cpp

+156-120
Large diffs are not rendered by default.

src/providers/ogr/qgsgeopackagedataitems.h

+3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ class QgsGeoPackageConnectionItem : public QgsDataCollectionItem
8282
//! Return the layer type from \a geometryType
8383
static QgsLayerItem::LayerType layerTypeFromDb( const QString &geometryType );
8484

85+
//! Delete a geopackage layer
86+
static bool deleteGeoPackageRasterLayer( const QString uri, QString &errCause );
87+
8588
public slots:
8689
#ifdef HAVE_GUI
8790
void editConnection();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/***************************************************************************
2+
qgsgeopackagerasterwriter.cpp - QgsGeoPackageRasterWriter
3+
4+
---------------------
5+
begin : 23.8.2017
6+
copyright : (C) 2017 by Alessandro Pasotti
7+
email : apasotti at boundlessgeo dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
17+
///@cond PRIVATE
18+
19+
#include "gdal.h"
20+
#include "gdal_utils.h"
21+
22+
#include "qgsgeopackagerasterwriter.h"
23+
#include "qgscplerrorhandler.h"
24+
25+
#include <QMessageBox>
26+
27+
QgsGeoPackageRasterWriter::QgsGeoPackageRasterWriter( const QgsMimeDataUtils::Uri sourceUri, const QString outputUrl ):
28+
mSourceUri( sourceUri ),
29+
mOutputUrl( outputUrl )
30+
{
31+
32+
}
33+
34+
QgsGeoPackageRasterWriter::WriterError QgsGeoPackageRasterWriter::writeRaster( QgsFeedback *feedback, QString *errorMessage )
35+
{
36+
const char *args[] = { "-of", "gpkg", "-co", QStringLiteral( "RASTER_TABLE=%1" ).arg( mSourceUri.name ).toUtf8().constData(), "-co", "APPEND_SUBDATASET=YES", nullptr };
37+
// This sends OGR/GDAL errors to the message log
38+
QgsCPLErrorHandler handler;
39+
GDALTranslateOptions *psOptions = GDALTranslateOptionsNew( ( char ** )args, nullptr );
40+
41+
GDALTranslateOptionsSetProgress( psOptions, [ ]( double dfComplete, const char *pszMessage, void *pProgressData ) -> int
42+
{
43+
Q_UNUSED( pszMessage );
44+
QgsFeedback *feedback = static_cast< QgsFeedback * >( pProgressData );
45+
feedback->setProgress( dfComplete * 100 );
46+
return ! feedback->isCanceled();
47+
}, feedback );
48+
49+
GDALDatasetH hSrcDS = GDALOpen( mSourceUri.uri.toUtf8().constData(), GA_ReadOnly );
50+
if ( ! hSrcDS )
51+
{
52+
*errorMessage = QObject::tr( "Failed to open source layer %1! See the OGR panel in the message logs for details.\n\n" ).arg( mSourceUri.name );
53+
mHasError = true;
54+
}
55+
else
56+
{
57+
CPLErrorReset();
58+
GDALDatasetH hOutDS = GDALTranslate( mOutputUrl.toUtf8().constData(), hSrcDS, psOptions, NULL );
59+
if ( ! hOutDS )
60+
{
61+
*errorMessage = QObject::tr( "Failed to import layer %1! See the OGR panel in the message logs for details.\n\n" ).arg( mSourceUri.name );
62+
mHasError = true;
63+
}
64+
else // All good!
65+
{
66+
GDALClose( hOutDS );
67+
}
68+
GDALClose( hSrcDS );
69+
}
70+
GDALTranslateOptionsFree( psOptions );
71+
return ( feedback && feedback->isCanceled() ) ? ErrUserCanceled : ( mHasError ? WriteError : NoError ) ;
72+
}
73+
74+
///@endcond
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/***************************************************************************
2+
qgsgeopackagerasterwriter.h - QgsGeoPackageRasterWriter
3+
4+
---------------------
5+
begin : 23.8.2017
6+
copyright : (C) 2017 by Alessandro Pasotti
7+
email : apasotti at boundlessgeo dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#ifndef QGSGEOPACKAGERASTERWRITER_H
17+
#define QGSGEOPACKAGERASTERWRITER_H
18+
19+
///@cond PRIVATE
20+
21+
#define SIP_NO_FILE
22+
23+
#include "qgsmimedatautils.h"
24+
#include "qgsfeedback.h"
25+
26+
class QgsGeoPackageRasterWriter
27+
{
28+
public:
29+
30+
//! Error codes
31+
enum WriterError
32+
{
33+
NoError = 0, //!< No errors were encountered
34+
WriteError, //! Generic GDAL Translate error
35+
ErrUserCanceled, //!< User canceled the export
36+
};
37+
38+
QgsGeoPackageRasterWriter( const QgsMimeDataUtils::Uri sourceUri, const QString destinationPath );
39+
WriterError writeRaster( QgsFeedback *feedback, QString *errorMessage );
40+
const QString outputUrl() const { return mOutputUrl; }
41+
42+
private:
43+
QgsMimeDataUtils::Uri mSourceUri;
44+
QString mOutputUrl;
45+
bool mHasError = false;
46+
};
47+
48+
49+
///@endcond
50+
51+
#endif // QGSGEOPACKAGERASTERWRITER_H
52+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/***************************************************************************
2+
qgsgeopackagerasterwritertask.cpp - QgsGeoPackageRasterWriterTask
3+
4+
---------------------
5+
begin : 23.8.2017
6+
copyright : (C) 2017 by Alessandro Pasotti
7+
email : apasotti at boundlessgeo dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#include "qgsgeopackagerasterwritertask.h"
17+
18+
19+
///@cond PRIVATE
20+
21+
22+
QgsGeoPackageRasterWriterTask::QgsGeoPackageRasterWriterTask( const QgsMimeDataUtils::Uri sourceUri, const QString destinationPath )
23+
: QgsTask( tr( "Saving %1" ).arg( destinationPath ), QgsTask::CanCancel )
24+
, mWriter( sourceUri, destinationPath )
25+
, mFeedback( new QgsFeedback() )
26+
{
27+
28+
}
29+
30+
void QgsGeoPackageRasterWriterTask::cancel()
31+
{
32+
mError = QgsGeoPackageRasterWriter::WriterError::ErrUserCanceled;
33+
mFeedback.get()->cancel();
34+
}
35+
36+
bool QgsGeoPackageRasterWriterTask::run()
37+
{
38+
connect( mFeedback.get(), &QgsFeedback::progressChanged, this, &QgsGeoPackageRasterWriterTask::setProgress );
39+
mError = mWriter.writeRaster( mFeedback.get(), &mErrorMessage );
40+
return mError == QgsGeoPackageRasterWriter::WriterError::NoError;
41+
}
42+
43+
void QgsGeoPackageRasterWriterTask::finished( bool result )
44+
{
45+
if ( result )
46+
{
47+
emit writeComplete( mWriter.outputUrl() );
48+
}
49+
else
50+
{
51+
emit errorOccurred( mError, mErrorMessage );
52+
}
53+
}
54+
55+
///@endcond
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/***************************************************************************
2+
qgsgeopackagerasterwritertask.h - QgsGeoPackageRasterWriterTask
3+
4+
---------------------
5+
begin : 23.8.2017
6+
copyright : (C) 2017 by Alessandro Pasotti
7+
email : apasotti at boundlessgeo dot com
8+
***************************************************************************
9+
* *
10+
* This program is free software; you can redistribute it and/or modify *
11+
* it under the terms of the GNU General Public License as published by *
12+
* the Free Software Foundation; either version 2 of the License, or *
13+
* (at your option) any later version. *
14+
* *
15+
***************************************************************************/
16+
#ifndef QGSGEOPACKAGERASTERWRITERTASK_H
17+
#define QGSGEOPACKAGERASTERWRITERTASK_H
18+
19+
20+
///@cond PRIVATE
21+
22+
#define SIP_NO_FILE
23+
24+
#include "qgis_core.h"
25+
#include "qgsgeopackagerasterwriter.h"
26+
#include "qgstaskmanager.h"
27+
#include "qgsfeedback.h"
28+
29+
30+
/**
31+
* \class QgsGeoPackageRasterWriterTask
32+
* QgsTask task which performs a QgsGeoPackageRasterWriter layer saving operation as a background
33+
* task. This can be used to save a raster layer out to a file without blocking the
34+
* QGIS interface.
35+
* \since QGIS 3.0
36+
* \see QgsGeoPackageRasterWriterTask
37+
*/
38+
class QgsGeoPackageRasterWriterTask : public QgsTask
39+
{
40+
Q_OBJECT
41+
42+
public:
43+
44+
/**
45+
* Constructor for QgsVectorFileWriterTask. Takes a source \a layer, destination \a fileName
46+
* and save \a options.
47+
*/
48+
QgsGeoPackageRasterWriterTask( const QgsMimeDataUtils::Uri sourceUri, const QString destinationPath );
49+
50+
virtual void cancel() override;
51+
52+
signals:
53+
54+
/**
55+
* Emitted when writing the layer is successfully completed. The \a newFilename
56+
* parameter indicates the file path for the written file.
57+
*/
58+
void writeComplete( const QString &newFilename );
59+
60+
/**
61+
* Emitted when an error occurs which prevented the file being written (or if
62+
* the task is canceled). The writing \a error and \a errorMessage will be reported.
63+
*/
64+
void errorOccurred( QgsGeoPackageRasterWriter::WriterError error, const QString &errorMessage );
65+
66+
protected:
67+
68+
virtual bool run() override;
69+
virtual void finished( bool result ) override;
70+
71+
private:
72+
73+
QgsGeoPackageRasterWriter mWriter;
74+
std::unique_ptr< QgsFeedback > mFeedback;
75+
QgsGeoPackageRasterWriter::WriterError mError = QgsGeoPackageRasterWriter::WriterError::NoError ;
76+
QString mErrorMessage;
77+
78+
};
79+
80+
81+
///@endcond
82+
83+
#endif // QGSGEOPACKAGERASTERWRITERTASK_H

0 commit comments

Comments
 (0)