Skip to content

Commit

Permalink
Fix legend symbol size when using map units
Browse files Browse the repository at this point in the history
fix #13078
The computation of icon sizes for legend symbols has been moved to
QgsLayerTreeModel::legendInvalidateMapBasedData() susch that icon size
is recomputed when zooming.
  • Loading branch information
vmora committed Aug 12, 2015
1 parent 45d4dbe commit 8776449
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 32 deletions.
35 changes: 35 additions & 0 deletions src/core/layertree/qgslayertreemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,10 @@ void QgsLayerTreeModel::addLegendToLayer( QgsLayerTreeLayer* nodeL )

if ( hasStyleOverride )
ml->styleManager()->restoreOverrideStyle();

// invalidate map based data even if the data is not map-based to make sure
// the symbol sizes are computed at least once
legendInvalidateMapBasedData();
}


Expand Down Expand Up @@ -1299,10 +1303,41 @@ QList<QgsLayerTreeModelLegendNode*> QgsLayerTreeModel::layerLegendNodes( QgsLaye

void QgsLayerTreeModel::legendInvalidateMapBasedData()
{
// we have varying icon sizes, and we want icon to be centered and
// text to be left aligned, so we have to compute the max width of icons
//
// we do that for nodes who share a common parent
//
// we do that here because for symbols with size defined in map units
// the symbol sizes changes depends on the zoom level

QList<QgsSymbolV2LegendNode*> symbolNodes;
QMap<QString, int> widthMax;
foreach ( const LayerLegendData& data, mLegend )
{
foreach ( QgsLayerTreeModelLegendNode* legendNode, data.originalNodes )
{
legendNode->invalidateMapBasedData();
QgsSymbolV2LegendNode* n = dynamic_cast<QgsSymbolV2LegendNode*>( legendNode );
if ( n )
{
n->setParent( this ); // map scale are in the model, so the parent needs to be set
const QSize sz( n->minimumIconSize() );
const QString parentKey( n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString() );
widthMax[parentKey] = qMax( sz.width(), widthMax.contains( parentKey ) ? widthMax[parentKey] : 0 );
n->setIconSize( sz );
symbolNodes.append( n );
}
}
}

foreach ( QgsSymbolV2LegendNode* n, symbolNodes )
{
const QString parentKey( n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString() );
Q_ASSERT( widthMax[parentKey] > 0 );
const int twiceMarginWidth = 2; // a one pixel margin avoids hugly rendering of icon
n->setIconSize( QSize( widthMax[parentKey] + twiceMarginWidth, n->iconSize().rheight() + twiceMarginWidth ) );
n->invalidateMapBasedData();
}
}

Expand Down
15 changes: 6 additions & 9 deletions src/core/layertree/qgslayertreemodellegendnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,13 +159,14 @@ Qt::ItemFlags QgsSymbolV2LegendNode::flags() const

QSize QgsSymbolV2LegendNode::minimumIconSize() const
{
QSize minSz;
QSize minSz( 16, 16 );
if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbolV2::Marker )
{
QScopedPointer<QgsRenderContext> context( createTemporaryRenderContext() );
minSz = QgsImageOperation::nonTransparentImageRect(
QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), QSize( 512, 512 ), context.data() ).toImage(),
mIconSize,
QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), QSize( 512, 512 ),
context.data() ).toImage(),
minSz,
true ).size();
}
else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbolV2::Line )
Expand All @@ -174,16 +175,12 @@ QSize QgsSymbolV2LegendNode::minimumIconSize() const
minSz = QgsImageOperation::nonTransparentImageRect(
QgsSymbolLayerV2Utils::symbolPreviewPixmap( mItem.symbol(), QSize( mIconSize.width(), 512 ),
context.data() ).toImage(),
mIconSize,
minSz,
true ).size();
}
else
{
minSz = mIconSize;
}

if ( mItem.level() != 0 && !( model() && model()->testFlag( QgsLayerTreeModel::ShowLegendAsTree ) ) )
minSz.setWidth( indentSize + minSz.width() );
minSz.setWidth( mItem.level() * indentSize + minSz.width() );

return minSz;
}
Expand Down
23 changes: 0 additions & 23 deletions src/core/qgsmaplayerlegend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,33 +199,10 @@ QList<QgsLayerTreeModelLegendNode*> QgsDefaultVectorLayerLegend::createLayerTree
nodes.append( new QgsSimpleLegendNode( nodeLayer, r->legendClassificationAttribute() ) );
}

// we have varying icon sizes, and we want icon to be centered and
// text to be left aligned, so we have to compute the max width of icons
//
// we do that for nodes who share a common parent

QList<QgsSymbolV2LegendNode*> symbolNodes;
QMap<QString, int> widthMax;
foreach ( const QgsLegendSymbolItemV2& i, r->legendSymbolItemsV2() )
{
QgsSymbolV2LegendNode * n = new QgsSymbolV2LegendNode( nodeLayer, i );
nodes.append( n );
if ( i.symbol() )
{
const QSize sz( n->minimumIconSize() );
const QString parentKey( n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString() );
widthMax[parentKey] = qMax( sz.width(), widthMax.contains( parentKey ) ? widthMax[parentKey] : 0 );
n->setIconSize( sz );
symbolNodes.append( n );
}
}

foreach ( QgsSymbolV2LegendNode* n, symbolNodes )
{
const QString parentKey( n->data( QgsLayerTreeModelLegendNode::ParentRuleKeyRole ).toString() );
Q_ASSERT( widthMax[parentKey] > 0 );
const int twiceMarginWidth = 2; // a one pixel margin avoids hugly rendering of icon
n->setIconSize( QSize( widthMax[parentKey] + twiceMarginWidth, n->iconSize().rheight() + twiceMarginWidth ) );
}

if ( nodes.count() == 1 && nodes[0]->data( Qt::EditRole ).toString().isEmpty() )
Expand Down

0 comments on commit 8776449

Please sign in to comment.