Skip to content

Commit

Permalink
[feature][processing] Add option to save layer metadata to Package
Browse files Browse the repository at this point in the history
Layers algorithm

If checked, this option copies the source layer metadata into the
geopackage so that it will be used as the default metadata for the
layer.
  • Loading branch information
nyalldawson committed May 10, 2021
1 parent 750a68f commit 1b69cef
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
11 changes: 9 additions & 2 deletions src/analysis/processing/qgsalgorithmpackage.cpp
Expand Up @@ -57,6 +57,7 @@ void QgsPackageAlgorithm::initAlgorithm( const QVariantMap & )
addParameter( outputParameter );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "OVERWRITE" ), QObject::tr( "Overwrite existing GeoPackage" ), false ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SAVE_STYLES" ), QObject::tr( "Save layer styles into GeoPackage" ), true ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SAVE_METADATA" ), QObject::tr( "Save layer metadata into GeoPackage" ), true ) );
addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "SELECTED_FEATURES_ONLY" ), QObject::tr( "Save only selected features" ), false ) );
addOutput( new QgsProcessingOutputMultipleLayers( QStringLiteral( "OUTPUT_LAYERS" ), QObject::tr( "Layers within new package" ) ) );
}
Expand Down Expand Up @@ -89,6 +90,7 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters
{
const bool overwrite = parameterAsBoolean( parameters, QStringLiteral( "OVERWRITE" ), context );
const bool saveStyles = parameterAsBoolean( parameters, QStringLiteral( "SAVE_STYLES" ), context );
const bool saveMetadata = parameterAsBoolean( parameters, QStringLiteral( "SAVE_METADATA" ), context );
const bool selectedFeaturesOnly = parameterAsBoolean( parameters, QStringLiteral( "SELECTED_FEATURES_ONLY" ), context );
QString packagePath = parameterAsString( parameters, QStringLiteral( "OUTPUT" ), context );
if ( packagePath.isEmpty() )
Expand Down Expand Up @@ -156,7 +158,7 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters
{
QgsVectorLayer *vectorLayer = qobject_cast<QgsVectorLayer *>( layer.get() );
bool onlySaveSelected = vectorLayer->selectedFeatureCount() > 0 && selectedFeaturesOnly;
if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, onlySaveSelected ) )
if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, saveMetadata, onlySaveSelected ) )
errored = true;
else
outputLayers.append( QStringLiteral( "%1|layername=%2" ).arg( packagePath, layer->name() ) );
Expand Down Expand Up @@ -213,7 +215,7 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap &parameters
}

bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context,
QgsProcessingFeedback *feedback, bool saveStyles, bool selectedFeaturesOnly )
QgsProcessingFeedback *feedback, bool saveStyles, bool saveMetadata, bool selectedFeaturesOnly )
{
QgsVectorFileWriter::SaveVectorOptions options;
options.driverName = QStringLiteral( "GPKG" );
Expand All @@ -222,6 +224,11 @@ bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QStri
options.fileEncoding = context.defaultEncoding();
options.onlySelectedFeatures = selectedFeaturesOnly;
options.feedback = feedback;
if ( saveMetadata )
{
options.layerMetadata = layer->metadata();
options.saveMetadata = true;
}

// remove any existing FID field, let this be completely recreated
// since many layer sources have fid fields which are not compatible with gpkg requirements
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmpackage.h
Expand Up @@ -55,7 +55,7 @@ class QgsPackageAlgorithm : public QgsProcessingAlgorithm
private:

bool packageVectorLayer( QgsVectorLayer *layer, const QString &path, QgsProcessingContext &context, QgsProcessingFeedback *feedback,
bool saveStyles, bool selectedFeaturesOnly );
bool saveStyles, bool saveMetadata, bool selectedFeaturesOnly );

std::vector< std::unique_ptr< QgsMapLayer> > mLayers;

Expand Down
28 changes: 22 additions & 6 deletions tests/src/analysis/testqgsprocessingalgs.cpp
Expand Up @@ -291,7 +291,7 @@ void TestQgsProcessingAlgs::cleanupTestCase()
QgsApplication::exitQgis();
}

QVariantMap pkgAlg( const QStringList &layers, const QString &outputGpkg, bool overwrite, bool selectedFeaturesOnly, bool *ok )
QVariantMap pkgAlg( const QStringList &layers, const QString &outputGpkg, bool overwrite, bool selectedFeaturesOnly, bool saveMetadata, bool *ok )
{
const QgsProcessingAlgorithm *package( QgsApplication::processingRegistry()->algorithmById( QStringLiteral( "native:package" ) ) );

Expand All @@ -305,6 +305,7 @@ QVariantMap pkgAlg( const QStringList &layers, const QString &outputGpkg, bool o
parameters.insert( QStringLiteral( "OUTPUT" ), outputGpkg );
parameters.insert( QStringLiteral( "OVERWRITE" ), overwrite );
parameters.insert( QStringLiteral( "SELECTED_FEATURES_ONLY" ), selectedFeaturesOnly );
parameters.insert( QStringLiteral( "SAVE_METADATA" ), saveMetadata );
return package->run( parameters, *context, &feedback, ok );
}

Expand Down Expand Up @@ -391,7 +392,7 @@ void TestQgsProcessingAlgs::packageAlg()
QVariantMap parameters;
QStringList layers = QStringList() << mPointsLayer->id() << mPolygonLayer->id();
bool ok = false;
QVariantMap results = pkgAlg( layers, outputGpkg, true, false, &ok );
QVariantMap results = pkgAlg( layers, outputGpkg, true, false, false, &ok );
QVERIFY( ok );

QVERIFY( !results.value( QStringLiteral( "OUTPUT" ) ).toString().isEmpty() );
Expand All @@ -409,9 +410,12 @@ void TestQgsProcessingAlgs::packageAlg()
std::unique_ptr<QgsVectorLayer> rectangles = std::make_unique<QgsVectorLayer>( QStringLiteral( TEST_DATA_DIR ) + "/rectangles.shp",
QStringLiteral( "rectangles" ), QStringLiteral( "ogr" ) );
QgsProject::instance()->addMapLayers( QList<QgsMapLayer *>() << rectangles.get() );
QgsLayerMetadata metadata;
metadata.setFees( QStringLiteral( "lots of dogecoin" ) );
rectangles->setMetadata( metadata );

// Test adding an additional layer (overwrite disabled)
QVariantMap results2 = pkgAlg( QStringList() << rectangles->id(), outputGpkg, false, false, &ok );
QVariantMap results2 = pkgAlg( QStringList() << rectangles->id(), outputGpkg, false, false, false, &ok );
QVERIFY( ok );

QVERIFY( !results2.value( QStringLiteral( "OUTPUT" ) ).toString().isEmpty() );
Expand All @@ -426,7 +430,7 @@ void TestQgsProcessingAlgs::packageAlg()
pointLayer.reset();

// And finally, test with overwrite enabled
QVariantMap results3 = pkgAlg( QStringList() << rectangles->id(), outputGpkg, true, false, &ok );
QVariantMap results3 = pkgAlg( QStringList() << rectangles->id(), outputGpkg, true, false, false, &ok );
QVERIFY( ok );

QVERIFY( !results2.value( QStringLiteral( "OUTPUT" ) ).toString().isEmpty() );
Expand All @@ -438,9 +442,21 @@ void TestQgsProcessingAlgs::packageAlg()
pointLayer = std::make_unique< QgsVectorLayer >( outputGpkg + "|layername=points", "points", "ogr" );
QVERIFY( !pointLayer->isValid() ); // It's gone -- the gpkg was recreated with a single layer

QCOMPARE( rectanglesPackagedLayer->metadata().fees(), QString() );
rectanglesPackagedLayer.reset();

// save layer metadata
results3 = pkgAlg( QStringList() << rectangles->id(), outputGpkg, true, false, true, &ok );
QVERIFY( ok );
rectanglesPackagedLayer = std::make_unique< QgsVectorLayer >( outputGpkg + "|layername=rectangles", "points", "ogr" );
QVERIFY( rectanglesPackagedLayer->isValid() );
QCOMPARE( rectanglesPackagedLayer->wkbType(), rectanglesPackagedLayer->wkbType() );
QCOMPARE( rectanglesPackagedLayer->featureCount(), rectangles->featureCount() );
QCOMPARE( rectanglesPackagedLayer->metadata().fees(), QStringLiteral( "lots of dogecoin" ) );

// Test saving of selected features only
mPolygonLayer->selectByIds( QgsFeatureIds() << 1 << 2 << 3 );
QVariantMap results4 = pkgAlg( QStringList() << mPolygonLayer->id(), outputGpkg, false, true, &ok );
QVariantMap results4 = pkgAlg( QStringList() << mPolygonLayer->id(), outputGpkg, false, true, false, &ok );
QVERIFY( ok );

QVERIFY( !results4.value( QStringLiteral( "OUTPUT" ) ).toString().isEmpty() );
Expand All @@ -451,7 +467,7 @@ void TestQgsProcessingAlgs::packageAlg()
selectedPolygonsPackagedLayer.reset();

mPolygonLayer->removeSelection();
QVariantMap results5 = pkgAlg( QStringList() << mPolygonLayer->id(), outputGpkg, false, true, &ok );
QVariantMap results5 = pkgAlg( QStringList() << mPolygonLayer->id(), outputGpkg, false, true, false, &ok );
QVERIFY( ok );

QVERIFY( !results5.value( QStringLiteral( "OUTPUT" ) ).toString().isEmpty() );
Expand Down

0 comments on commit 1b69cef

Please sign in to comment.