Skip to content

Commit d236942

Browse files
authored
Merge pull request #5650 from nyalldawson/proc_gpkg
[FEATURE][processing] Package layers algorithm
2 parents b288a5f + 0a18b1f commit d236942

14 files changed

+526
-112
lines changed

python/core/core_auto.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
%Include processing/qgsprocessingoutputs.sip
180180
%Include processing/qgsprocessingparameters.sip
181181
%Include processing/qgsprocessingutils.sip
182+
%Include processing/models/qgsprocessingmodelalgorithm.sip
182183
%Include processing/models/qgsprocessingmodelchildalgorithm.sip
183184
%Include processing/models/qgsprocessingmodelchildparametersource.sip
184185
%Include processing/models/qgsprocessingmodelcomponent.sip
@@ -391,7 +392,6 @@
391392
%Include processing/qgsprocessingfeedback.sip
392393
%Include processing/qgsprocessingprovider.sip
393394
%Include processing/qgsprocessingregistry.sip
394-
%Include processing/models/qgsprocessingmodelalgorithm.sip
395395
%Include raster/qgsrasterfilewritertask.sip
396396
%Include raster/qgsrasterlayer.sip
397397
%Include raster/qgsrasterdataprovider.sip

python/core/processing/models/qgsprocessingmodelalgorithm.sip

-2
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,6 @@ Translated description of variable
374374
};
375375

376376

377-
378-
379377
/************************************************************************
380378
* This file has been generated automatically from *
381379
* *

python/core/processing/qgsprocessingfeedback.sip

+46
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,52 @@ class QgsProcessingFeedback : QgsFeedback
8080
};
8181

8282

83+
class QgsProcessingMultiStepFeedback : QgsProcessingFeedback
84+
{
85+
%Docstring
86+
87+
Processing feedback object for multi-step operations.
88+
89+
A processing feedback object which proxies its calls to an underlying
90+
feedback object, but scales overall progress reports to account
91+
for a number of child steps which each report their own feedback.
92+
93+
.. versionadded:: 3.0
94+
%End
95+
96+
%TypeHeaderCode
97+
#include "qgsprocessingfeedback.h"
98+
%End
99+
public:
100+
101+
QgsProcessingMultiStepFeedback( int steps, QgsProcessingFeedback *feedback );
102+
%Docstring
103+
Constructor for QgsProcessingMultiStepFeedback, for a process with the specified
104+
number of ``steps``. This feedback object will proxy calls
105+
to the specified ``feedback`` object.
106+
%End
107+
108+
void setCurrentStep( int step );
109+
%Docstring
110+
Sets the ``step`` which is being executed. This is used
111+
to scale the current progress to account for progress through the overall process.
112+
%End
113+
114+
virtual void setProgressText( const QString &text );
115+
116+
virtual void reportError( const QString &error );
117+
118+
virtual void pushInfo( const QString &info );
119+
120+
virtual void pushCommandInfo( const QString &info );
121+
122+
virtual void pushDebugInfo( const QString &info );
123+
124+
virtual void pushConsoleInfo( const QString &info );
125+
126+
127+
};
128+
83129

84130

85131
/************************************************************************

src/analysis/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ SET(QGIS_ANALYSIS_SRCS
4646
processing/qgsalgorithmminimumenclosingcircle.cpp
4747
processing/qgsalgorithmmultiparttosinglepart.cpp
4848
processing/qgsalgorithmorientedminimumboundingbox.cpp
49+
processing/qgsalgorithmpackage.cpp
4950
processing/qgsalgorithmpromotetomultipart.cpp
5051
processing/qgsalgorithmrasterlayeruniquevalues.cpp
5152
processing/qgsalgorithmremovenullgeometry.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/***************************************************************************
2+
qgsalgorithmpackage.cpp
3+
---------------------
4+
begin : November 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#include "qgsalgorithmpackage.h"
19+
#include "qgsgeometryengine.h"
20+
#include "qgsogrutils.h"
21+
#include "qgsvectorfilewriter.h"
22+
23+
///@cond PRIVATE
24+
25+
QString QgsPackageAlgorithm::name() const
26+
{
27+
return QStringLiteral( "package" );
28+
}
29+
30+
QString QgsPackageAlgorithm::displayName() const
31+
{
32+
return QObject::tr( "Package layers" );
33+
}
34+
35+
QStringList QgsPackageAlgorithm::tags() const
36+
{
37+
return QObject::tr( "geopackage,collect,merge,combine" ).split( ',' );
38+
}
39+
40+
QString QgsPackageAlgorithm::group() const
41+
{
42+
return QObject::tr( "Database" );
43+
}
44+
45+
void QgsPackageAlgorithm::initAlgorithm( const QVariantMap & )
46+
{
47+
addParameter( new QgsProcessingParameterMultipleLayers( QStringLiteral( "LAYERS" ), QObject::tr( "Input layers" ), QgsProcessing::TypeVector ) );
48+
addParameter( new QgsProcessingParameterFileDestination( QStringLiteral( "OUTPUT" ), QObject::tr( "Destination GeoPackage" ), QStringLiteral( "*.gpkg" ) ) );
49+
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "OVERWRITE" ), QObject::tr( "Overwrite existing GeoPackage" ), false ) );
50+
}
51+
52+
QString QgsPackageAlgorithm::shortHelpString() const
53+
{
54+
return QObject::tr( "This algorithm collects a number of existing layers and packages them together into a single GeoPackage database." );
55+
}
56+
57+
QgsPackageAlgorithm *QgsPackageAlgorithm::createInstance() const
58+
{
59+
return new QgsPackageAlgorithm();
60+
}
61+
62+
QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
63+
{
64+
bool overwrite = parameterAsBool( parameters, QStringLiteral( "OVERWRITE" ), context );
65+
QString packagePath = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );
66+
if ( packagePath.isEmpty() )
67+
throw QgsProcessingException( QObject::tr( "No output file specified." ) );
68+
69+
// delete existing geopackage if it exists
70+
if ( overwrite && QFile::exists( packagePath ) )
71+
{
72+
feedback->pushInfo( QObject::tr( "Removing existing file '%1'" ).arg( packagePath ) );
73+
if ( !QFile( packagePath ).remove() )
74+
{
75+
throw QgsProcessingException( QObject::tr( "Could not remove existing file '%1'" ) );
76+
}
77+
}
78+
79+
OGRSFDriverH hGpkgDriver = OGRGetDriverByName( "GPKG" );
80+
if ( !hGpkgDriver )
81+
{
82+
throw QgsProcessingException( QObject::tr( "GeoPackage driver not found." ) );
83+
}
84+
85+
gdal::ogr_datasource_unique_ptr hDS( OGR_Dr_CreateDataSource( hGpkgDriver, packagePath.toUtf8().constData(), nullptr ) );
86+
if ( !hDS )
87+
throw QgsProcessingException( QObject::tr( "Creation of database failed (OGR error: %1)" ).arg( QString::fromUtf8( CPLGetLastErrorMsg() ) ) );
88+
89+
bool errored = false;
90+
const QList< QgsMapLayer * > layers = parameterAsLayerList( parameters, QStringLiteral( "LAYERS" ), context );
91+
92+
QgsProcessingMultiStepFeedback multiStepFeedback( layers.count(), feedback );
93+
94+
int i = 0;
95+
for ( QgsMapLayer *layer : layers )
96+
{
97+
if ( feedback->isCanceled() )
98+
break;
99+
100+
multiStepFeedback.setCurrentStep( i );
101+
i++;
102+
103+
feedback->pushInfo( QObject::tr( "Packaging layer %1/%2: %3" ).arg( i ).arg( layers.count() ).arg( layer->name() ) );
104+
105+
if ( !layer )
106+
{
107+
// don't throw immediately - instead do what we can and error out later
108+
feedback->pushDebugInfo( QObject::tr( "Error retrieving map layer." ) );
109+
errored = true;
110+
continue;
111+
}
112+
113+
switch ( layer->type() )
114+
{
115+
case QgsMapLayer::VectorLayer:
116+
{
117+
if ( !packageVectorLayer( qobject_cast< QgsVectorLayer * >( layer ), packagePath,
118+
context, &multiStepFeedback ) )
119+
errored = true;
120+
break;
121+
}
122+
123+
case QgsMapLayer::RasterLayer:
124+
{
125+
//not supported
126+
feedback->pushDebugInfo( QObject::tr( "Raster layers are not currently supported." ) );
127+
errored = true;
128+
break;
129+
}
130+
131+
case QgsMapLayer::PluginLayer:
132+
//not supported
133+
feedback->pushDebugInfo( QObject::tr( "Packaging plugin layers is not supported." ) );
134+
errored = true;
135+
break;
136+
}
137+
}
138+
139+
if ( errored )
140+
throw QgsProcessingException( QObject::tr( "Error obtained while packaging one or more layers." ) );
141+
142+
QVariantMap outputs;
143+
outputs.insert( QStringLiteral( "OUTPUT" ), packagePath );
144+
return outputs;
145+
}
146+
147+
bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context,
148+
QgsProcessingFeedback *feedback )
149+
{
150+
QgsVectorFileWriter::SaveVectorOptions options;
151+
options.driverName = QStringLiteral( "GPKG" );
152+
options.layerName = layer->name();
153+
options.actionOnExistingFile = QgsVectorFileWriter::CreateOrOverwriteLayer;
154+
options.fileEncoding = context.defaultEncoding();
155+
options.feedback = feedback;
156+
157+
QString error;
158+
if ( QgsVectorFileWriter::writeAsVectorFormat( layer, path, options, &error ) != QgsVectorFileWriter::NoError )
159+
{
160+
feedback->pushDebugInfo( QObject::tr( "Packaging layer failed: %1" ).arg( error ) );
161+
return false;
162+
}
163+
else
164+
{
165+
return true;
166+
}
167+
}
168+
169+
///@endcond
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/***************************************************************************
2+
qgsalgorithmpackage.h
3+
------------------
4+
begin : November 2017
5+
copyright : (C) 2017 by Nyall Dawson
6+
email : nyall dot dawson at gmail dot com
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSALGORITHMPACKAGE_H
19+
#define QGSALGORITHMPACKAGE_H
20+
21+
#define SIP_NO_FILE
22+
23+
#include "qgis.h"
24+
#include "qgsprocessingalgorithm.h"
25+
26+
///@cond PRIVATE
27+
28+
class QgsVectorLayer;
29+
30+
/**
31+
* Native package layers algorithm.
32+
*/
33+
class QgsPackageAlgorithm : public QgsProcessingAlgorithm
34+
{
35+
36+
public:
37+
38+
QgsPackageAlgorithm() = default;
39+
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
40+
QString name() const override;
41+
QString displayName() const override;
42+
virtual QStringList tags() const override;
43+
QString group() const override;
44+
QString shortHelpString() const override;
45+
QgsPackageAlgorithm *createInstance() const override SIP_FACTORY;
46+
47+
protected:
48+
49+
virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
50+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
51+
52+
private:
53+
54+
bool packageVectorLayer( QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context, QgsProcessingFeedback *feedback );
55+
56+
};
57+
58+
///@endcond PRIVATE
59+
60+
#endif // QGSALGORITHMPACKAGE_H
61+
62+

src/analysis/processing/qgsnativealgorithms.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "qgsalgorithmminimumenclosingcircle.h"
4444
#include "qgsalgorithmmultiparttosinglepart.h"
4545
#include "qgsalgorithmorientedminimumboundingbox.h"
46+
#include "qgsalgorithmpackage.h"
4647
#include "qgsalgorithmpromotetomultipart.h"
4748
#include "qgsalgorithmrasterlayeruniquevalues.h"
4849
#include "qgsalgorithmremovenullgeometry.h"
@@ -118,6 +119,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
118119
addAlgorithm( new QgsMinimumEnclosingCircleAlgorithm() );
119120
addAlgorithm( new QgsMultipartToSinglepartAlgorithm() );
120121
addAlgorithm( new QgsOrientedMinimumBoundingBoxAlgorithm() );
122+
addAlgorithm( new QgsPackageAlgorithm() );
121123
addAlgorithm( new QgsPromoteToMultipartAlgorithm() );
122124
addAlgorithm( new QgsRasterLayerUniqueValuesReportAlgorithm() );
123125
addAlgorithm( new QgsRemoveNullGeometryAlgorithm() );

src/core/CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ SET(QGIS_CORE_SRCS
100100

101101
processing/qgsprocessingalgorithm.cpp
102102
processing/qgsprocessingalgrunnertask.cpp
103+
processing/qgsprocessingfeedback.cpp
103104
processing/qgsprocessingoutputs.cpp
104105
processing/qgsprocessingparameters.cpp
105106
processing/qgsprocessingprovider.cpp
@@ -706,7 +707,6 @@ SET(QGIS_CORE_MOC_HDRS
706707
processing/qgsprocessingfeedback.h
707708
processing/qgsprocessingprovider.h
708709
processing/qgsprocessingregistry.h
709-
processing/models/qgsprocessingmodelalgorithm.h
710710

711711
providers/memory/qgsmemoryprovider.h
712712

@@ -1024,6 +1024,7 @@ SET(QGIS_CORE_HDRS
10241024
processing/qgsprocessingoutputs.h
10251025
processing/qgsprocessingparameters.h
10261026
processing/qgsprocessingutils.h
1027+
processing/models/qgsprocessingmodelalgorithm.h
10271028
processing/models/qgsprocessingmodelchildalgorithm.h
10281029
processing/models/qgsprocessingmodelchildparametersource.h
10291030
processing/models/qgsprocessingmodelcomponent.h

0 commit comments

Comments
 (0)