Skip to content
Permalink
Browse files

[layer tree][ui] Allow users to set a minimum/maximum legend size

  • Loading branch information
nirvn committed Nov 6, 2020
1 parent df4d239 commit 5f161a89fdce0df81008449303ac873f0c125a48
@@ -713,6 +713,12 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti

cmbLegendDoubleClickAction->setCurrentIndex( mSettings->value( QStringLiteral( "/qgis/legendDoubleClickAction" ), 0 ).toInt() );

// Legend symbol minimum / maximum values
mLegendSymbolMinimumSizeSpinBox->setClearValue( 0.0, tr( "none" ) );
mLegendSymbolMaximumSizeSpinBox->setClearValue( 0.0, tr( "none" ) );
mLegendSymbolMinimumSizeSpinBox->setValue( mSettings->value( QStringLiteral( "/qgis/legendsymbolMinimumSize" ), 0.1 ).toDouble() );
mLegendSymbolMaximumSizeSpinBox->setValue( mSettings->value( QStringLiteral( "/qgis/legendsymbolMaximumSize" ), 20.0 ).toDouble() );

// WMS getLegendGraphic setting
mLegendGraphicResolutionSpinBox->setValue( mSettings->value( QStringLiteral( "/qgis/defaultLegendGraphicResolution" ), 0 ).toInt() );

@@ -1557,6 +1563,10 @@ void QgsOptions::saveOptions()
mSettings->setValue( QStringLiteral( "/qgis/mainSnappingWidgetMode" ), mSnappingMainDialogComboBox->currentData() );

mSettings->setValue( QStringLiteral( "/qgis/compileExpressions" ), cbxCompileExpressions->isChecked() );

mSettings->setValue( QStringLiteral( "/qgis/legendsymbolMinimumSize" ), mLegendSymbolMinimumSizeSpinBox->value() );
mSettings->setValue( QStringLiteral( "/qgis/legendsymbolMaximumSize" ), mLegendSymbolMaximumSizeSpinBox->value() );

mSettings->setValue( QStringLiteral( "/qgis/defaultLegendGraphicResolution" ), mLegendGraphicResolutionSpinBox->value() );
mSettings->setValue( QStringLiteral( "/qgis/mapTipsDelay" ), mMapTipsDelaySpinBox->value() );
mSettings->setEnumValue( QStringLiteral( "/qgis/copyFeatureFormat" ), ( QgsClipboard::CopyFormat )mComboCopyFeatureFormat->currentData().toInt() );
@@ -34,6 +34,7 @@
#include "qgsvectorlayerfeaturecounter.h"
#include "qgsexpression.h"
#include "qgstextrenderer.h"
#include "qgssettings.h"


QgsLayerTreeModelLegendNode::QgsLayerTreeModelLegendNode( QgsLayerTreeLayer *nodeL, QObject *parent )
@@ -249,6 +250,10 @@ QgsSymbolLegendNode::QgsSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const Qg
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
mIconSize = QSize( iconSize, iconSize );

QgsSettings settings;
mSymbolMinimumSize = settings.value( "/qgis/legendsymbolMinimumSize", 0.5 ).toDouble();
mSymbolMaximumSize = settings.value( "/qgis/legendsymbolMaximumSize", 20.0 ).toDouble();

updateLabel();
connect( qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ), &QgsVectorLayer::symbolFeatureCountMapChanged, this, &QgsSymbolLegendNode::updateLabel );
connect( nodeLayer, &QObject::destroyed, this, [ = ]() { mLayerNode = nullptr; } );
@@ -279,16 +284,23 @@ QSize QgsSymbolLegendNode::minimumIconSize( QgsRenderContext *context ) const
QSize minSz( iconSize, iconSize );
if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Marker )
{
// unusued width, height variables
double width = 0.0;
double height = 0.0;
std::unique_ptr<QgsSymbol> symbol( QgsSymbolLayerUtils::restrictedSizeSymbol( mItem.symbol(), mSymbolMinimumSize, mSymbolMaximumSize, context, width, height ) );
minSz = QgsImageOperation::nonTransparentImageRect(
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( largeIconSize, largeIconSize ), 0,
QgsSymbolLayerUtils::symbolPreviewPixmap( symbol ? symbol.get() : mItem.symbol(), QSize( largeIconSize, largeIconSize ), 0,
context ).toImage(),
minSz,
true ).size();
}
else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Line )
{
double width = 0.0;
double height = 0.0;
std::unique_ptr<QgsSymbol> symbol( QgsSymbolLayerUtils::restrictedSizeSymbol( mItem.symbol(), mSymbolMinimumSize, mSymbolMaximumSize, context, width, height ) );
minSz = QgsImageOperation::nonTransparentImageRect(
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), largeIconSize ), 0,
QgsSymbolLayerUtils::symbolPreviewPixmap( symbol ? symbol.get() : mItem.symbol(), QSize( minSz.width(), largeIconSize ), 0,
context ).toImage(),
minSz,
true ).size();
@@ -452,7 +464,12 @@ QVariant QgsSymbolLegendNode::data( int role ) const
if ( mItem.symbol() )
{
std::unique_ptr<QgsRenderContext> context( createTemporaryRenderContext() );
pix = QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), mIconSize, 0, context.get() );

// unusued width, height variables
double width = 0.0;
double height = 0.0;
std::unique_ptr<QgsSymbol> symbol( QgsSymbolLayerUtils::restrictedSizeSymbol( mItem.symbol(), mSymbolMinimumSize, mSymbolMaximumSize, context.get(), width, height ) );
pix = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol ? symbol.get() : mItem.symbol(), mIconSize, 0, context.get() );

if ( !mTextOnSymbolLabel.isEmpty() && context )
{
@@ -472,7 +472,10 @@ class CORE_EXPORT QgsSymbolLegendNode : public QgsLayerTreeModelLegendNode
mutable QPixmap mPixmap; // cached symbol preview
QString mLabel;
bool mSymbolUsesMapUnits;

QSize mIconSize;
double mSymbolMinimumSize = 0.5;
double mSymbolMaximumSize = 20.0;

QString mTextOnSymbolLabel;
QgsTextFormat mTextOnSymbolTextFormat;
@@ -3343,7 +3343,7 @@
<item>
<widget class="QLabel" name="label_58">
<property name="text">
<string>WMS getLegendGraphic Resolution</string>
<string>WMS getLegendGraphic resolution</string>
</property>
</widget>
</item>
@@ -3377,6 +3377,125 @@
<property name="maximum">
<number>1000000</number>
</property>
<property name="suffix">
<string> dpi</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_34">
<item>
<widget class="QLabel" name="labelLegendSymbolMinimumSize">
<property name="text">
<string>Minimum legend symbol size</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_391">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QgsDoubleSpinBox" name="mLegendSymbolMinimumSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> mm</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>999.00</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="value">
<double>0.10</double>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
<property name="toolTip">
<string extracomment="(set value to 0 to skip minimum size)"/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_34">
<item>
<widget class="QLabel" name="labelLegendSymbolMaximumSize">
<property name="text">
<string>Maximum legend symbol size</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_391">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Preferred</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>30</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QgsDoubleSpinBox" name="mLegendSymbolMaximumSizeSpinBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> mm</string>
</property>
<property name="decimals">
<number>2</number>
</property>
<property name="maximum">
<double>999.00</double>
</property>
<property name="singleStep">
<double>0.200000000000000</double>
</property>
<property name="value">
<double>20.00</double>
</property>
<property name="showClearButton" stdset="0">
<bool>true</bool>
</property>
<property name="toolTip">
<string extracomment="(set value to 0 to skip maximum size)"/>
</property>
</widget>
</item>
</layout>
@@ -3399,7 +3518,7 @@
</sizepolicy>
</property>
<property name="text">
<string>Delay (ms)</string>
<string>Delay (in milliseconds)</string>
</property>
</widget>
</item>
@@ -3421,6 +3540,9 @@
</item>
<item>
<widget class="QgsSpinBox" name="mMapTipsDelaySpinBox">
<property name="suffix">
<string> ms</string>
</property>
<property name="toolTip">
<string extracomment="MAP_RESOLUTION or DPI value overloading getMap default value (set 0 to use default)"/>
</property>
@@ -27,6 +27,7 @@
#include <qgslayertreemodel.h>
#include <qgslayertreemodellegendnode.h>
#include <qgslayertreeutils.h>
#include <qgssettings.h>
#include "qgslegendsettings.h"

class TestQgsLayerTree : public QObject
@@ -42,6 +43,7 @@ class TestQgsLayerTree : public QObject
void testCheckStateHiearchical();
void testCheckStateMutuallyExclusive();
void testCheckStateMutuallyExclusiveEdgeCases();
void testRestrictedSymbolSize();
void testShowHideAllSymbolNodes();
void testFindLegendNode();
void testLegendSymbolCategorized();
@@ -84,6 +86,10 @@ void TestQgsLayerTree::initTestCase()
QgsApplication::init();
QgsApplication::initQgis();

QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );

mRoot = new QgsLayerTreeGroup();
mRoot->addGroup( QStringLiteral( "grp1" ) );
mRoot->addGroup( QStringLiteral( "grp2" ) );
@@ -291,6 +297,46 @@ void TestQgsLayerTree::testCheckStateMutuallyExclusiveEdgeCases()
delete root3;
}

void TestQgsLayerTree::testRestrictedSymbolSize()
{
QgsSettings settings;
settings.setValue( "/qgis/legendsymbolMaximumSize", 15.0 );

//new memory layer
QgsVectorLayer *vl = new QgsVectorLayer( QStringLiteral( "Point?field=col1:integer" ), QStringLiteral( "vl" ), QStringLiteral( "memory" ) );
QVERIFY( vl->isValid() );

QgsProject project;
project.addMapLayer( vl );

QgsMarkerSymbol *symbol = static_cast< QgsMarkerSymbol * >( QgsSymbol::defaultSymbol( QgsWkbTypes::PointGeometry ) );
symbol->setSize( 500.0 );
symbol->setSizeUnit( QgsUnitTypes::RenderMapUnits );

//create a categorized renderer for layer
QgsCategorizedSymbolRenderer *renderer = new QgsCategorizedSymbolRenderer();
renderer->setClassAttribute( QStringLiteral( "col1" ) );
renderer->setSourceSymbol( symbol->clone() );
renderer->addCategory( QgsRendererCategory( "a", symbol->clone(), QStringLiteral( "a" ) ) );
renderer->addCategory( QgsRendererCategory( "b", symbol->clone(), QStringLiteral( "b" ) ) );
vl->setRenderer( renderer );

//create legend with symbology nodes for categorized renderer
QgsLayerTree *root = new QgsLayerTree();
QgsLayerTreeLayer *n = new QgsLayerTreeLayer( vl );
root->addChildNode( n );
QgsLayerTreeModel *m = new QgsLayerTreeModel( root, nullptr );
m->setLegendMapViewData( 10, 96, 10 );

QList<QgsLayerTreeModelLegendNode *> nodes = m->layerLegendNodes( n );
QSize minimumSize = static_cast< QgsSymbolLegendNode *>( nodes.at( 0 ) )->minimumIconSize();
QCOMPARE( minimumSize.width(), 52 );

//cleanup
delete m;
delete root;
}

void TestQgsLayerTree::testShowHideAllSymbolNodes()
{
//new memory layer

0 comments on commit 5f161a8

Please sign in to comment.
You can’t perform that action at this time.