Don't show private layers in print layout legends by default

When a print layout legend is in auto mode, private layers should
not be included

Fixes #51427
This commit is contained in:
Nyall Dawson 2024-08-19 10:40:11 +10:00
parent 71c7b63cf6
commit 452d597cbc
6 changed files with 72 additions and 4 deletions

View File

@ -22,6 +22,7 @@
#include "qgslayoutmodel.h"
#include "qgslayertree.h"
#include "qgslayertreemodel.h"
#include "qgslayertreefilterproxymodel.h"
#include "qgslegendrenderer.h"
#include "qgslegendstyle.h"
#include "qgslogger.h"
@ -153,7 +154,7 @@ void QgsLayoutItemLegend::paint( QPainter *painter, const QStyleOptionGraphicsIt
}
mInitialMapScaleCalculated = true;
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
QgsLegendRenderer legendRenderer = createRenderer();
legendRenderer.setLegendSize( mForceResize && mSizeToContents ? QSize() : rect().size() );
const QPointF oldPos = pos();
@ -265,7 +266,7 @@ void QgsLayoutItemLegend::draw( QgsLayoutItemRenderContext &context )
Q_NOWARN_DEPRECATED_POP
}
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
QgsLegendRenderer legendRenderer = createRenderer();
legendRenderer.setLegendSize( rect().size() );
legendRenderer.drawLegend( rc );
@ -288,7 +289,7 @@ void QgsLayoutItemLegend::adjustBoxSize()
QgsRenderContext context = mMap ? QgsLayoutUtils::createRenderContextForMap( mMap, nullptr ) :
QgsLayoutUtils::createRenderContextForLayout( mLayout, nullptr );
QgsLegendRenderer legendRenderer( mLegendModel.get(), mSettings );
QgsLegendRenderer legendRenderer = createRenderer();
const QSizeF size = legendRenderer.minimumSize( &context );
QgsDebugMsgLevel( QStringLiteral( "width = %1 height = %2" ).arg( size.width() ).arg( size.height() ), 2 );
if ( size.isValid() )
@ -329,6 +330,16 @@ void QgsLayoutItemLegend::ensureModelIsInitialized() const
}
}
QgsLegendRenderer QgsLayoutItemLegend::createRenderer() const
{
QgsLegendRenderer res( mLegendModel.get(), mSettings );
// only show private layers when not in auto update mode
res.proxyModel()->setShowPrivateLayers( static_cast< bool >( mCustomLayerTree ) );
return res;
}
QgsLegendModel *QgsLayoutItemLegend::model()
{
ensureModelIsInitialized();

View File

@ -351,7 +351,7 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
* A symbol size of 0.0 indicates no maximum is set.
*
* \see maximumSymbolSize()
* \since QGIS 3.16
* \since QGIS 3.16:
*/
void setMaximumSymbolSize( double size );
@ -642,6 +642,9 @@ class CORE_EXPORT QgsLayoutItemLegend : public QgsLayoutItem
void setModelStyleOverrides( const QMap<QString, QString> &overrides );
void ensureModelIsInitialized() const;
QgsLegendRenderer createRenderer() const;
std::unique_ptr< QgsLegendModel > mLegendModel;
std::unique_ptr< QgsLayerTree > mCustomLayerTree;
bool mDeferLegendModelInitialization = true;

View File

@ -37,6 +37,15 @@ QgsLegendRenderer::QgsLegendRenderer( QgsLayerTreeModel *legendModel, const QgsL
mProxyModel->setLayerTreeModel( mLegendModel );
}
QgsLegendRenderer::QgsLegendRenderer( QgsLegendRenderer &&other )
: mLegendModel( other.mLegendModel )
, mProxyModel( std::move( other.mProxyModel ) )
, mSettings( std::move( other.mSettings ) )
, mLegendSize( other.mLegendSize )
{
mProxyModel->setLayerTreeModel( mLegendModel );
}
QgsLegendRenderer::~QgsLegendRenderer() = default;
QSizeF QgsLegendRenderer::minimumSize( QgsRenderContext *renderContext )

View File

@ -58,6 +58,7 @@ class CORE_EXPORT QgsLegendRenderer
#ifndef SIP_RUN
QgsLegendRenderer( const QgsLegendRenderer &other ) = delete;
QgsLegendRenderer &operator=( const QgsLegendRenderer &other ) = delete;
QgsLegendRenderer( QgsLegendRenderer &&other );
#endif
/**

View File

@ -24,6 +24,7 @@ from qgis.PyQt.QtGui import (
from qgis.PyQt.QtXml import QDomDocument
from qgis.core import (
QgsMapLayer,
QgsCategorizedSymbolRenderer,
QgsCoordinateReferenceSystem,
QgsExpression,
@ -441,6 +442,49 @@ class TestQgsLayoutItemLegend(QgisTestCase, LayoutItemTestCase):
)
)
def test_private_layers(self):
"""
Test legend does not contain private layers by default
"""
point_path = os.path.join(TEST_DATA_DIR, 'points.shp')
point_layer1 = QgsVectorLayer(point_path, 'points 1', 'ogr')
point_layer2 = QgsVectorLayer(point_path, 'points 2', 'ogr')
point_layer2.setFlags(QgsMapLayer.LayerFlag.Private)
p = QgsProject()
p.addMapLayers([point_layer1, point_layer2])
marker_symbol = QgsMarkerSymbol.createSimple(
{'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'})
point_layer1.setRenderer(
QgsSingleSymbolRenderer(marker_symbol.clone()))
point_layer2.setRenderer(
QgsSingleSymbolRenderer(marker_symbol.clone()))
layout = QgsLayout(p)
layout.initializeDefaults()
legend = QgsLayoutItemLegend(layout)
legend.setTitle("Legend")
legend.attemptSetSceneRect(QRectF(120, 20, 80, 80))
legend.setFrameEnabled(True)
legend.setFrameStrokeWidth(QgsLayoutMeasurement(2))
legend.setBackgroundColor(QColor(200, 200, 200))
legend.setTitle('')
layout.addLayoutItem(legend)
legend.setStyleFont(QgsLegendStyle.Style.Title, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Style.Group, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Style.Subgroup, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Style.Symbol, QgsFontUtils.getStandardTestFont('Bold', 16))
legend.setStyleFont(QgsLegendStyle.Style.SymbolLabel, QgsFontUtils.getStandardTestFont('Bold', 16))
self.assertTrue(
self.render_layout_check(
'composer_legend_private_layers', layout
)
)
def testResizeDisabled(self):
"""
Test that test legend does not resize if auto size is disabled