Skip to content

Commit

Permalink
Merge pull request #36370 from pblottiere/legend_json
Browse files Browse the repository at this point in the history
Update the API to export a legend in JSON
  • Loading branch information
pblottiere committed May 13, 2020
2 parents 55efa3c + 3cfe500 commit dee5882
Show file tree
Hide file tree
Showing 10 changed files with 118 additions and 78 deletions.
Expand Up @@ -160,14 +160,13 @@ Default implementation calls drawSymbol() and drawSymbolText() methods.
If ctx is ``None``, this is just first stage when preparing layout - without actual rendering.
%End

void exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json );
QJsonObject exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context );
%Docstring
Entry point called from QgsLegendRenderer to do the rendering in a
JSON object.

:param settings: Legend layout configuration
:param context: Rendering context
:param json: The json object to update

.. versionadded:: 3.8
%End
Expand All @@ -183,13 +182,12 @@ Draws symbol on the left side of the item
:return: Real size of the symbol (may be bigger than "normal" symbol size from settings)
%End

virtual void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const;
virtual QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const;
%Docstring
Adds a symbol in base64 string within a JSON object with the key "icon".

:param settings: Legend layout configuration
:param context: Rendering context
:param json: The json object to update

.. versionadded:: 3.8
%End
Expand All @@ -203,16 +201,6 @@ Draws label on the right side of the item
:param symbolSize: Real size of the associated symbol - used for correct positioning when rendering

:return: Size of the label (may span multiple lines)
%End

void exportSymbolTextToJson( const QgsLegendSettings &settings, QJsonObject &json ) const;
%Docstring
Adds a label in a JSON object with the key "title".

:param settings: Legend layout configuration
:param json: The json object to update

.. versionadded:: 3.8
%End

signals:
Expand Down Expand Up @@ -269,7 +257,7 @@ Constructor for QgsSymbolLegendNode.
virtual QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const;


virtual void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const;
virtual QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const;


virtual void setEmbeddedInParent( bool embedded );
Expand Down Expand Up @@ -519,7 +507,7 @@ Constructor for QgsImageLegendNode.
virtual QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const;


virtual void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const;
virtual QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const;


};
Expand Down Expand Up @@ -553,7 +541,7 @@ Constructor for QgsRasterSymbolLegendNode.
virtual QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const;


virtual void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const;
virtual QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const;


};
Expand Down Expand Up @@ -586,7 +574,7 @@ Constructor for QgsWmsLegendNode.
virtual QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const;


virtual void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const;
virtual QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const;


virtual void invalidateMapBasedData();
Expand Down
2 changes: 1 addition & 1 deletion python/core/auto_generated/qgslegendrenderer.sip.in
Expand Up @@ -81,7 +81,7 @@ Draws the legend using a given render ``context``. The legend will occupy the ar
.. versionadded:: 3.6
%End

void exportLegendToJson( const QgsRenderContext &context, QJsonObject &json );
QJsonObject exportLegendToJson( const QgsRenderContext &context );
%Docstring
Renders the legend in a ``json`` object.

Expand Down
53 changes: 32 additions & 21 deletions src/core/layertree/qgslayertreemodellegendnode.cpp
Expand Up @@ -84,10 +84,12 @@ QgsLayerTreeModelLegendNode::ItemMetrics QgsLayerTreeModelLegendNode::draw( cons
return im;
}

void QgsLayerTreeModelLegendNode::exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json )
QJsonObject QgsLayerTreeModelLegendNode::exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context )
{
exportSymbolToJson( settings, context, json );
exportSymbolTextToJson( settings, json );
QJsonObject json = exportSymbolToJson( settings, context );
const QString text = data( Qt::DisplayRole ).toString();
json[ QStringLiteral( "title" ) ] = text;
return json;
}

QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const
Expand Down Expand Up @@ -130,18 +132,21 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbol( const QgsLegendSettings &setting
return size;
}

void QgsLayerTreeModelLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const
QJsonObject QgsLayerTreeModelLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext & ) const
{
const QIcon icon = data( Qt::DecorationRole ).value<QIcon>();
if ( icon.isNull() )
return;
return QJsonObject();

const QImage image( icon.pixmap( settings.symbolSize().width(), settings.symbolSize().height() ).toImage() );
QByteArray byteArray;
QBuffer buffer( &byteArray );
image.save( &buffer, "PNG" );
const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
json[ "icon" ] = base64;

QJsonObject json;
json[ QStringLiteral( "icon" ) ] = base64;
return json;
}

QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &settings, ItemContext *ctx, QSizeF symbolSize ) const
Expand Down Expand Up @@ -225,12 +230,6 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
return labelSize;
}

void QgsLayerTreeModelLegendNode::exportSymbolTextToJson( const QgsLegendSettings &, QJsonObject &json ) const
{
const QString text = data( Qt::DisplayRole ).toString();
json[ "title" ] = text;
}

// -------------------------------------------------------------------------

QgsSymbolLegendNode::QgsSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QgsLegendSymbolItem &item, QObject *parent )
Expand Down Expand Up @@ -661,12 +660,12 @@ QSizeF QgsSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemC
std::max( height + 2 * heightOffset, static_cast< double >( desiredHeight ) ) );
}

void QgsSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const
QJsonObject QgsSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const
{
const QgsSymbol *s = mCustomSymbol ? mCustomSymbol.get() : mItem.symbol();
if ( !s )
{
return;
return QJsonObject();
}


Expand Down Expand Up @@ -704,7 +703,10 @@ void QgsSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings,
QBuffer buffer( &byteArray );
img.save( &buffer, "PNG" );
const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
json[ "icon" ] = base64;

QJsonObject json;
json[ QStringLiteral( "icon" ) ] = base64;
return json;
}

void QgsSymbolLegendNode::setEmbeddedInParent( bool embedded )
Expand Down Expand Up @@ -862,13 +864,16 @@ QSizeF QgsImageLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemCo
return settings.wmsLegendSize();
}

void QgsImageLegendNode::exportSymbolToJson( const QgsLegendSettings &, const QgsRenderContext &, QJsonObject &json ) const
QJsonObject QgsImageLegendNode::exportSymbolToJson( const QgsLegendSettings &, const QgsRenderContext & ) const
{
QByteArray byteArray;
QBuffer buffer( &byteArray );
mImage.save( &buffer, "PNG" );
const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
json[ "icon" ] = base64;

QJsonObject json;
json[ QStringLiteral( "icon" ) ] = base64;
return json;
}

// -------------------------------------------------------------------------
Expand Down Expand Up @@ -954,7 +959,7 @@ QSizeF QgsRasterSymbolLegendNode::drawSymbol( const QgsLegendSettings &settings,
return size;
}

void QgsRasterSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &, QJsonObject &json ) const
QJsonObject QgsRasterSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext & ) const
{
QImage img = QImage( settings.symbolSize().toSize(), QImage::Format_ARGB32 );
img.fill( Qt::transparent );
Expand Down Expand Up @@ -989,7 +994,10 @@ void QgsRasterSymbolLegendNode::exportSymbolToJson( const QgsLegendSettings &set
QBuffer buffer( &byteArray );
img.save( &buffer, "PNG" );
const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
json[ "icon" ] = base64;

QJsonObject json;
json[ QStringLiteral( "icon" ) ] = base64;
return json;
}

// -------------------------------------------------------------------------
Expand Down Expand Up @@ -1078,13 +1086,16 @@ QSizeF QgsWmsLegendNode::drawSymbol( const QgsLegendSettings &settings, ItemCont
return settings.wmsLegendSize();
}

void QgsWmsLegendNode::exportSymbolToJson( const QgsLegendSettings &, const QgsRenderContext &, QJsonObject &json ) const
QJsonObject QgsWmsLegendNode::exportSymbolToJson( const QgsLegendSettings &, const QgsRenderContext & ) const
{
QByteArray byteArray;
QBuffer buffer( &byteArray );
mImage.save( &buffer, "PNG" );
const QString base64 = QString::fromLatin1( byteArray.toBase64().data() );
json[ "icon" ] = base64;

QJsonObject json;
json[ QStringLiteral( "icon" ) ] = base64;
return json;
}

/* private */
Expand Down
22 changes: 6 additions & 16 deletions src/core/layertree/qgslayertreemodellegendnode.h
Expand Up @@ -220,10 +220,9 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
* JSON object.
* \param settings Legend layout configuration
* \param context Rendering context
* \param json The json object to update
* \since QGIS 3.8
*/
void exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json );
QJsonObject exportToJson( const QgsLegendSettings &settings, const QgsRenderContext &context );

/**
* Draws symbol on the left side of the item
Expand All @@ -238,10 +237,9 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
* Adds a symbol in base64 string within a JSON object with the key "icon".
* \param settings Legend layout configuration
* \param context Rendering context
* \param json The json object to update
* \since QGIS 3.8
*/
virtual void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const;
virtual QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const;

/**
* Draws label on the right side of the item
Expand All @@ -252,14 +250,6 @@ class CORE_EXPORT QgsLayerTreeModelLegendNode : public QObject
*/
virtual QSizeF drawSymbolText( const QgsLegendSettings &settings, ItemContext *ctx, QSizeF symbolSize ) const;

/**
* Adds a label in a JSON object with the key "title".
* \param settings Legend layout configuration
* \param json The json object to update
* \since QGIS 3.8
*/
void exportSymbolTextToJson( const QgsLegendSettings &settings, QJsonObject &json ) const;

signals:
//! Emitted on internal data change so the layer tree model can forward the signal to views
void dataChanged();
Expand Down Expand Up @@ -311,7 +301,7 @@ class CORE_EXPORT QgsSymbolLegendNode : public QgsLayerTreeModelLegendNode

QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const override;

void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const override;
QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const override;

void setEmbeddedInParent( bool embedded ) override;

Expand Down Expand Up @@ -554,7 +544,7 @@ class CORE_EXPORT QgsImageLegendNode : public QgsLayerTreeModelLegendNode

QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const override;

void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const override;
QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const override;

private:
QImage mImage;
Expand Down Expand Up @@ -585,7 +575,7 @@ class CORE_EXPORT QgsRasterSymbolLegendNode : public QgsLayerTreeModelLegendNode

QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const override;

void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const override;
QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const override;

private:
QColor mColor;
Expand Down Expand Up @@ -617,7 +607,7 @@ class CORE_EXPORT QgsWmsLegendNode : public QgsLayerTreeModelLegendNode

QSizeF drawSymbol( const QgsLegendSettings &settings, ItemContext *ctx, double itemHeight ) const override;

void exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context, QJsonObject &json ) const override;
QJsonObject exportSymbolToJson( const QgsLegendSettings &settings, const QgsRenderContext &context ) const override;

void invalidateMapBasedData() override;

Expand Down
31 changes: 18 additions & 13 deletions src/core/qgslegendrenderer.cpp
Expand Up @@ -68,18 +68,22 @@ void QgsLegendRenderer::drawLegend( QPainter *painter )
paintAndDetermineSize( context );
}

void QgsLegendRenderer::exportLegendToJson( const QgsRenderContext &context, QJsonObject &json )
QJsonObject QgsLegendRenderer::exportLegendToJson( const QgsRenderContext &context )
{
QJsonObject json;

QgsLayerTreeGroup *rootGroup = mLegendModel->rootGroup();
if ( !rootGroup )
return;
return json;

json = exportLegendToJson( context, rootGroup );
json[QStringLiteral( "title" )] = mSettings.title();
exportLegendToJson( context, rootGroup, json );
return json;
}

void QgsLegendRenderer::exportLegendToJson( const QgsRenderContext &context, QgsLayerTreeGroup *nodeGroup, QJsonObject &json )
QJsonObject QgsLegendRenderer::exportLegendToJson( const QgsRenderContext &context, QgsLayerTreeGroup *nodeGroup )
{
QJsonObject json;
QJsonArray nodes;
const QList<QgsLayerTreeNode *> childNodes = nodeGroup->children();
for ( QgsLayerTreeNode *node : childNodes )
Expand All @@ -90,17 +94,13 @@ void QgsLegendRenderer::exportLegendToJson( const QgsRenderContext &context, Qgs
const QModelIndex idx = mLegendModel->node2index( nodeGroup );
const QString text = mLegendModel->data( idx, Qt::DisplayRole ).toString();

QJsonObject group;
QJsonObject group = exportLegendToJson( context, nodeGroup );
group[ QStringLiteral( "type" ) ] = QStringLiteral( "group" );
group[ QStringLiteral( "title" ) ] = text;
exportLegendToJson( context, nodeGroup, group );
nodes.append( group );
}
else if ( QgsLayerTree::isLayer( node ) )
{
QJsonObject group;
group[ QStringLiteral( "type" ) ] = QStringLiteral( "layer" );

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

QString text;
Expand All @@ -117,27 +117,32 @@ void QgsLegendRenderer::exportLegendToJson( const QgsRenderContext &context, Qgs

if ( legendNodes.count() == 1 )
{
legendNodes.at( 0 )->exportToJson( mSettings, context, group );
QJsonObject group = legendNodes.at( 0 )->exportToJson( mSettings, context );
group[ QStringLiteral( "type" ) ] = QStringLiteral( "layer" );
nodes.append( group );
}
else if ( legendNodes.count() > 1 )
{
QJsonObject group;
group[ QStringLiteral( "type" ) ] = QStringLiteral( "layer" );
group[ QStringLiteral( "title" ) ] = text;

QJsonArray symbols;
for ( int j = 0; j < legendNodes.count(); j++ )
{
QgsLayerTreeModelLegendNode *legendNode = legendNodes.at( j );
QJsonObject symbol;
legendNode->exportToJson( mSettings, context, symbol );
QJsonObject symbol = legendNode->exportToJson( mSettings, context );
symbols.append( symbol );
}
group[ QStringLiteral( "title" ) ] = text;
group[ QStringLiteral( "symbols" ) ] = symbols;

nodes.append( group );
}
}
}

json[QStringLiteral( "nodes" )] = nodes;
return json;
}

QSizeF QgsLegendRenderer::paintAndDetermineSize( QgsRenderContext &context )
Expand Down

0 comments on commit dee5882

Please sign in to comment.