mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
Fix incorrect sizing of symbol layer previews on hidpi display,
pixelated icons
This commit is contained in:
parent
14cf1de302
commit
1298018bc4
@ -338,7 +338,7 @@ Draws a symbol layer preview to a QPicture
|
||||
.. versionadded:: 2.9
|
||||
%End
|
||||
|
||||
static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer = 0 );
|
||||
static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer = 0, const QScreen *screen = 0 );
|
||||
%Docstring
|
||||
Draws a symbol layer preview to an icon.
|
||||
|
||||
@ -348,6 +348,7 @@ Draws a symbol layer preview to an icon.
|
||||
:param scale: map unit scale for preview
|
||||
:param parentSymbolType: since QGIS 3.22, can be used to specify the parent symbol type so that geometry generator preview icons are correctly calculated
|
||||
:param mapLayer: since QGIS 3.28, can be used to specify the associated map layer so that layer related expressions are correctly calculated
|
||||
:param screen: since QGIS 3.32, can be used to specify the destination screen for the icon. This allows the icon to be generated using the correct DPI and device pixel ratio for the target screen.
|
||||
|
||||
:return: icon containing symbol layer preview
|
||||
|
||||
|
@ -148,7 +148,7 @@ QgsRenderContext QgsRenderContext::fromQPainter( QPainter *painter )
|
||||
context.setPainter( painter );
|
||||
if ( painter && painter->device() )
|
||||
{
|
||||
context.setScaleFactor( painter->device()->logicalDpiX() / 25.4 );
|
||||
context.setScaleFactor( painter->device()->physicalDpiX() / 25.4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "qgssymbollayerreference.h"
|
||||
#include "qgsmarkersymbollayer.h"
|
||||
#include "qmath.h"
|
||||
#include "qgsmasksymbollayer.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QFont>
|
||||
@ -981,16 +980,25 @@ QPicture QgsSymbolLayerUtils::symbolLayerPreviewPicture( const QgsSymbolLayer *l
|
||||
return picture;
|
||||
}
|
||||
|
||||
QIcon QgsSymbolLayerUtils::symbolLayerPreviewIcon( const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &, Qgis::SymbolType parentSymbolType, QgsMapLayer *mapLayer )
|
||||
QIcon QgsSymbolLayerUtils::symbolLayerPreviewIcon( const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &, Qgis::SymbolType parentSymbolType, QgsMapLayer *mapLayer, const QScreen *screen )
|
||||
{
|
||||
QPixmap pixmap( size );
|
||||
const double devicePixelRatio = screen ? screen->devicePixelRatio() : 1;
|
||||
QPixmap pixmap( size * devicePixelRatio );
|
||||
pixmap.setDevicePixelRatio( devicePixelRatio );
|
||||
pixmap.fill( Qt::transparent );
|
||||
QPainter painter;
|
||||
painter.begin( &pixmap );
|
||||
painter.setRenderHint( QPainter::Antialiasing );
|
||||
QgsRenderContext renderContext = QgsRenderContext::fromQPainter( &painter );
|
||||
|
||||
if ( screen )
|
||||
{
|
||||
renderContext.setScaleFactor( screen->physicalDotsPerInch() / 25.4 );
|
||||
}
|
||||
|
||||
renderContext.setFlag( Qgis::RenderContextFlag::RenderSymbolPreview );
|
||||
renderContext.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms );
|
||||
renderContext.setDevicePixelRatio( devicePixelRatio );
|
||||
// build a minimal expression context
|
||||
QgsExpressionContext expContext;
|
||||
expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mapLayer ) );
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "qgscolorramp.h"
|
||||
#include "qgsarrowsymbollayer.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qscreen.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
@ -324,10 +325,11 @@ class CORE_EXPORT QgsSymbolLayerUtils
|
||||
* \param scale map unit scale for preview
|
||||
* \param parentSymbolType since QGIS 3.22, can be used to specify the parent symbol type so that geometry generator preview icons are correctly calculated
|
||||
* \param mapLayer since QGIS 3.28, can be used to specify the associated map layer so that layer related expressions are correctly calculated
|
||||
* \param screen since QGIS 3.32, can be used to specify the destination screen for the icon. This allows the icon to be generated using the correct DPI and device pixel ratio for the target screen.
|
||||
* \returns icon containing symbol layer preview
|
||||
* \see symbolLayerPreviewPicture()
|
||||
*/
|
||||
static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer = nullptr );
|
||||
static QIcon symbolLayerPreviewIcon( const QgsSymbolLayer *layer, Qgis::RenderUnit u, QSize size, const QgsMapUnitScale &scale = QgsMapUnitScale(), Qgis::SymbolType parentSymbolType = Qgis::SymbolType::Hybrid, QgsMapLayer *mapLayer = nullptr, const QScreen *screen = nullptr );
|
||||
|
||||
/**
|
||||
* Returns an icon preview for a color ramp.
|
||||
|
@ -63,8 +63,11 @@ void QgsMaskSourceSelectionWidget::update()
|
||||
class SymbolLayerFillVisitor : public QgsStyleEntityVisitorInterface
|
||||
{
|
||||
public:
|
||||
SymbolLayerFillVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &items ):
|
||||
mLayerItem( layerItem ), mLayer( layer ), mItems( items )
|
||||
SymbolLayerFillVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &items, const QScreen *screen )
|
||||
: mLayerItem( layerItem )
|
||||
, mLayer( layer )
|
||||
, mItems( items )
|
||||
, mScreen( screen )
|
||||
{}
|
||||
|
||||
bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
|
||||
@ -90,7 +93,7 @@ void QgsMaskSourceSelectionWidget::update()
|
||||
indexPath.append( idx );
|
||||
|
||||
std::unique_ptr< QTreeWidgetItem > slItem = std::make_unique< QTreeWidgetItem >( rootItem );
|
||||
const QIcon slIcon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), symbol->type() );
|
||||
const QIcon slIcon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), symbol->type(), nullptr, mScreen );
|
||||
slItem->setIcon( 0, slIcon );
|
||||
if ( sl->layerType() == "MaskMarker" )
|
||||
{
|
||||
@ -137,6 +140,7 @@ void QgsMaskSourceSelectionWidget::update()
|
||||
QTreeWidgetItem *mLayerItem;
|
||||
const QgsVectorLayer *mLayer;
|
||||
QHash<QgsSymbolLayerReference, QTreeWidgetItem *> &mItems;
|
||||
const QScreen *mScreen = nullptr;
|
||||
};
|
||||
|
||||
class LabelMasksVisitor : public QgsStyleEntityVisitorInterface
|
||||
@ -204,7 +208,7 @@ void QgsMaskSourceSelectionWidget::update()
|
||||
vl->labeling()->accept( &lblVisitor );
|
||||
}
|
||||
|
||||
SymbolLayerFillVisitor slVisitor( layerItem.get(), vl, mItems );
|
||||
SymbolLayerFillVisitor slVisitor( layerItem.get(), vl, mItems, screen() );
|
||||
vl->renderer()->accept( &slVisitor );
|
||||
|
||||
if ( layerItem->childCount() > 0 )
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <QVBoxLayout>
|
||||
|
||||
#include "qgssymbollayerselectionwidget.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
#include "symbology/qgsrenderer.h"
|
||||
#include "qgsstyleentityvisitor.h"
|
||||
@ -49,8 +48,11 @@ void QgsSymbolLayerSelectionWidget::setLayer( const QgsVectorLayer *layer )
|
||||
class TreeFillVisitor : public QgsStyleEntityVisitorInterface
|
||||
{
|
||||
public:
|
||||
TreeFillVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QString, QTreeWidgetItem *> &items ):
|
||||
mLayerItem( layerItem ), mLayer( layer ), mItems( items )
|
||||
TreeFillVisitor( QTreeWidgetItem *layerItem, const QgsVectorLayer *layer, QHash<QString, QTreeWidgetItem *> &items, const QScreen *screen )
|
||||
: mLayerItem( layerItem )
|
||||
, mLayer( layer )
|
||||
, mItems( items )
|
||||
, mScreen( screen )
|
||||
{}
|
||||
|
||||
bool visitEnter( const QgsStyleEntityVisitorInterface::Node &node ) override
|
||||
@ -79,7 +81,7 @@ void QgsSymbolLayerSelectionWidget::setLayer( const QgsVectorLayer *layer )
|
||||
indexPath.append( idx );
|
||||
|
||||
QTreeWidgetItem *slItem = new QTreeWidgetItem();
|
||||
const QIcon slIcon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), symbol->type() );
|
||||
const QIcon slIcon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), symbol->type(), nullptr, mScreen );
|
||||
slItem->setData( 0, Qt::UserRole, idx );
|
||||
slItem->setIcon( 0, slIcon );
|
||||
auto flags = slItem->flags();
|
||||
@ -134,6 +136,7 @@ void QgsSymbolLayerSelectionWidget::setLayer( const QgsVectorLayer *layer )
|
||||
QTreeWidgetItem *mLayerItem;
|
||||
const QgsVectorLayer *mLayer;
|
||||
QHash<QString, QTreeWidgetItem *> &mItems;
|
||||
const QScreen *mScreen = nullptr;
|
||||
};
|
||||
|
||||
// populate the tree
|
||||
@ -142,7 +145,7 @@ void QgsSymbolLayerSelectionWidget::setLayer( const QgsVectorLayer *layer )
|
||||
if ( ! mLayer->renderer() )
|
||||
return;
|
||||
|
||||
TreeFillVisitor visitor( mTree->invisibleRootItem(), mLayer, mItems );
|
||||
TreeFillVisitor visitor( mTree->invisibleRootItem(), mLayer, mItems, screen() );
|
||||
mLayer->renderer()->accept( &visitor );
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ QgsEllipseSymbolLayerWidget::QgsEllipseSymbolLayerWidget( QgsVectorLayer *vl, QW
|
||||
lyr->setFillColor( QColor( 200, 200, 200 ) );
|
||||
lyr->setSymbolWidth( markerSize );
|
||||
lyr->setSymbolHeight( markerSize * 0.75 );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, Qgis::RenderUnit::Pixels, QSize( size, size ) );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, Qgis::RenderUnit::Pixels, QSize( size, size ), QgsMapUnitScale(), Qgis::SymbolType::Hybrid, nullptr, screen() );
|
||||
QListWidgetItem *item = new QListWidgetItem( icon, QString(), mShapeListWidget );
|
||||
item->setData( Qt::UserRole, static_cast< int >( shape ) );
|
||||
item->setToolTip( QgsEllipseSymbolLayer::encodeShape( shape ) );
|
||||
|
@ -698,7 +698,7 @@ QgsSimpleMarkerSymbolLayerWidget::QgsSimpleMarkerSymbolLayerWidget( QgsVectorLay
|
||||
lyr->setSizeUnit( Qgis::RenderUnit::Pixels );
|
||||
lyr->setColor( QColor( 200, 200, 200 ) );
|
||||
lyr->setStrokeColor( QColor( 0, 0, 0 ) );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, Qgis::RenderUnit::Pixels, QSize( size, size ) );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, Qgis::RenderUnit::Pixels, QSize( size, size ), QgsMapUnitScale(), Qgis::SymbolType::Hybrid, nullptr, screen() );
|
||||
QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
|
||||
item->setData( Qt::UserRole, static_cast< int >( shape ) );
|
||||
item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
|
||||
@ -1141,7 +1141,7 @@ QgsFilledMarkerSymbolLayerWidget::QgsFilledMarkerSymbolLayerWidget( QgsVectorLay
|
||||
lyr->setSizeUnit( Qgis::RenderUnit::Pixels );
|
||||
lyr->setColor( QColor( 200, 200, 200 ) );
|
||||
lyr->setStrokeColor( QColor( 0, 0, 0 ) );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, Qgis::RenderUnit::Pixels, QSize( size, size ) );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( lyr, Qgis::RenderUnit::Pixels, QSize( size, size ), QgsMapUnitScale(), Qgis::SymbolType::Hybrid, nullptr, screen() );
|
||||
QListWidgetItem *item = new QListWidgetItem( icon, QString(), lstNames );
|
||||
item->setData( Qt::UserRole, static_cast< int >( shape ) );
|
||||
item->setToolTip( QgsSimpleMarkerSymbolLayerBase::encodeShape( shape ) );
|
||||
|
@ -111,7 +111,7 @@ void QgsSymbolLevelsWidget::populateTable()
|
||||
else
|
||||
{
|
||||
const QgsSymbolLayer *sl = sym->symbolLayer( layer );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), sym->type() );
|
||||
const QIcon icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( sl, Qgis::RenderUnit::Millimeters, QSize( iconSize, iconSize ), QgsMapUnitScale(), sym->type(), nullptr, screen() );
|
||||
item = new QTableWidgetItem( icon, QString::number( sl->renderingPass() ) );
|
||||
}
|
||||
tableLevels->setItem( row, layer + 1, item );
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qgsgui.h"
|
||||
#include "qgsmarkersymbol.h"
|
||||
#include "qgslinesymbol.h"
|
||||
#include "qscreen.h"
|
||||
|
||||
#include <QColorDialog>
|
||||
#include <QPainter>
|
||||
@ -117,14 +118,16 @@ void DataDefinedRestorer::restore()
|
||||
class SymbolLayerItem : public QStandardItem
|
||||
{
|
||||
public:
|
||||
explicit SymbolLayerItem( QgsSymbolLayer *layer, Qgis::SymbolType symbolType, QgsVectorLayer *vectorLayer )
|
||||
explicit SymbolLayerItem( QgsSymbolLayer *layer, Qgis::SymbolType symbolType, QgsVectorLayer *vectorLayer, const QScreen *screen )
|
||||
: mVectorLayer( vectorLayer )
|
||||
, mScreen( screen )
|
||||
{
|
||||
setLayer( layer, symbolType );
|
||||
}
|
||||
|
||||
explicit SymbolLayerItem( QgsSymbol *symbol, QgsVectorLayer *vectorLayer )
|
||||
explicit SymbolLayerItem( QgsSymbol *symbol, QgsVectorLayer *vectorLayer, const QScreen *screen )
|
||||
: mVectorLayer( vectorLayer )
|
||||
, mScreen( screen )
|
||||
{
|
||||
setSymbol( symbol );
|
||||
}
|
||||
@ -155,7 +158,7 @@ class SymbolLayerItem : public QStandardItem
|
||||
}
|
||||
QIcon icon;
|
||||
if ( mIsLayer )
|
||||
icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( mLayer, Qgis::RenderUnit::Millimeters, mSize, QgsMapUnitScale(), mSymbol ? mSymbol->type() : mSymbolType, mVectorLayer ); //todo: make unit a parameter
|
||||
icon = QgsSymbolLayerUtils::symbolLayerPreviewIcon( mLayer, Qgis::RenderUnit::Millimeters, mSize, QgsMapUnitScale(), mSymbol ? mSymbol->type() : mSymbolType, mVectorLayer, mScreen );
|
||||
else
|
||||
{
|
||||
QgsExpressionContext expContext;
|
||||
@ -238,6 +241,7 @@ class SymbolLayerItem : public QStandardItem
|
||||
bool mIsLayer = false;
|
||||
QSize mSize;
|
||||
Qgis::SymbolType mSymbolType = Qgis::SymbolType::Hybrid;
|
||||
const QScreen *mScreen = nullptr;
|
||||
};
|
||||
|
||||
///@endcond
|
||||
@ -391,7 +395,7 @@ void QgsSymbolSelectorWidget::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *pa
|
||||
parent = static_cast<SymbolLayerItem *>( mSymbolLayersModel->invisibleRootItem() );
|
||||
}
|
||||
|
||||
SymbolLayerItem *symbolItem = new SymbolLayerItem( symbol, mVectorLayer );
|
||||
SymbolLayerItem *symbolItem = new SymbolLayerItem( symbol, mVectorLayer, screen() );
|
||||
QFont boldFont = symbolItem->font();
|
||||
boldFont.setBold( true );
|
||||
symbolItem->setFont( boldFont );
|
||||
@ -400,7 +404,7 @@ void QgsSymbolSelectorWidget::loadSymbol( QgsSymbol *symbol, SymbolLayerItem *pa
|
||||
const int count = symbol->symbolLayerCount();
|
||||
for ( int i = count - 1; i >= 0; i-- )
|
||||
{
|
||||
SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ), symbol->type(), mVectorLayer );
|
||||
SymbolLayerItem *layerItem = new SymbolLayerItem( symbol->symbolLayer( i ), symbol->type(), mVectorLayer, screen() );
|
||||
layerItem->setEditable( false );
|
||||
symbolItem->appendRow( layerItem );
|
||||
if ( symbol->symbolLayer( i )->subSymbol() )
|
||||
@ -627,7 +631,7 @@ void QgsSymbolSelectorWidget::addLayer()
|
||||
if ( ddWidth )
|
||||
static_cast<QgsLineSymbol *>( parentSymbol )->setDataDefinedWidth( ddWidth );
|
||||
|
||||
SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer );
|
||||
SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer, screen() );
|
||||
item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
|
||||
item->updatePreview();
|
||||
|
||||
@ -727,7 +731,7 @@ void QgsSymbolSelectorWidget::duplicateLayer()
|
||||
else
|
||||
parentSymbol->insertSymbolLayer( item->rowCount() - insertIdx, newLayer );
|
||||
|
||||
SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer );
|
||||
SymbolLayerItem *newLayerItem = new SymbolLayerItem( newLayer, parentSymbol->type(), mVectorLayer, screen() );
|
||||
item->insertRow( insertIdx == -1 ? 0 : insertIdx, newLayerItem );
|
||||
if ( newLayer->subSymbol() )
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user