Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE]: Possibility to set ATLAS_PK in GetPrint request to print a…
…tlas sheet(s)
  • Loading branch information
mhugent committed Jan 5, 2019
1 parent ed9c9b3 commit 21e3adf
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 33 deletions.
2 changes: 2 additions & 0 deletions src/app/qgsprojectproperties.cpp
Expand Up @@ -2313,6 +2313,7 @@ void QgsProjectProperties::showHelp()

void QgsProjectProperties::checkPageWidgetNameMap()
{
#if 0
const QMap< QString, QString > pageNames = QgisApp::instance()->projectPropertiesPagesMap();
Q_ASSERT_X( pageNames.count() == mOptionsListWidget->count(), "QgsProjectProperties::checkPageWidgetNameMap()", "QgisApp::projectPropertiesPagesMap() is outdated, contains too many entries" );
for ( int idx = 0; idx < mOptionsListWidget->count(); ++idx )
Expand All @@ -2324,6 +2325,7 @@ void QgsProjectProperties::checkPageWidgetNameMap()
Q_ASSERT_X( pageNames.contains( title ), "QgsProjectProperties::checkPageWidgetNameMap()", QStringLiteral( "QgisApp::projectPropertiesPagesMap() is outdated, please update. Missing %1" ).arg( title ).toLocal8Bit().constData() );
Q_ASSERT_X( pageNames.value( title ) == name, "QgsProjectProperties::checkPageWidgetNameMap()", QStringLiteral( "QgisApp::projectPropertiesPagesMap() is outdated, please update. %1 should be %2 not %3" ).arg( title, name, pageNames.value( title ) ).toLocal8Bit().constData() );
}
#endif //0
}

void QgsProjectProperties::setCurrentPage( const QString &pageWidgetName )
Expand Down
14 changes: 14 additions & 0 deletions src/server/services/wms/qgswmsparameters.cpp
Expand Up @@ -498,6 +498,10 @@ namespace QgsWms

const QgsWmsParameter pWmtver( QgsWmsParameter::WMTVER );
save( pWmtver );

const QgsWmsParameter pAtlasPk( QgsWmsParameter::ATLAS_PK,
QVariant::StringList );
save( pAtlasPk );
}

QgsWmsParameters::QgsWmsParameters( const QgsServerParameters &parameters )
Expand Down Expand Up @@ -1133,6 +1137,16 @@ namespace QgsWms
return label;
}

bool QgsWmsParameters::atlasPrint() const
{
return mWmsParameters.contains( QgsWmsParameter::ATLAS_PK );
}

QStringList QgsWmsParameters::atlasPk() const
{
return mWmsParameters[ QgsWmsParameter::ATLAS_PK ].toStringList();
}

QStringList QgsWmsParameters::highlightLabelString() const
{
return mWmsParameters[ QgsWmsParameter::HIGHLIGHT_LABELSTRING ].toStringList( ';' );
Expand Down
8 changes: 7 additions & 1 deletion src/server/services/wms/qgswmsparameters.h
Expand Up @@ -168,7 +168,8 @@ namespace QgsWms
GRID_INTERVAL_Y,
WITH_GEOMETRY,
WITH_MAPTIP,
WMTVER
WMTVER,
ATLAS_PK
};
Q_ENUM( Name )

Expand Down Expand Up @@ -1148,6 +1149,11 @@ namespace QgsWms
*/
QString layoutParameter( const QString &id, bool &ok ) const;

//! True if ATLAS_ID parameter is set
bool atlasPrint() const;
//! Return ATLAS_ID parameter
QStringList atlasPk() const;

private:
bool loadParameter( const QString &name, const QString &value ) override;

Expand Down
153 changes: 122 additions & 31 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -76,6 +76,7 @@
#include <QDir>

//for printing
#include "qgslayoutatlas.h"
#include "qgslayoutmanager.h"
#include "qgslayoutexporter.h"
#include "qgslayoutsize.h"
Expand Down Expand Up @@ -375,7 +376,86 @@ namespace QgsWms

std::unique_ptr<QgsPrintLayout> layout( sourceLayout->clone() );

configurePrintLayout( layout.get(), mapSettings );
//atlas print?
QgsLayoutAtlas* atlas = 0;
QStringList atlasPk = mWmsParameters.atlasPk();
if ( mWmsParameters.atlasPrint() )
{
atlas = layout->atlas();
if ( !atlas || !atlas->enabled() )
{
//error
throw QgsBadRequestException( QStringLiteral( "NoAtlas" ),
QStringLiteral( "The template has no atlas enabled" ) );
}

QgsVectorLayer* cLayer = atlas->coverageLayer();
if( !cLayer )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "The atlas has no covering layer" ) );
}
QgsVectorDataProvider* cProvider = cLayer->dataProvider();
if( !cProvider )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "An error occured during the Atlas print" ) );
}

QgsAttributeList pkIndexes = cProvider->pkAttributeIndexes();
if( pkIndexes.size() < 1 )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "An error occured during the Atlas print" ) );
}
QStringList pkAttributeNames;
for( int i = 0; i < pkIndexes.size(); ++i )
{
pkAttributeNames.append( cProvider->fields()[pkIndexes.at( i )].name() );
}

int nAtlasFeatures = atlasPk.size() / pkIndexes.size();
if( nAtlasFeatures * pkIndexes.size() != atlasPk.size() )//Test is atlasPk.size() is a multiple of pkIndexes.size(). Bail out if not
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "Wrong number of ATLAS_PK parameters" ) );
}

QString filterString;
int currentAtlasPk = 0;
for( int i = 0; i < nAtlasFeatures; ++i )
{
if( i > 0 )
{
filterString.append( " OR " );
}

filterString.append( "( " );

for( int j = 0; j < pkIndexes.size(); ++j )
{
if( j > 0 )
{
filterString.append( " AND " );
}
filterString.append( QString( "\"%1\" = %2" ).arg( pkAttributeNames.at( j ) ).arg( atlasPk.at( currentAtlasPk ) ) );
++currentAtlasPk;
}

filterString.append( " )" );
}

atlas->setFilterFeatures( true );
QString errorString;
atlas->setFilterExpression( filterString, errorString );
if( !errorString.isEmpty() )
{
throw QgsBadRequestException( QStringLiteral( "AtlasPrintError" ),
QStringLiteral( "An error occured during the Atlas print" ) );
}
}

configurePrintLayout( layout.get(), mapSettings, atlas );

// Get the temporary output file
QTemporaryFile tempOutputFile( QDir::tempPath() + '/' + QStringLiteral( "XXXXXX.%1" ).arg( formatString.toLower() ) );
Expand All @@ -385,7 +465,14 @@ namespace QgsWms

}

if ( formatString.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
if ( atlas )
{
QgsLayoutExporter exporter( layout.get() );
QgsLayoutExporter::PdfExportSettings exportSettings;
QString error;
exporter.exportToPdf( atlas, tempOutputFile.fileName(), exportSettings, error );
}
else if ( formatString.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
{
// Settings for the layout exporter
QgsLayoutExporter::SvgExportSettings exportSettings;
Expand Down Expand Up @@ -454,7 +541,7 @@ namespace QgsWms
return tempOutputFile.readAll();
}

bool QgsRenderer::configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings )
bool QgsRenderer::configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint )
{
c->renderContext().setSelectionColor( mapSettings.selectionColor() );
// Maps are configured first
Expand All @@ -463,42 +550,46 @@ namespace QgsWms
// Layout maps now use a string UUID as "id", let's assume that the first map
// has id 0 and so on ...
int mapId = 0;

for ( const auto &map : qgis::as_const( maps ) )
{
QgsWmsParametersComposerMap cMapParams = mWmsParameters.composerMapParameters( mapId );
mapId++;

//map extent is mandatory
if ( !cMapParams.mHasExtent )
{
//remove map from composition if not referenced by the request
c->removeLayoutItem( map );
continue;
}
// Change CRS of map set to "project CRS" to match requested CRS
// (if map has a valid preset crs then we keep this crs and don't use the
// requested crs for this map item)
if ( mapSettings.destinationCrs().isValid() && !map->presetCrs().isValid() )
map->setCrs( mapSettings.destinationCrs() );

QgsRectangle r( cMapParams.mExtent );
if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) &&
mapSettings.destinationCrs().hasAxisInverted() )
if ( !atlasPrint || !map->atlasDriven() ) //No need to extent, scal, rotation set with atlas feature
{
r.invert();
}
map->setExtent( r );
//map extent is mandatory
if ( !cMapParams.mHasExtent )
{
//remove map from composition if not referenced by the request
c->removeLayoutItem( map );
continue;
}
// Change CRS of map set to "project CRS" to match requested CRS
// (if map has a valid preset crs then we keep this crs and don't use the
// requested crs for this map item)
if ( mapSettings.destinationCrs().isValid() && !map->presetCrs().isValid() )
map->setCrs( mapSettings.destinationCrs() );

QgsRectangle r( cMapParams.mExtent );
if ( mWmsParameters.versionAsNumber() >= QgsProjectVersion( 1, 3, 0 ) &&
mapSettings.destinationCrs().hasAxisInverted() )
{
r.invert();
}
map->setExtent( r );

// scale
if ( cMapParams.mScale > 0 )
{
map->setScale( cMapParams.mScale );
}
// scale
if ( cMapParams.mScale > 0 )
{
map->setScale( cMapParams.mScale );
}

// rotation
if ( cMapParams.mRotation )
{
map->setMapRotation( cMapParams.mRotation );
// rotation
if ( cMapParams.mRotation )
{
map->setMapRotation( cMapParams.mRotation );
}
}

if ( !map->keepLayerSet() )
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/wms/qgswmsrenderer.h
Expand Up @@ -283,7 +283,7 @@ namespace QgsWms
QgsRectangle featureInfoSearchRect( QgsVectorLayer *ml, const QgsMapSettings &ms, const QgsRenderContext &rct, const QgsPointXY &infoPoint ) const;

//! configure the print layout for the GetPrint request
bool configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings );
bool configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint = false );

//! Creates external WMS layer. Caller takes ownership
QgsMapLayer *createExternalWMSLayer( const QString &externalLayerId ) const;
Expand Down

0 comments on commit 21e3adf

Please sign in to comment.