Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #5168 from rldhont/release-2_18-server-getprint-gr…
…oup-order

[BUGFIX][Server] GetPrint request renders layers from group in wrong order
  • Loading branch information
rldhont committed Sep 12, 2017
2 parents 70cd0e4 + 9d12581 commit b035704
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 81 deletions.
4 changes: 4 additions & 0 deletions python/server/qgswmsconfigparser.sip
Expand Up @@ -35,6 +35,10 @@ class QgsWMSConfigParser
/** Fills a layer and a style list. The two list have the same number of entries and the style and the layer at a position belong together (similar to the HTTP parameters 'Layers' and 'Styles'. Returns 0 in case of success*/
virtual int layersAndStyles( QStringList& layers, QStringList& styles ) const = 0;

/** Creates a layer set and returns a stringlist with layer ids that can be passed to a QgsMapRenderer. Usually used in conjunction with readLayersAndStyles
@param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS, double scaleDenominator = -1 ) const;

/** Returns the xml fragment of a style*/
virtual QDomDocument getStyle( const QString& styleName, const QString& layerName ) const = 0;

Expand Down
87 changes: 80 additions & 7 deletions src/server/qgswmsconfigparser.cpp
Expand Up @@ -19,6 +19,8 @@
#include "qgsmaplayer.h"
#include "qgsmaplayerregistry.h"
#include "qgsmapserviceexception.h"
#include "qgslogger.h"
#include "qgsmessagelog.h"

#include "qgscomposerlabel.h"
#include "qgscomposerlegend.h"
Expand All @@ -45,6 +47,73 @@ QgsWMSConfigParser::~QgsWMSConfigParser()

}

QStringList QgsWMSConfigParser::layerSet( const QStringList &layersList,
const QStringList &stylesList,
const QgsCoordinateReferenceSystem &destCRS, double scaleDenominator ) const
{
Q_UNUSED( destCRS );
QStringList layerKeys;
QStringList::const_iterator llstIt;
QStringList::const_iterator slstIt;
QgsMapLayer* theMapLayer = nullptr;
QgsMessageLog::logMessage( QString( "Calculating layerset using %1 layers, %2 styles and CRS %3" ).arg( layersList.count() ).arg( stylesList.count() ).arg( destCRS.description() ) );
for ( llstIt = layersList.begin(), slstIt = stylesList.begin(); llstIt != layersList.end(); ++llstIt )
{
QString styleName;
if ( slstIt != stylesList.end() )
{
styleName = *slstIt;
}
QgsMessageLog::logMessage( "Trying to get layer " + *llstIt + "//" + styleName );

//does the layer name appear several times in the layer list?
//if yes, layer caching must be disabled because several named layers could have
//several user styles
bool allowCaching = true;
if ( layersList.count( *llstIt ) > 1 )
{
allowCaching = false;
}

QList<QgsMapLayer*> layerList = mapLayerFromStyle( *llstIt, styleName, allowCaching );
int listIndex;

for ( listIndex = layerList.size() - 1; listIndex >= 0; listIndex-- )
{
theMapLayer = layerList.at( listIndex );
if ( theMapLayer )
{
QString lName = theMapLayer->name();
if ( useLayerIDs() )
lName = theMapLayer->id();
else if ( !theMapLayer->shortName().isEmpty() )
lName = theMapLayer->shortName();
QgsMessageLog::logMessage( QString( "Checking layer: %1" ).arg( lName ) );
//test if layer is visible in requested scale
bool useScaleConstraint = ( scaleDenominator > 0 && theMapLayer->hasScaleBasedVisibility() );
if ( !useScaleConstraint ||
( theMapLayer->minimumScale() <= scaleDenominator && theMapLayer->maximumScale() >= scaleDenominator ) )
{
layerKeys.push_front( theMapLayer->id() );
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << theMapLayer, false, false );
}
}
else
{
QgsMessageLog::logMessage( "Layer or style not defined, aborting" );
throw QgsMapServiceException( "LayerNotDefined", "Layer '" + *llstIt + "' and/or style '" + styleName + "' not defined" );
}
}

if ( slstIt != stylesList.end() )
{
++slstIt;
}
}
return layerKeys;
}

QgsComposition* QgsWMSConfigParser::createPrintComposition( const QString& composerTemplate, QgsMapRenderer* mapRenderer, const QMap< QString, QString >& parameterMap ) const
{
QStringList highlightLayers;
Expand Down Expand Up @@ -144,10 +213,11 @@ QgsComposition* QgsWMSConfigParser::createPrintComposition( const QString& compo
}

//layers / styles
QStringList layerSet;
QgsCoordinateReferenceSystem dummyCRS;
QStringList mapLayerSet;
if ( currentMap->keepLayerSet() )
{
layerSet = currentMap->layerSet();
mapLayerSet = currentMap->layerSet();
}
else
{
Expand All @@ -169,6 +239,8 @@ QgsComposition* QgsWMSConfigParser::createPrintComposition( const QString& compo
wmsStyleList = styles.split( "," );
}

mapLayerSet = layerSet( wmsLayerList, wmsStyleList, dummyCRS );
/*
for ( int i = 0; i < wmsLayerList.size(); ++i )
{
QString styleName;
Expand All @@ -185,15 +257,16 @@ QgsComposition* QgsWMSConfigParser::createPrintComposition( const QString& compo
}
}
}
* */
}

//save layer list prior to adding highlight layers
QStringList bkLayerSet = layerSet;
QStringList bkLayerSet = mapLayerSet;

//add highlight layers
highlightLayers.append( addHighlightLayers( parameterMap, layerSet, mapId + ":" ) );
highlightLayers.append( addHighlightLayers( parameterMap, mapLayerSet, mapId + ":" ) );

currentMap->setLayerSet( layerSet );
currentMap->setLayerSet( mapLayerSet );
currentMap->setKeepLayerSet( true );

//remove highlight layers from the composer legends
Expand Down Expand Up @@ -233,8 +306,8 @@ QgsComposition* QgsWMSConfigParser::createPrintComposition( const QString& compo

// get model and layer tree root of the legend
QgsLegendModelV2* model = currentLegend->modelV2();
QStringList layerSet = map->layerSet();
setLayerIdsToLegendModel( model, layerSet, map->scale() );
QStringList mapLayerSet = map->layerSet();
setLayerIdsToLegendModel( model, mapLayerSet, map->scale() );
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/server/qgswmsconfigparser.h
Expand Up @@ -46,6 +46,10 @@ class SERVER_EXPORT QgsWMSConfigParser
/** Fills a layer and a style list. The two list have the same number of entries and the style and the layer at a position belong together (similar to the HTTP parameters 'Layers' and 'Styles'. Returns 0 in case of success*/
virtual int layersAndStyles( QStringList& layers, QStringList& styles ) const = 0;

/** Creates a layer set and returns a stringlist with layer ids that can be passed to a QgsMapRenderer. Usually used in conjunction with readLayersAndStyles
@param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS, double scaleDenominator = -1 ) const;

/** Returns the xml fragment of a style*/
virtual QDomDocument getStyle( const QString& styleName, const QString& layerName ) const = 0;

Expand Down
73 changes: 3 additions & 70 deletions src/server/qgswmsserver.cpp
Expand Up @@ -779,7 +779,7 @@ QImage* QgsWMSServer::getLegendGraphics()
}

QgsCoordinateReferenceSystem dummyCRS;
QStringList layerIds = layerSet( layersList, stylesList, dummyCRS, scaleDenominator );
QStringList layerIds = mConfigParser->layerSet( layersList, stylesList, dummyCRS, scaleDenominator );
if ( layerIds.size() < 1 )
{
return nullptr;
Expand Down Expand Up @@ -1690,7 +1690,7 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, const QString& version )
}

//get the layer registered in QgsMapLayerRegistry and apply possible filters
( void )layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
( void )mConfigParser->layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );

//scoped pointer to restore all original layer filters (subsetStrings) when pointer goes out of scope
//there's LOTS of potential exit paths here, so we avoid having to restore the filters manually
Expand Down Expand Up @@ -1967,7 +1967,7 @@ QImage* QgsWMSServer::initializeRendering( QStringList& layersList, QStringList&
QgsRectangle mapExtent = mMapRenderer->extent();
mConfigParser->setScaleDenominator( scaleCalc.calculate( mapExtent, theImage->width() ) );

layerIdList = layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
layerIdList = mConfigParser->layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
#ifdef QGISDEBUG
QgsMessageLog::logMessage( QString( "Number of layers to be rendered. %1" ).arg( layerIdList.count() ) );
#endif
Expand Down Expand Up @@ -2597,73 +2597,6 @@ int QgsWMSServer::featureInfoFromRasterLayer( QgsRasterLayer* layer,
return 0;
}

QStringList QgsWMSServer::layerSet( const QStringList &layersList,
const QStringList &stylesList,
const QgsCoordinateReferenceSystem &destCRS, double scaleDenominator ) const
{
Q_UNUSED( destCRS );
QStringList layerKeys;
QStringList::const_iterator llstIt;
QStringList::const_iterator slstIt;
QgsMapLayer* theMapLayer = nullptr;
QgsMessageLog::logMessage( QString( "Calculating layerset using %1 layers, %2 styles and CRS %3" ).arg( layersList.count() ).arg( stylesList.count() ).arg( destCRS.description() ) );
for ( llstIt = layersList.begin(), slstIt = stylesList.begin(); llstIt != layersList.end(); ++llstIt )
{
QString styleName;
if ( slstIt != stylesList.end() )
{
styleName = *slstIt;
}
QgsMessageLog::logMessage( "Trying to get layer " + *llstIt + "//" + styleName );

//does the layer name appear several times in the layer list?
//if yes, layer caching must be disabled because several named layers could have
//several user styles
bool allowCaching = true;
if ( layersList.count( *llstIt ) > 1 )
{
allowCaching = false;
}

QList<QgsMapLayer*> layerList = mConfigParser->mapLayerFromStyle( *llstIt, styleName, allowCaching );
int listIndex;

for ( listIndex = layerList.size() - 1; listIndex >= 0; listIndex-- )
{
theMapLayer = layerList.at( listIndex );
if ( theMapLayer )
{
QString lName = theMapLayer->name();
if ( mConfigParser && mConfigParser->useLayerIDs() )
lName = theMapLayer->id();
else if ( !theMapLayer->shortName().isEmpty() )
lName = theMapLayer->shortName();
QgsMessageLog::logMessage( QString( "Checking layer: %1" ).arg( lName ) );
//test if layer is visible in requested scale
bool useScaleConstraint = ( scaleDenominator > 0 && theMapLayer->hasScaleBasedVisibility() );
if ( !useScaleConstraint ||
( theMapLayer->minimumScale() <= scaleDenominator && theMapLayer->maximumScale() >= scaleDenominator ) )
{
layerKeys.push_front( theMapLayer->id() );
QgsMapLayerRegistry::instance()->addMapLayers(
QList<QgsMapLayer *>() << theMapLayer, false, false );
}
}
else
{
QgsMessageLog::logMessage( "Layer or style not defined, aborting" );
throw QgsMapServiceException( "LayerNotDefined", "Layer '" + *llstIt + "' and/or style '" + styleName + "' not defined" );
}
}

if ( slstIt != stylesList.end() )
{
++slstIt;
}
}
return layerKeys;
}


void QgsWMSServer::applyRequestedLayerFilters( const QStringList& layerList , QHash<QgsMapLayer*, QString>& originalFilters ) const
{
Expand Down
4 changes: 0 additions & 4 deletions src/server/qgswmsserver.h
Expand Up @@ -171,10 +171,6 @@ class QgsWMSServer: public QgsOWSServer
const QString& version,
const QString& infoFormat ) const;

/** Creates a layer set and returns a stringlist with layer ids that can be passed to a QgsMapRenderer. Usually used in conjunction with readLayersAndStyles
@param scaleDenominator Filter out layer if scale based visibility does not match (or use -1 if no scale restriction)*/
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS, double scaleDenominator = -1 ) const;

/** Record which symbols would be used if the map was in the current configuration of mMapRenderer. This is useful for content-based legend*/
void runHitTest( QPainter* painter, HitTest& hitTest );
/** Record which symbols within one layer would be rendered with the given renderer context*/
Expand Down

0 comments on commit b035704

Please sign in to comment.