Fix undersized layertree icons on hidpi displays

This commit is contained in:
Nyall Dawson 2019-01-27 09:45:19 +10:00
parent fc9796f52a
commit 27bb2c156f
4 changed files with 42 additions and 9 deletions

View File

@ -307,6 +307,17 @@ Gets map of map layer style overrides (key: layer ID, value: style name) where a
Sets map of map layer style overrides (key: layer ID, value: style name) where a different style should be used instead of the current one
.. versionadded:: 2.10
%End
static int scaleIconSize( int standardSize );
%Docstring
Scales an layer tree model icon size to compensate for display pixel density, making the icon
size hi-dpi friendly, whilst still resulting in pixel-perfect sizes for low-dpi
displays.
``standardSize`` should be set to a standard icon size, e.g. 16, 24, 48, etc.
.. versionadded:: 3.6
%End
protected slots:

View File

@ -224,10 +224,11 @@ QVariant QgsLayerTreeModel::data( const QModelIndex &index, int role ) const
if ( vlayer && vlayer->isEditable() )
{
QPixmap pixmap( icon.pixmap( 16, 16 ) );
const int iconSize = scaleIconSize( 16 );
QPixmap pixmap( icon.pixmap( iconSize, iconSize ) );
QPainter painter( &pixmap );
painter.drawPixmap( 0, 0, 16, 16, QgsApplication::getThemePixmap( vlayer->isModified() ? "/mIconEditableEdits.svg" : "/mActionToggleEditing.svg" ) );
painter.drawPixmap( 0, 0, iconSize, iconSize, QgsApplication::getThemePixmap( vlayer->isModified() ? QStringLiteral( "/mIconEditableEdits.svg" ) : QStringLiteral( "/mActionToggleEditing.svg" ) ) );
painter.end();
icon = QIcon( pixmap );
@ -690,6 +691,13 @@ void QgsLayerTreeModel::setLayerStyleOverrides( const QMap<QString, QString> &ov
mLayerStyleOverrides = overrides;
}
int QgsLayerTreeModel::scaleIconSize( int standardSize )
{
QFontMetrics fm( ( QFont() ) );
const double scale = 1.1 * standardSize / 24;
return static_cast< int >( std::floor( std::max( Qgis::UI_SCALE_FACTOR * fm.height() * scale, static_cast< double >( standardSize ) ) ) );
}
void QgsLayerTreeModel::nodeWillAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo )
{
Q_ASSERT( node );

View File

@ -274,6 +274,17 @@ class CORE_EXPORT QgsLayerTreeModel : public QAbstractItemModel
*/
void setLayerStyleOverrides( const QMap<QString, QString> &overrides );
/**
* Scales an layer tree model icon size to compensate for display pixel density, making the icon
* size hi-dpi friendly, whilst still resulting in pixel-perfect sizes for low-dpi
* displays.
*
* \a standardSize should be set to a standard icon size, e.g. 16, 24, 48, etc.
*
* \since QGIS 3.6
*/
static int scaleIconSize( int standardSize );
protected slots:
void nodeWillAddChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );
void nodeAddedChildren( QgsLayerTreeNode *node, int indexFrom, int indexTo );

View File

@ -130,13 +130,14 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
// -------------------------------------------------------------------------
QgsSymbolLegendNode::QgsSymbolLegendNode( QgsLayerTreeLayer *nodeLayer, const QgsLegendSymbolItem &item, QObject *parent )
: QgsLayerTreeModelLegendNode( nodeLayer, parent )
, mItem( item )
, mSymbolUsesMapUnits( false )
, mIconSize( 16, 16 )
{
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
mIconSize = QSize( iconSize, iconSize );
updateLabel();
connect( qobject_cast<QgsVectorLayer *>( nodeLayer->layer() ), &QgsVectorLayer::symbolFeatureCountMapChanged, this, &QgsSymbolLegendNode::updateLabel );
connect( nodeLayer, &QObject::destroyed, this, [ = ]() { mLayerNode = nullptr; } );
@ -162,11 +163,13 @@ QSize QgsSymbolLegendNode::minimumIconSize() const
QSize QgsSymbolLegendNode::minimumIconSize( QgsRenderContext *context ) const
{
QSize minSz( 16, 16 );
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 );
const int largeIconSize = QgsLayerTreeModel::scaleIconSize( 512 );
QSize minSz( iconSize, iconSize );
if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Marker )
{
minSz = QgsImageOperation::nonTransparentImageRect(
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( 512, 512 ), 0,
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( largeIconSize, largeIconSize ), 0,
context ).toImage(),
minSz,
true ).size();
@ -174,7 +177,7 @@ QSize QgsSymbolLegendNode::minimumIconSize( QgsRenderContext *context ) const
else if ( mItem.symbol() && mItem.symbol()->type() == QgsSymbol::Line )
{
minSz = QgsImageOperation::nonTransparentImageRect(
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), 512 ), 0,
QgsSymbolLayerUtils::symbolPreviewPixmap( mItem.symbol(), QSize( minSz.width(), largeIconSize ), 0,
context ).toImage(),
minSz,
true ).size();
@ -607,8 +610,8 @@ QVariant QgsRasterSymbolLegendNode::data( int role ) const
{
if ( role == Qt::DecorationRole )
{
QSize iconSize( 16, 16 ); // TODO: configurable?
QPixmap pix( iconSize );
const int iconSize = QgsLayerTreeModel::scaleIconSize( 16 ); // TODO: configurable?
QPixmap pix( iconSize, iconSize );
pix.fill( mColor );
return QIcon( pix );
}