diff --git a/src/core/qgsabstractgeopdfexporter.h b/src/core/qgsabstractgeopdfexporter.h index 39f30a3cf490..359304343ee8 100644 --- a/src/core/qgsabstractgeopdfexporter.h +++ b/src/core/qgsabstractgeopdfexporter.h @@ -131,8 +131,11 @@ class CORE_EXPORT QgsAbstractGeoPdfExporter /** * To be called after the rendering operation is complete. * - * Will export the list of PDF layer \a components to a new PDF file at \a destinationFile. Any features - * previously collected by calls to pushRenderedFeature() will be included automatically in the GeoPDF + * Will export the list of PDF layer \a components to a new PDF file at \a destinationFile. The \a components + * argument gives a list of additional layers to include in the generated PDF file. These must have already + * been created, e.g. as a result of rendering layers to seperate PDF source files. + * + * Any features previously collected by calls to pushRenderedFeature() will be included automatically in the GeoPDF * export. * * Returns TRUE if the operation was successful, or FALSE if an error occurred. If an error occurred, it diff --git a/tests/src/core/testqgsgeopdfexport.cpp b/tests/src/core/testqgsgeopdfexport.cpp index fc46f12c3a4a..03a600286213 100644 --- a/tests/src/core/testqgsgeopdfexport.cpp +++ b/tests/src/core/testqgsgeopdfexport.cpp @@ -55,6 +55,7 @@ class TestQgsGeoPdfExport : public QObject void init();// will be called before each testfunction is executed. void cleanup();// will be called after every testfunction. void testCollectingFeatures(); + void testComposition(); private: @@ -174,5 +175,93 @@ void TestQgsGeoPdfExport::testCollectingFeatures() QCOMPARE( f.geometry().asWkt(), QStringLiteral( "LineString (1 1, 2 2)" ) ); } +void TestQgsGeoPdfExport::testComposition() +{ + if ( !QgsAbstractGeoPdfExporter::geoPDFCreationAvailable() ) + { + QSKIP( "This test requires GeoPDF creation abilities", SkipSingle ); + } + + TestGeoPdfExporter geoPdfExporter; + // no features, no crash + QVERIFY( geoPdfExporter.saveTemporaryLayers() ); + QCOMPARE( geoPdfExporter.mVectorComponents.count(), 0 ); + + QgsFields fields; + fields.append( QgsField( QStringLiteral( "a1" ), QVariant::Int ) ); + fields.append( QgsField( QStringLiteral( "a2" ), QVariant::Int ) ); + QgsFeature f( fields ); + + f.setAttributes( QgsAttributes() << 1 << 2 ); + f.setGeometry( QgsGeometry( new QgsPoint( 1, 2 ) ) ); + QgsGeometry renderedBounds( QgsGeometry::fromRect( QgsRectangle( 1, 10, 6, 20 ) ) ); + geoPdfExporter.pushRenderedFeature( QStringLiteral( "layer1" ), QgsAbstractGeoPdfExporter::RenderedFeature( f, renderedBounds ) ); + f.setAttributes( QgsAttributes() << 31 << 32 ); + f.setGeometry( QgsGeometry( new QgsPoint( 4, 5 ) ) ); + renderedBounds = QgsGeometry::fromWkt( QStringLiteral( "LineString(1 1, 2 2)" ) ); + geoPdfExporter.pushRenderedFeature( QStringLiteral( "layer2" ), QgsAbstractGeoPdfExporter::RenderedFeature( f, renderedBounds ) ); + + QVERIFY( geoPdfExporter.saveTemporaryLayers() ); + QgsAbstractGeoPdfExporter::VectorComponentDetail component; + QString layer1Path; + QString layer1Layer; + QString layer2Path; + QString layer2Layer; + + for ( const auto &it : qgis::as_const( geoPdfExporter.mVectorComponents ) ) + { + if ( it.mapLayerId == QStringLiteral( "layer1" ) ) + { + layer1Path = it.sourceVectorPath; + layer1Layer = it.sourceVectorLayer; + } + else if ( it.mapLayerId == QStringLiteral( "layer2" ) ) + { + layer2Path = it.sourceVectorPath; + layer2Layer = it.sourceVectorLayer; + } + } + + // test creation of the composition xml + QList< QgsAbstractGeoPdfExporter::ComponentLayerDetail > renderedLayers; // no extra layers for now + QString composition = geoPdfExporter.createCompositionXml( renderedLayers ); + QgsDebugMsg( composition ); + QDomDocument doc; + doc.setContent( composition ); + QDomNodeList ifLayerOnList = doc.elementsByTagName( QStringLiteral( "IfLayerOn" ) ); + QCOMPARE( ifLayerOnList.count(), 2 ); + + int layer1Idx = ifLayerOnList.at( 0 ).toElement().attribute( QStringLiteral( "layerId" ) ) == QStringLiteral( "layer1" ) ? 0 : 1; + int layer2Idx = layer1Idx == 0 ? 1 : 0; + QCOMPARE( ifLayerOnList.at( layer1Idx ).toElement().attribute( QStringLiteral( "layerId" ) ), QStringLiteral( "layer1" ) ); + QCOMPARE( ifLayerOnList.at( layer1Idx ).toElement().elementsByTagName( QStringLiteral( "Vector" ) ).at( 0 ).toElement().attribute( QStringLiteral( "dataset" ) ), layer1Path ); + QCOMPARE( ifLayerOnList.at( layer1Idx ).toElement().elementsByTagName( QStringLiteral( "Vector" ) ).at( 0 ).toElement().attribute( QStringLiteral( "layer" ) ), layer1Layer ); + QCOMPARE( ifLayerOnList.at( layer1Idx ).toElement().elementsByTagName( QStringLiteral( "Vector" ) ).at( 0 ).toElement().attribute( QStringLiteral( "visible" ) ), QStringLiteral( "false" ) ); + QCOMPARE( ifLayerOnList.at( layer1Idx ).toElement().elementsByTagName( QStringLiteral( "LogicalStructure" ) ).at( 0 ).toElement().attribute( QStringLiteral( "fieldToDisplay" ) ), QStringLiteral( "attr layer1" ) ); + QCOMPARE( ifLayerOnList.at( layer1Idx ).toElement().elementsByTagName( QStringLiteral( "LogicalStructure" ) ).at( 0 ).toElement().attribute( QStringLiteral( "displayLayerName" ) ), QStringLiteral( "name layer1" ) ); + + QCOMPARE( ifLayerOnList.at( layer2Idx ).toElement().attribute( QStringLiteral( "layerId" ) ), QStringLiteral( "layer2" ) ); + QCOMPARE( ifLayerOnList.at( layer2Idx ).toElement().elementsByTagName( QStringLiteral( "Vector" ) ).at( 0 ).toElement().attribute( QStringLiteral( "dataset" ) ), layer2Path ); + QCOMPARE( ifLayerOnList.at( layer2Idx ).toElement().elementsByTagName( QStringLiteral( "Vector" ) ).at( 0 ).toElement().attribute( QStringLiteral( "layer" ) ), layer2Layer ); + QCOMPARE( ifLayerOnList.at( layer2Idx ).toElement().elementsByTagName( QStringLiteral( "Vector" ) ).at( 0 ).toElement().attribute( QStringLiteral( "visible" ) ), QStringLiteral( "false" ) ); + QCOMPARE( ifLayerOnList.at( layer2Idx ).toElement().elementsByTagName( QStringLiteral( "LogicalStructure" ) ).at( 0 ).toElement().attribute( QStringLiteral( "fieldToDisplay" ) ), QStringLiteral( "attr layer2" ) ); + QCOMPARE( ifLayerOnList.at( layer2Idx ).toElement().elementsByTagName( QStringLiteral( "LogicalStructure" ) ).at( 0 ).toElement().attribute( QStringLiteral( "displayLayerName" ) ), QStringLiteral( "name layer2" ) ); + + + QDomNodeList layerTreeList = doc.elementsByTagName( QStringLiteral( "LayerTree" ) ).at( 0 ).toElement().childNodes(); + QCOMPARE( layerTreeList.count(), 2 ); + + layer1Idx = layerTreeList.at( 0 ).toElement().attribute( QStringLiteral( "id" ) ) == QStringLiteral( "layer1" ) ? 0 : 1; + layer2Idx = layer1Idx == 0 ? 1 : 0; + QCOMPARE( layerTreeList.at( layer1Idx ).toElement().attribute( QStringLiteral( "id" ) ), QStringLiteral( "layer1" ) ); + QCOMPARE( layerTreeList.at( layer1Idx ).toElement().attribute( QStringLiteral( "name" ) ), QStringLiteral( "name layer1" ) ); + QCOMPARE( layerTreeList.at( layer1Idx ).toElement().attribute( QStringLiteral( "initiallyVisible" ) ), QStringLiteral( "true" ) ); + + QCOMPARE( layerTreeList.at( layer2Idx ).toElement().attribute( QStringLiteral( "id" ) ), QStringLiteral( "layer2" ) ); + QCOMPARE( layerTreeList.at( layer2Idx ).toElement().attribute( QStringLiteral( "name" ) ), QStringLiteral( "name layer2" ) ); + QCOMPARE( layerTreeList.at( layer2Idx ).toElement().attribute( QStringLiteral( "initiallyVisible" ) ), QStringLiteral( "true" ) ); + +} + QGSTEST_MAIN( TestQgsGeoPdfExport ) #include "testqgsgeopdfexport.moc"