Skip to content

Commit

Permalink
Merge pull request #9699 from pblottiere/server_split
Browse files Browse the repository at this point in the history
[server] Move specialised funtions in correponding service cpp files
  • Loading branch information
pblottiere committed Apr 9, 2019
2 parents ae17fb3 + 9b298ca commit c2840a2
Show file tree
Hide file tree
Showing 9 changed files with 401 additions and 277 deletions.
16 changes: 16 additions & 0 deletions python/core/auto_generated/layertree/qgslayertreelayer.sip.in
Expand Up @@ -76,6 +76,21 @@ Sets the layer's name.
.. seealso:: :py:func:`name`

.. versionadded:: 3.0
%End

void setUseLayerName( bool use = true );
%Docstring
Uses the layer's name if ``use`` is true, or the name manually set if
false.

.. versionadded:: 3.8
%End

bool useLayerName() const;
%Docstring
Returns whether the layer's name is used, or the name manually set.

.. versionadded:: 3.8
%End

static QgsLayerTreeLayer *readXml( QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
Expand Down Expand Up @@ -127,6 +142,7 @@ Emitted when a previously available layer got unloaded (from layer registry).
void attachToLayer();



private:

QgsLayerTreeLayer( const QgsLayerTreeLayer &other );
Expand Down
13 changes: 11 additions & 2 deletions src/core/layertree/qgslayertreelayer.cpp
Expand Up @@ -76,12 +76,12 @@ void QgsLayerTreeLayer::attachToLayer()

QString QgsLayerTreeLayer::name() const
{
return mRef ? mRef->name() : mLayerName;
return ( mRef && mUseLayerName ) ? mRef->name() : mLayerName;
}

void QgsLayerTreeLayer::setName( const QString &n )
{
if ( mRef )
if ( mRef && mUseLayerName )
{
if ( mRef->name() == n )
return;
Expand Down Expand Up @@ -173,6 +173,15 @@ void QgsLayerTreeLayer::layerWillBeDeleted()

}

void QgsLayerTreeLayer::setUseLayerName( const bool use )
{
mUseLayerName = use;
}

bool QgsLayerTreeLayer::useLayerName() const
{
return mUseLayerName;
}

void QgsLayerTreeLayer::layerNameChanged()
{
Expand Down
18 changes: 17 additions & 1 deletion src/core/layertree/qgslayertreelayer.h
Expand Up @@ -90,6 +90,19 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode
*/
void setName( const QString &n ) override;

/**
* Uses the layer's name if \a use is true, or the name manually set if
* false.
* \since QGIS 3.8
*/
void setUseLayerName( bool use = true );

/**
* Returns whether the layer's name is used, or the name manually set.
* \since QGIS 3.8
*/
bool useLayerName() const;

/**
* Read layer node from XML. Returns new instance.
* Does not resolve textual references to layers. Call resolveReferences() afterwards to do it.
Expand Down Expand Up @@ -133,9 +146,12 @@ class CORE_EXPORT QgsLayerTreeLayer : public QgsLayerTreeNode

//! Weak reference to the layer (or just it's ID if the reference is not resolved yet)
QgsMapLayerRef mRef;
//! Layer name - only used if layer does not exist
//! Layer name - only used if layer does not exist or if mUseLayerName is false
QString mLayerName;

//!
bool mUseLayerName = true;

private slots:

/**
Expand Down
193 changes: 192 additions & 1 deletion src/server/services/wms/qgswmsgetlegendgraphics.cpp
Expand Up @@ -18,6 +18,13 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgslayertree.h"
#include "qgslegendrenderer.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerfeaturecounter.h"
#include "qgssymbollayerutils.h"
#include "qgsmaplayerlegend.h"

#include "qgswmsutils.h"
#include "qgswmsserviceexception.h"
#include "qgswmsgetlegendgraphics.h"
Expand All @@ -34,6 +41,9 @@ namespace QgsWms
// get parameters from query
QgsWmsParameters parameters( QUrlQuery( request.url() ) );

// check parameters validity
checkParameters( parameters );

// init render context
QgsWmsRenderContext context( project, serverIface );
context.setFlag( QgsWmsRenderContext::UseScaleDenominator );
Expand Down Expand Up @@ -81,7 +91,23 @@ namespace QgsWms
#endif
QgsRenderer renderer( context );

std::unique_ptr<QImage> result( renderer.getLegendGraphics() );
// retrieve legend settings and model
std::unique_ptr<QgsLayerTree> tree( layerTree( context ) );
std::unique_ptr<QgsLayerTreeModel> model( legendModel( context, *tree.get() ) );

// rendering
std::unique_ptr<QImage> result;
if ( !parameters.rule().isEmpty() )
{
QgsLayerTreeModelLegendNode *node = legendNode( parameters.rule(), *model.get() );
result.reset( renderer.getLegendGraphics( *node ) );
}
else
{
result.reset( renderer.getLegendGraphics( *model.get() ) );
}

tree->clear();

if ( result )
{
Expand All @@ -100,5 +126,170 @@ namespace QgsWms
throw QgsException( QStringLiteral( "Failed to compute GetLegendGraphics image" ) );
}
}

void checkParameters( const QgsWmsParameters &parameters )
{
if ( parameters.allLayersNickname().isEmpty() )
{
throw QgsBadRequestException( QgsServiceException::QGIS_MISSING_PARAMETER_VALUE,
parameters[QgsWmsParameter::LAYERS] );
}

if ( parameters.format() == QgsWmsParameters::Format::NONE )
{
throw QgsBadRequestException( QgsServiceException::QGIS_MISSING_PARAMETER_VALUE,
parameters[QgsWmsParameter::FORMAT] );
}

if ( ! parameters.bbox().isEmpty() && !parameters.rule().isEmpty() )
{
throw QgsBadRequestException( QgsServiceException::QGIS_INVALID_PARAMETER_VALUE,
QStringLiteral( "BBOX parameter cannot be combined with RULE." ) );
}

if ( ! parameters.bbox().isEmpty() && parameters.bboxAsRectangle().isEmpty() )
{
throw QgsBadRequestException( QgsServiceException::QGIS_INVALID_PARAMETER_VALUE,
parameters[QgsWmsParameter::BBOX] );
}
}

QgsLayerTreeModel *legendModel( const QgsWmsRenderContext &context, QgsLayerTree &tree )
{
const QgsWmsParameters parameters = context.parameters();
std::unique_ptr<QgsLayerTreeModel> model( new QgsLayerTreeModel( &tree ) );

if ( context.scaleDenominator() > 0 )
{
model->setLegendFilterByScale( context.scaleDenominator() );
}

// content based legend
if ( ! parameters.bbox().isEmpty() )
{
QgsRenderer renderer( context );
const QgsRenderer::HitTest symbols = renderer.symbols();

for ( QgsLayerTreeNode *node : tree.children() )
{
QgsLayerTreeLayer *layer = QgsLayerTree::toLayer( node );

QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( layer->layer() );
if ( !vl || !vl->renderer() )
continue;

QList<int> order;
int i = 0;

for ( const QgsLegendSymbolItem &item : vl->renderer()->legendSymbolItems() )
{
const QString prop = QgsSymbolLayerUtils::symbolProperties( item.legacyRuleKey() );
if ( symbols[vl].contains( prop ) )
{
order.append( i );
}
++i;
}

// either remove the whole layer or just filter out some items
if ( order.isEmpty() )
{
tree.removeChildNode( layer );
}
else
{
QgsMapLayerLegendUtils::setLegendNodeOrder( layer, order );
model->refreshLayerLegend( layer );
}
}
}

// if legend is not based on rendering rules
if ( parameters.rule().isEmpty() )
{
QList<QgsLayerTreeNode *> children = tree.children();
for ( QgsLayerTreeNode *node : children )
{
if ( ! QgsLayerTree::isLayer( node ) )
continue;

QgsLayerTreeLayer *nodeLayer = QgsLayerTree::toLayer( node );

// layer titles - hidden or not
QgsLegendRenderer::setNodeLegendStyle( nodeLayer, parameters.layerTitleAsBool() ? QgsLegendStyle::Subgroup : QgsLegendStyle::Hidden );

// rule item titles
if ( !parameters.ruleLabelAsBool() )
{
for ( QgsLayerTreeModelLegendNode *legendNode : model->layerLegendNodes( nodeLayer ) )
{
// empty string = no override, so let's use one space
legendNode->setUserLabel( QStringLiteral( " " ) );
}
}
else if ( !parameters.layerTitleAsBool() )
{
for ( QgsLayerTreeModelLegendNode *legendNode : model->layerLegendNodes( nodeLayer ) )
{
if ( legendNode->isEmbeddedInParent() )
legendNode->setEmbeddedInParent( false );
}
}
}
}

return model.release();
}

QgsLayerTree *layerTree( const QgsWmsRenderContext &context )
{
std::unique_ptr<QgsLayerTree> tree( new QgsLayerTree() );

QList<QgsVectorLayerFeatureCounter *> counters;
for ( QgsMapLayer *ml : context.layersToRender() )
{
QgsLayerTreeLayer *lt = tree->addLayer( ml );
lt->setUseLayerName( false ); // do not modify underlying layer

// name
if ( !ml->title().isEmpty() )
lt->setName( ml->title() );

// show feature count
const bool showFeatureCount = context.parameters().showFeatureCountAsBool();
const QString property = QStringLiteral( "showFeatureCount" );
lt->setCustomProperty( property, showFeatureCount );

if ( ml->type() != QgsMapLayerType::VectorLayer || !showFeatureCount )
continue;

QgsVectorLayer *vl = qobject_cast<QgsVectorLayer *>( ml );
QgsVectorLayerFeatureCounter *counter = vl->countSymbolFeatures();
if ( !counter )
continue;

counters.append( counter );
}

for ( QgsVectorLayerFeatureCounter *counter : counters )
{
counter->waitForFinished();
}

return tree.release();
}

QgsLayerTreeModelLegendNode *legendNode( const QString &rule, QgsLayerTreeModel &model )
{
for ( QgsLayerTreeLayer *layer : model.rootGroup()->findLayers() )
{
for ( QgsLayerTreeModelLegendNode *node : model.layerLegendNodes( layer ) )
{
if ( node->data( Qt::DisplayRole ).toString().compare( rule ) == 0 )
return node;
}
}
return nullptr;
}
} // namespace QgsWms

10 changes: 8 additions & 2 deletions src/server/services/wms/qgswmsgetlegendgraphics.h
Expand Up @@ -18,6 +18,9 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgslayertreemodel.h"

#include "qgswmsrendercontext.h"

namespace QgsWms
{
Expand All @@ -29,8 +32,11 @@ namespace QgsWms
const QString &version, const QgsServerRequest &request,
QgsServerResponse &response );

} // namespace QgsWms

void checkParameters( const QgsWmsParameters &parameters );

QgsLayerTreeModel *legendModel( const QgsWmsRenderContext &context, QgsLayerTree &tree );

QgsLayerTree *layerTree( const QgsWmsRenderContext &context );

QgsLayerTreeModelLegendNode *legendNode( const QString &rule, QgsLayerTreeModel &model );
} // namespace QgsWms

0 comments on commit c2840a2

Please sign in to comment.