Skip to content

Commit 0ee1097

Browse files
committed
Fix undersized layertree icons on hidpi displays
(cherry picked from commit 27bb2c1)
1 parent 149d68d commit 0ee1097

File tree

4 files changed

+42
-9
lines changed

4 files changed

+42
-9
lines changed

python/core/auto_generated/layertree/qgslayertreemodel.sip.in

+11
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,17 @@ Gets map of map layer style overrides (key: layer ID, value: style name) where a
307307
Set map of map layer style overrides (key: layer ID, value: style name) where a different style should be used instead of the current one
308308

309309
.. versionadded:: 2.10
310+
%End
311+
312+
static int scaleIconSize( int standardSize );
313+
%Docstring
314+
Scales an layer tree model icon size to compensate for display pixel density, making the icon
315+
size hi-dpi friendly, whilst still resulting in pixel-perfect sizes for low-dpi
316+
displays.
317+
318+
``standardSize`` should be set to a standard icon size, e.g. 16, 24, 48, etc.
319+
320+
.. versionadded:: 3.6
310321
%End
311322

312323
protected slots:

src/core/layertree/qgslayertreemodel.cpp

+10-2
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,11 @@ QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
227227

228228
if ( vlayer && vlayer->isEditable() )
229229
{
230-
QPixmap pixmap( icon.pixmap( 16, 16 ) );
230+
const int iconSize = scaleIconSize( 16 );
231+
QPixmap pixmap( icon.pixmap( iconSize, iconSize ) );
231232

232233
QPainter painter( &pixmap );
233-
painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.svg" : "/mActionToggleEditing.svg" ) );
234+
painter.drawPixmap( 0, 0, iconSize, iconSize, QgsApplication::getThemePixmap( vlayer->isModified() ? QStringLiteral( "/mIconEditableEdits.svg" ) : QStringLiteral( "/mActionToggleEditing.svg" ) ) );
234235
painter.end();
235236

236237
icon = QIcon( pixmap );
@@ -691,6 +692,13 @@ void QgsLayerTreeModel::setLayerStyleOverrides( const QMap<QString, QString> &ov
691692
mLayerStyleOverrides = overrides;
692693
}
693694

695+
int QgsLayerTreeModel::scaleIconSize( int standardSize )
696+
{
697+
QFontMetrics fm( ( QFont() ) );
698+
const double scale = 1.1 * standardSize / 24;
699+
return static_cast< int >( std::floor( std::max( Qgis::UI_SCALE_FACTOR * fm.height() * scale, static_cast< double >( standardSize ) ) ) );
700+
}
701+
694702
void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
695703
{
696704
Q_ASSERT( node );

src/core/layertree/qgslayertreemodel.h

+11
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,17 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
274274
*/
275275
void setLayerStyleOverrides( const QMap<QString, QString> &overrides );
276276

277+
/**
278+
* Scales an layer tree model icon size to compensate for display pixel density, making the icon
279+
* size hi-dpi friendly, whilst still resulting in pixel-perfect sizes for low-dpi
280+
* displays.
281+
*
282+
* \a standardSize should be set to a standard icon size, e.g. 16, 24, 48, etc.
283+
*
284+
* \since QGIS 3.6
285+
*/
286+
static int scaleIconSize( int standardSize );
287+
277288
protected slots:
278289
void nodeWillAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
279290
void nodeAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );

src/core/layertree/qgslayertreemodellegendnode.cpp

+10-7
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,14 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
128128

129129
// -------------------------------------------------------------------------
130130

131-
132131
QgsSymbolLegendNode::QgsSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QgsLegendSymbolItem &item, QObject *parent )
133132
: QgsLayerTreeModelLegendNode( nodeLayer, parent )
134133
, mItem( item )
135134
, mSymbolUsesMapUnits( false )
136-
, mIconSize( 16, 16 )
137135
{
136+
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
137+
mIconSize = QSize( iconSize, iconSize );
138+
138139
updateLabel();
139140
connect( qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ), &QgsVectorLayer::symbolFeatureCountMapChanged, this, &QgsSymbolLegendNode::updateLabel );
140141
connect( nodeLayer, &QObject::destroyed, this, [ = ]() { mLayerNode = nullptr; } );
@@ -160,19 +161,21 @@ QSize QgsSymbolLegendNode::minimumIconSize() const
160161

161162
QSize QgsSymbolLegendNode::minimumIconSize( QgsRenderContext *context ) const
162163
{
163-
QSize minSz( 16, 16 );
164+
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
165+
const int largeIconSize = QgsLayerTreeModel::scaleIconSize( 512 );
166+
QSize minSz( iconSize, iconSize );
164167
if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Marker )
165168
{
166169
minSz = QgsImageOperation::nonTransparentImageRect(
167-
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( 512, 512 ), 0,
170+
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( largeIconSize, largeIconSize ), 0,
168171
context ).toImage(),
169172
minSz,
170173
true ).size();
171174
}
172175
else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Line )
173176
{
174177
minSz = QgsImageOperation::nonTransparentImageRect(
175-
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), 512 ), 0,
178+
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), largeIconSize ), 0,
176179
context ).toImage(),
177180
minSz,
178181
true ).size();
@@ -576,8 +579,8 @@ QVariant QgsRasterSymbolLegendNode::data( int role ) const
576579
{
577580
if ( role == Qt::DecorationRole )
578581
{
579-
QSize iconSize( 16, 16 ); // TODO: configurable?
580-
QPixmap pix( iconSize );
582+
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 ); // TODO: configurable?
583+
QPixmap pix( iconSize, iconSize );
581584
pix.fill( mColor );
582585
return QIcon( pix );
583586
}

0 commit comments

Comments
 (0)