Fix incorrect sizing & pixelation of symbol previews on hidpi

displays
This commit is contained in:
Nyall Dawson 2023-06-21 17:33:14 +10:00
parent 1298018bc4
commit 0641766902
23 changed files with 99 additions and 84 deletions

View File

@ -9,6 +9,7 @@
typedef QList<QgsSymbolLayer *> QgsSymbolLayerList; typedef QList<QgsSymbolLayer *> QgsSymbolLayerList;
class QgsSymbolAnimationSettings class QgsSymbolAnimationSettings
@ -334,7 +335,7 @@ layer.
%End %End
void drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext = 0, bool selected = false, const QgsExpressionContext *expressionContext = 0, void drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext = 0, bool selected = false, const QgsExpressionContext *expressionContext = 0,
const QgsLegendPatchShape *patchShape = 0 ); const QgsLegendPatchShape *patchShape = 0, const QScreen *screen = 0 );
%Docstring %Docstring
Draws an icon of the symbol that occupies an area given by ``size`` using the specified ``painter``. Draws an icon of the symbol that occupies an area given by ``size`` using the specified ``painter``.
@ -344,18 +345,15 @@ matches the settings from that context.
:param painter: destination painter :param painter: destination painter
:param size: size of the icon :param size: size of the icon
:param customContext: the context in which the rendering happens :param customContext: the context in which the rendering happens
:param selected: set to ``True`` to render the symbol in a selected state :param selected: set to ``True`` to render the symbol in a selected state (since QGIS 3.10)
:param expressionContext: optional custom expression context :param expressionContext: optional custom expression context
:param patchShape: optional patch shape to use for symbol preview. If not specified a default shape will be used instead. :param patchShape: optional patch shape to use for symbol preview. If not specified a default shape will be used instead.
:param screen: 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 (since QGIS 3.32)
.. seealso:: :py:func:`exportImage` .. seealso:: :py:func:`exportImage`
.. seealso:: :py:func:`asImage` .. seealso:: :py:func:`asImage`
.. note::
Parameter selected added in QGIS 3.10
.. versionadded:: 2.6 .. versionadded:: 2.6
%End %End
@ -383,13 +381,14 @@ matches the settings from that context.
.. seealso:: :py:func:`drawPreviewIcon` .. seealso:: :py:func:`drawPreviewIcon`
%End %End
QImage bigSymbolPreviewImage( QgsExpressionContext *expressionContext = 0, Qgis::SymbolPreviewFlags flags = Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols ) /PyName=bigSymbolPreviewImageV2/; QImage bigSymbolPreviewImage( QgsExpressionContext *expressionContext = 0, Qgis::SymbolPreviewFlags flags = Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols, const QScreen *screen = 0 ) /PyName=bigSymbolPreviewImageV2/;
%Docstring %Docstring
Returns a large (roughly 100x100 pixel) preview image for the symbol. Returns a large (roughly 100x100 pixel) preview image for the symbol.
:param expressionContext: optional expression context, for evaluation of :param expressionContext: optional expression context, for evaluation of
data defined symbol properties data defined symbol properties
:param flags: optional flags to control how preview image is generated :param flags: optional flags to control how preview image is generated
:param screen: 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 (since QGIS 3.32)
.. seealso:: :py:func:`asImage` .. seealso:: :py:func:`asImage`

View File

@ -276,7 +276,7 @@ Decodes a symbol scale method from a string.
static QPainter::CompositionMode decodeBlendMode( const QString &s ); static QPainter::CompositionMode decodeBlendMode( const QString &s );
static QIcon symbolPreviewIcon( const QgsSymbol *symbol, QSize size, int padding = 0, QgsLegendPatchShape *shape = 0 ); static QIcon symbolPreviewIcon( const QgsSymbol *symbol, QSize size, int padding = 0, QgsLegendPatchShape *shape = 0, const QScreen *screen = 0 );
%Docstring %Docstring
Returns an icon preview for a color ramp. Returns an icon preview for a color ramp.
@ -284,39 +284,26 @@ Returns an icon preview for a color ramp.
:param size: target pixmap size :param size: target pixmap size
:param padding: space between icon edge and symbol :param padding: space between icon edge and symbol
:param shape: optional legend patch shape to use for rendering the preview icon :param shape: optional legend patch shape to use for rendering the preview icon
:param screen: 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 (since QGIS 3.32)
.. seealso:: :py:func:`symbolPreviewPixmap` .. seealso:: :py:func:`symbolPreviewPixmap`
%End %End
static QPixmap symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding = 0, QgsRenderContext *customContext = 0, bool selected = false, static QPixmap symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding = 0, QgsRenderContext *customContext = 0, bool selected = false,
const QgsExpressionContext *expressionContext = 0, const QgsExpressionContext *expressionContext = 0,
const QgsLegendPatchShape *shape = 0 ); const QgsLegendPatchShape *shape = 0,
const QScreen *screen = 0 );
%Docstring %Docstring
Returns a pixmap preview for a color ramp. Returns a pixmap preview for a color ramp.
:param symbol: symbol :param symbol: symbol
:param size: target pixmap size :param size: target pixmap size
:param padding: space between icon edge and symbol :param padding: space between icon edge and symbol
:param customContext: render context to use when rendering symbol :param customContext: render context to use when rendering symbol (since QGIS 2.6)
:param selected: set to ``True`` to render the symbol in a selected state :param selected: set to ``True`` to render the symbol in a selected state (since QGIS 3.10)
:param expressionContext: optional custom expression context :param expressionContext: optional custom expression context (since QGIS 3.10)
:param shape: optional legend patch shape to use for rendering the preview icon :param shape: optional legend patch shape to use for rendering the preview icon (since QGIS 3.14)
:param screen: 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 (since QGIS 3.32)
.. note::
Parameter customContext added in QGIS 2.6
.. note::
Parameter selected added in QGIS 3.10
.. note::
Parameter expressionContext added in QGIS 3.10
.. note::
Parameter shape added in QGIS 3.14
.. seealso:: :py:func:`symbolPreviewIcon` .. seealso:: :py:func:`symbolPreviewIcon`
%End %End

View File

@ -27,7 +27,7 @@ Tree model for the rules:
%End %End
public: public:
QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent ); QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent, const QScreen *screen = 0 );
%Docstring %Docstring
Constructor for QgsRuleBasedRendererModel, for the specified ``renderer``. Constructor for QgsRuleBasedRendererModel, for the specified ``renderer``.
%End %End

View File

@ -923,7 +923,7 @@ QColor QgsSymbol::color() const
return QColor( 0, 0, 0 ); return QColor( 0, 0, 0 );
} }
void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext, bool selected, const QgsExpressionContext *expressionContext, const QgsLegendPatchShape *patchShape ) void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext, bool selected, const QgsExpressionContext *expressionContext, const QgsLegendPatchShape *patchShape, const QScreen *screen )
{ {
QgsRenderContext *context = customContext; QgsRenderContext *context = customContext;
std::unique_ptr< QgsRenderContext > tempContext; std::unique_ptr< QgsRenderContext > tempContext;
@ -934,6 +934,12 @@ void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext
context->setFlag( Qgis::RenderContextFlag::RenderSymbolPreview, true ); context->setFlag( Qgis::RenderContextFlag::RenderSymbolPreview, true );
} }
if ( screen )
{
context->setScaleFactor( screen->physicalDotsPerInch() / 25.4 );
context->setDevicePixelRatio( screen->devicePixelRatio() );
}
const bool prevForceVector = context->forceVectorOutput(); const bool prevForceVector = context->forceVectorOutput();
context->setForceVectorOutput( true ); context->setForceVectorOutput( true );
@ -1055,10 +1061,12 @@ QImage QgsSymbol::asImage( QSize size, QgsRenderContext *customContext )
} }
QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext, Qgis::SymbolPreviewFlags flags ) QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext, Qgis::SymbolPreviewFlags flags, const QScreen *screen )
{ {
QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied ); const double devicePixelRatio = screen ? screen->devicePixelRatio() : 1;
QImage preview( QSize( 100, 100 ) * devicePixelRatio, QImage::Format_ARGB32_Premultiplied );
preview.fill( 0 ); preview.fill( 0 );
preview.setDevicePixelRatio( devicePixelRatio );
QPainter p( &preview ); QPainter p( &preview );
p.setRenderHint( QPainter::Antialiasing ); p.setRenderHint( QPainter::Antialiasing );
@ -1067,8 +1075,8 @@ QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext
if ( mType == Qgis::SymbolType::Marker && flags & Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols ) if ( mType == Qgis::SymbolType::Marker && flags & Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols )
{ {
p.setPen( QPen( Qt::gray ) ); p.setPen( QPen( Qt::gray ) );
p.drawLine( 0, 50, 100, 50 ); p.drawLine( QLineF( 0, 50, 100, 50 ) );
p.drawLine( 50, 0, 50, 100 ); p.drawLine( QLineF( 50, 0, 50, 100 ) );
} }
QgsRenderContext context = QgsRenderContext::fromQPainter( &p ); QgsRenderContext context = QgsRenderContext::fromQPainter( &p );
@ -1076,6 +1084,13 @@ QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext
context.setFlag( Qgis::RenderContextFlag::Antialiasing ); context.setFlag( Qgis::RenderContextFlag::Antialiasing );
context.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms ); context.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms );
context.setPainterFlagsUsingContext( &p ); context.setPainterFlagsUsingContext( &p );
context.setDevicePixelRatio( devicePixelRatio );
if ( screen )
{
context.setScaleFactor( screen->physicalDotsPerInch() / 25.4 );
}
if ( expressionContext ) if ( expressionContext )
context.setExpressionContext( *expressionContext ); context.setExpressionContext( *expressionContext );

View File

@ -26,6 +26,8 @@ class QgsLegendPatchShape;
class QgsSymbolRenderContext; class QgsSymbolRenderContext;
class QgsLineSymbolLayer; class QgsLineSymbolLayer;
class QScreen;
typedef QList<QgsSymbolLayer *> QgsSymbolLayerList; typedef QList<QgsSymbolLayer *> QgsSymbolLayerList;
/** /**
@ -371,17 +373,17 @@ class CORE_EXPORT QgsSymbol
* \param painter destination painter * \param painter destination painter
* \param size size of the icon * \param size size of the icon
* \param customContext the context in which the rendering happens * \param customContext the context in which the rendering happens
* \param selected set to TRUE to render the symbol in a selected state * \param selected set to TRUE to render the symbol in a selected state (since QGIS 3.10)
* \param expressionContext optional custom expression context * \param expressionContext optional custom expression context
* \param patchShape optional patch shape to use for symbol preview. If not specified a default shape will be used instead. * \param patchShape optional patch shape to use for symbol preview. If not specified a default shape will be used instead.
* \param screen 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 (since QGIS 3.32)
* *
* \see exportImage() * \see exportImage()
* \see asImage() * \see asImage()
* \note Parameter selected added in QGIS 3.10
* \since QGIS 2.6 * \since QGIS 2.6
*/ */
void drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext = nullptr, bool selected = false, const QgsExpressionContext *expressionContext = nullptr, void drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext *customContext = nullptr, bool selected = false, const QgsExpressionContext *expressionContext = nullptr,
const QgsLegendPatchShape *patchShape = nullptr ); const QgsLegendPatchShape *patchShape = nullptr, const QScreen *screen = nullptr );
/** /**
* Export the symbol as an image format, to the specified \a path and with the given \a size. * Export the symbol as an image format, to the specified \a path and with the given \a size.
@ -411,11 +413,12 @@ class CORE_EXPORT QgsSymbol
* \param expressionContext optional expression context, for evaluation of * \param expressionContext optional expression context, for evaluation of
* data defined symbol properties * data defined symbol properties
* \param flags optional flags to control how preview image is generated * \param flags optional flags to control how preview image is generated
* \param screen 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 (since QGIS 3.32)
* *
* \see asImage() * \see asImage()
* \see drawPreviewIcon() * \see drawPreviewIcon()
*/ */
QImage bigSymbolPreviewImage( QgsExpressionContext *expressionContext = nullptr, Qgis::SymbolPreviewFlags flags = Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols ) SIP_PYNAME( bigSymbolPreviewImageV2 ); QImage bigSymbolPreviewImage( QgsExpressionContext *expressionContext = nullptr, Qgis::SymbolPreviewFlags flags = Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols, const QScreen *screen = nullptr ) SIP_PYNAME( bigSymbolPreviewImageV2 );
/** /**
* \deprecated use bigSymbolPreviewImageV2 instead. * \deprecated use bigSymbolPreviewImageV2 instead.

View File

@ -868,15 +868,19 @@ QPainter::CompositionMode QgsSymbolLayerUtils::decodeBlendMode( const QString &s
return QPainter::CompositionMode_SourceOver; // "Normal" return QPainter::CompositionMode_SourceOver; // "Normal"
} }
QIcon QgsSymbolLayerUtils::symbolPreviewIcon( const QgsSymbol *symbol, QSize size, int padding, QgsLegendPatchShape *shape ) QIcon QgsSymbolLayerUtils::symbolPreviewIcon( const QgsSymbol *symbol, QSize size, int padding, QgsLegendPatchShape *shape, const QScreen *screen )
{ {
return QIcon( symbolPreviewPixmap( symbol, size, padding, nullptr, false, nullptr, shape ) ); return QIcon( symbolPreviewPixmap( symbol, size, padding, nullptr, false, nullptr, shape, screen ) );
} }
QPixmap QgsSymbolLayerUtils::symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding, QgsRenderContext *customContext, bool selected, const QgsExpressionContext *expressionContext, const QgsLegendPatchShape *shape ) QPixmap QgsSymbolLayerUtils::symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding, QgsRenderContext *customContext, bool selected, const QgsExpressionContext *expressionContext, const QgsLegendPatchShape *shape, const QScreen *screen )
{ {
Q_ASSERT( symbol ); Q_ASSERT( symbol );
QPixmap pixmap( size );
const double devicePixelRatio = screen ? screen->devicePixelRatio() : 1;
QPixmap pixmap( size * devicePixelRatio );
pixmap.setDevicePixelRatio( devicePixelRatio );
pixmap.fill( Qt::transparent ); pixmap.fill( Qt::transparent );
QPainter painter; QPainter painter;
painter.begin( &pixmap ); painter.begin( &pixmap );
@ -919,12 +923,12 @@ QPixmap QgsSymbolLayerUtils::symbolPreviewPixmap( const QgsSymbol *symbol, QSize
prop.setActive( false ); prop.setActive( false );
} }
} }
symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape ); symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
} }
else else
{ {
std::unique_ptr<QgsSymbol> symbolClone( symbol->clone( ) ); std::unique_ptr<QgsSymbol> symbolClone( symbol->clone( ) );
symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape ); symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen );
} }
painter.end(); painter.end();

View File

@ -281,28 +281,27 @@ class CORE_EXPORT QgsSymbolLayerUtils
* \param size target pixmap size * \param size target pixmap size
* \param padding space between icon edge and symbol * \param padding space between icon edge and symbol
* \param shape optional legend patch shape to use for rendering the preview icon * \param shape optional legend patch shape to use for rendering the preview icon
* \param screen 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 (since QGIS 3.32)
* \see symbolPreviewPixmap() * \see symbolPreviewPixmap()
*/ */
static QIcon symbolPreviewIcon( const QgsSymbol *symbol, QSize size, int padding = 0, QgsLegendPatchShape *shape = nullptr ); static QIcon symbolPreviewIcon( const QgsSymbol *symbol, QSize size, int padding = 0, QgsLegendPatchShape *shape = nullptr, const QScreen *screen = nullptr );
/** /**
* Returns a pixmap preview for a color ramp. * Returns a pixmap preview for a color ramp.
* \param symbol symbol * \param symbol symbol
* \param size target pixmap size * \param size target pixmap size
* \param padding space between icon edge and symbol * \param padding space between icon edge and symbol
* \param customContext render context to use when rendering symbol * \param customContext render context to use when rendering symbol (since QGIS 2.6)
* \param selected set to TRUE to render the symbol in a selected state * \param selected set to TRUE to render the symbol in a selected state (since QGIS 3.10)
* \param expressionContext optional custom expression context * \param expressionContext optional custom expression context (since QGIS 3.10)
* \param shape optional legend patch shape to use for rendering the preview icon * \param shape optional legend patch shape to use for rendering the preview icon (since QGIS 3.14)
* \note Parameter customContext added in QGIS 2.6 * \param screen 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 (since QGIS 3.32)
* \note Parameter selected added in QGIS 3.10
* \note Parameter expressionContext added in QGIS 3.10
* \note Parameter shape added in QGIS 3.14
* \see symbolPreviewIcon() * \see symbolPreviewIcon()
*/ */
static QPixmap symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding = 0, QgsRenderContext *customContext = nullptr, bool selected = false, static QPixmap symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding = 0, QgsRenderContext *customContext = nullptr, bool selected = false,
const QgsExpressionContext *expressionContext = nullptr, const QgsExpressionContext *expressionContext = nullptr,
const QgsLegendPatchShape *shape = nullptr ); const QgsLegendPatchShape *shape = nullptr,
const QScreen *screen = nullptr );
/** /**
* Draws a symbol layer preview to a QPicture * Draws a symbol layer preview to a QPicture

View File

@ -287,7 +287,7 @@ void QgsLegendPatchShapeButton::updatePreview()
} }
//create an icon pixmap //create an icon pixmap
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mPreviewSymbol.get(), currentIconSize, currentIconSize.height() / 10, &mShape ); QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mPreviewSymbol.get(), currentIconSize, currentIconSize.height() / 10, &mShape, screen() );
setIconSize( currentIconSize ); setIconSize( currentIconSize );
setIcon( icon ); setIcon( icon );

View File

@ -125,7 +125,7 @@ void QgsMaskSourceSelectionWidget::update()
return true; return true;
std::unique_ptr< QTreeWidgetItem > symbolItem = std::make_unique< QTreeWidgetItem >( mLayerItem, QStringList() << ( mCurrentDescription + leaf.description ) ); std::unique_ptr< QTreeWidgetItem > symbolItem = std::make_unique< QTreeWidgetItem >( mLayerItem, QStringList() << ( mCurrentDescription + leaf.description ) );
const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, QSize( iconSize, iconSize ) ); const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, QSize( iconSize, iconSize ), 0, nullptr, mScreen );
symbolItem->setIcon( 0, icon ); symbolItem->setIcon( 0, icon );
if ( visitSymbol( symbolItem.get(), leaf.identifier, symbol, {} ) ) if ( visitSymbol( symbolItem.get(), leaf.identifier, symbol, {} ) )

View File

@ -507,7 +507,7 @@ void QgsSymbolButton::prepareMenu()
std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) ); std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) );
if ( tempSymbol && tempSymbol->type() == mType ) if ( tempSymbol && tempSymbol->type() == mType )
{ {
pasteSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( tempSymbol.get(), QSize( iconSize, iconSize ), 1 ) ); pasteSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( tempSymbol.get(), QSize( iconSize, iconSize ), 1, nullptr, screen() ) );
} }
else else
{ {
@ -528,7 +528,7 @@ void QgsSymbolButton::prepareMenu()
if ( mDefaultSymbol ) if ( mDefaultSymbol )
{ {
QAction *defaultSymbolAction = new QAction( tr( "Default Symbol" ), this ); QAction *defaultSymbolAction = new QAction( tr( "Default Symbol" ), this );
defaultSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( mDefaultSymbol.get(), QSize( iconSize, iconSize ), 1 ) ); defaultSymbolAction->setIcon( QgsSymbolLayerUtils::symbolPreviewIcon( mDefaultSymbol.get(), QSize( iconSize, iconSize ), 1, nullptr, screen() ) );
mMenu->addAction( defaultSymbolAction ); mMenu->addAction( defaultSymbolAction );
connect( defaultSymbolAction, &QAction::triggered, this, &QgsSymbolButton::setToDefaultSymbol ); connect( defaultSymbolAction, &QAction::triggered, this, &QgsSymbolButton::setToDefaultSymbol );
} }
@ -703,7 +703,7 @@ void QgsSymbolButton::updatePreview( const QColor &color, QgsSymbol *tempSymbol
previewSymbol->setColor( color ); previewSymbol->setColor( color );
//create an icon pixmap //create an icon pixmap
const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize ); const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize, 0, nullptr, screen() );
setIconSize( currentIconSize ); setIconSize( currentIconSize );
setIcon( icon ); setIcon( icon );

View File

@ -119,7 +119,7 @@ void QgsSymbolLayerSelectionWidget::setLayer( const QgsVectorLayer *layer )
// either leaf.description or mCurrentDescription is defined // either leaf.description or mCurrentDescription is defined
QTreeWidgetItem *symbolItem = new QTreeWidgetItem( QStringList() << ( mCurrentDescription + leaf.description ) ); QTreeWidgetItem *symbolItem = new QTreeWidgetItem( QStringList() << ( mCurrentDescription + leaf.description ) );
const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, QSize( iconSize, iconSize ) ); const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( symbol, QSize( iconSize, iconSize ), 0, nullptr, mScreen );
symbolItem->setData( 0, Qt::UserRole, mCurrentIdentifier ); symbolItem->setData( 0, Qt::UserRole, mCurrentIdentifier );
symbolItem->setIcon( 0, icon ); symbolItem->setIcon( 0, icon );
mLayerItem->addChild( symbolItem ); mLayerItem->addChild( symbolItem );

View File

@ -51,8 +51,9 @@
///@cond PRIVATE ///@cond PRIVATE
QgsCategorizedSymbolRendererModel::QgsCategorizedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent ) QgsCategorizedSymbolRendererModel::QgsCategorizedSymbolRendererModel( QObject *parent, const QScreen *screen ) : QAbstractItemModel( parent )
, mMimeFormat( QStringLiteral( "application/x-qgscategorizedsymbolrendererv2model" ) ) , mMimeFormat( QStringLiteral( "application/x-qgscategorizedsymbolrendererv2model" ) )
, mScreen( screen )
{ {
} }
@ -197,7 +198,7 @@ QVariant QgsCategorizedSymbolRendererModel::data( const QModelIndex &index, int
if ( index.column() == 0 && category.symbol() ) if ( index.column() == 0 && category.symbol() )
{ {
const int iconSize = QgsGuiUtils::scaleIconSize( 16 ); const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
return QgsSymbolLayerUtils::symbolPreviewIcon( category.symbol(), QSize( iconSize, iconSize ) ); return QgsSymbolLayerUtils::symbolPreviewIcon( category.symbol(), QSize( iconSize, iconSize ), 0, nullptr, mScreen );
} }
break; break;
} }
@ -669,7 +670,7 @@ QgsCategorizedSymbolRendererWidget::QgsCategorizedSymbolRendererWidget( QgsVecto
btnChangeCategorizedSymbol->setSymbol( mCategorizedSymbol->clone() ); btnChangeCategorizedSymbol->setSymbol( mCategorizedSymbol->clone() );
} }
mModel = new QgsCategorizedSymbolRendererModel( this ); mModel = new QgsCategorizedSymbolRendererModel( this, screen() );
mModel->setRenderer( mRenderer.get() ); mModel->setRenderer( mRenderer.get() );
// update GUI from renderer // update GUI from renderer

View File

@ -37,7 +37,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererModel : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT
public: public:
QgsCategorizedSymbolRendererModel( QObject *parent = nullptr ); QgsCategorizedSymbolRendererModel( QObject *parent = nullptr, const QScreen *screen = nullptr );
Qt::ItemFlags flags( const QModelIndex &index ) const override; Qt::ItemFlags flags( const QModelIndex &index ) const override;
Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDropActions() const override;
QVariant data( const QModelIndex &index, int role ) const override; QVariant data( const QModelIndex &index, int role ) const override;
@ -66,6 +66,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererModel : public QAbstractItemModel
private: private:
QgsCategorizedSymbolRenderer *mRenderer = nullptr; QgsCategorizedSymbolRenderer *mRenderer = nullptr;
QString mMimeFormat; QString mMimeFormat;
const QScreen *mScreen = nullptr;
}; };
/** /**

View File

@ -82,7 +82,7 @@ QgsDataDefinedSizeLegendWidget::QgsDataDefinedSizeLegendWidget( const QgsDataDef
btnChangeSymbol->setEnabled( !mOverrideSymbol ); btnChangeSymbol->setEnabled( !mOverrideSymbol );
const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSourceSymbol.get(), btnChangeSymbol->iconSize() ); const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSourceSymbol.get(), btnChangeSymbol->iconSize(), 0, nullptr, screen() );
btnChangeSymbol->setIcon( icon ); btnChangeSymbol->setIcon( icon );
editTitle->setText( ddsLegend ? ddsLegend->title() : QString() ); editTitle->setText( ddsLegend ? ddsLegend->title() : QString() );
@ -212,7 +212,7 @@ void QgsDataDefinedSizeLegendWidget::changeSymbol()
return; return;
mSourceSymbol = std::move( newSymbol ); mSourceSymbol = std::move( newSymbol );
const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSourceSymbol.get(), btnChangeSymbol->iconSize() ); const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( mSourceSymbol.get(), btnChangeSymbol->iconSize(), 0, nullptr, screen() );
btnChangeSymbol->setIcon( icon ); btnChangeSymbol->setIcon( icon );
emit widgetChanged(); emit widgetChanged();

View File

@ -61,8 +61,9 @@
///@cond PRIVATE ///@cond PRIVATE
QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent ) QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent, const QScreen *screen ) : QAbstractItemModel( parent )
, mMimeFormat( QStringLiteral( "application/x-qgsgraduatedsymbolrendererv2model" ) ) , mMimeFormat( QStringLiteral( "application/x-qgsgraduatedsymbolrendererv2model" ) )
, mScreen( screen )
{ {
} }
@ -178,7 +179,7 @@ QVariant QgsGraduatedSymbolRendererModel::data( const QModelIndex &index, int ro
else if ( role == Qt::DecorationRole && index.column() == 0 && range.symbol() ) else if ( role == Qt::DecorationRole && index.column() == 0 && range.symbol() )
{ {
const int iconSize = QgsGuiUtils::scaleIconSize( 16 ); const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
return QgsSymbolLayerUtils::symbolPreviewIcon( range.symbol(), QSize( iconSize, iconSize ) ); return QgsSymbolLayerUtils::symbolPreviewIcon( range.symbol(), QSize( iconSize, iconSize ), 0, nullptr, mScreen );
} }
else if ( role == Qt::TextAlignmentRole ) else if ( role == Qt::TextAlignmentRole )
{ {
@ -481,7 +482,7 @@ QgsGraduatedSymbolRendererWidget::QgsGraduatedSymbolRendererWidget( QgsVectorLay
connect( methodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged ); connect( methodComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged );
this->layout()->setContentsMargins( 0, 0, 0, 0 ); this->layout()->setContentsMargins( 0, 0, 0, 0 );
mModel = new QgsGraduatedSymbolRendererModel( this ); mModel = new QgsGraduatedSymbolRendererModel( this, screen() );
mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date ); mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date );
mExpressionWidget->setLayer( mLayer ); mExpressionWidget->setLayer( mLayer );

View File

@ -39,7 +39,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererModel : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT
public: public:
QgsGraduatedSymbolRendererModel( QObject *parent = nullptr ); QgsGraduatedSymbolRendererModel( QObject *parent = nullptr, const QScreen *screen = nullptr );
Qt::ItemFlags flags( const QModelIndex &index ) const override; Qt::ItemFlags flags( const QModelIndex &index ) const override;
Qt::DropActions supportedDropActions() const override; Qt::DropActions supportedDropActions() const override;
QVariant data( const QModelIndex &index, int role ) const override; QVariant data( const QModelIndex &index, int role ) const override;
@ -70,6 +70,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererModel : public QAbstractItemModel
private: private:
QgsGraduatedSymbolRenderer *mRenderer = nullptr; QgsGraduatedSymbolRenderer *mRenderer = nullptr;
QString mMimeFormat; QString mMimeFormat;
const QScreen *mScreen = nullptr;
}; };
// View style which shows drop indicator line between items // View style which shows drop indicator line between items

View File

@ -76,7 +76,7 @@ QgsRuleBasedRendererWidget::QgsRuleBasedRendererWidget( QgsVectorLayer *layer, Q
setupUi( this ); setupUi( this );
this->layout()->setContentsMargins( 0, 0, 0, 0 ); this->layout()->setContentsMargins( 0, 0, 0, 0 );
mModel = new QgsRuleBasedRendererModel( mRenderer.get(), viewRules ); mModel = new QgsRuleBasedRendererModel( mRenderer.get(), viewRules, screen() );
#ifdef ENABLE_MODELTEST #ifdef ENABLE_MODELTEST
new ModelTest( mModel, this ); // for model validity checking new ModelTest( mModel, this ); // for model validity checking
#endif #endif
@ -914,9 +914,10 @@ void QgsRendererRulePropsWidget::setDockMode( bool dockMode )
///// /////
QgsRuleBasedRendererModel::QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent ) QgsRuleBasedRendererModel::QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent, const QScreen *screen )
: QAbstractItemModel( parent ) : QAbstractItemModel( parent )
, mR( renderer ) , mR( renderer )
, mScreen( screen )
{ {
} }
@ -1002,7 +1003,7 @@ QVariant QgsRuleBasedRendererModel::data( const QModelIndex &index, int role ) c
else if ( role == Qt::DecorationRole && index.column() == 0 && rule->symbol() ) else if ( role == Qt::DecorationRole && index.column() == 0 && rule->symbol() )
{ {
const int iconSize = QgsGuiUtils::scaleIconSize( 16 ); const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
return QgsSymbolLayerUtils::symbolPreviewIcon( rule->symbol(), QSize( iconSize, iconSize ) ); return QgsSymbolLayerUtils::symbolPreviewIcon( rule->symbol(), QSize( iconSize, iconSize ), 0, nullptr, mScreen );
} }
else if ( role == Qt::TextAlignmentRole ) else if ( role == Qt::TextAlignmentRole )
{ {

View File

@ -53,7 +53,7 @@ class GUI_EXPORT QgsRuleBasedRendererModel : public QAbstractItemModel
/** /**
* Constructor for QgsRuleBasedRendererModel, for the specified \a renderer. * Constructor for QgsRuleBasedRendererModel, for the specified \a renderer.
*/ */
QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent ); QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent, const QScreen *screen = nullptr );
Qt::ItemFlags flags( const QModelIndex &index ) const override; Qt::ItemFlags flags( const QModelIndex &index ) const override;
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
@ -103,6 +103,7 @@ class GUI_EXPORT QgsRuleBasedRendererModel : public QAbstractItemModel
protected: protected:
QgsRuleBasedRenderer *mR = nullptr; QgsRuleBasedRenderer *mR = nullptr;
QHash<QgsRuleBasedRenderer::Rule *, QgsRuleBasedRendererCount> mFeatureCountMap; QHash<QgsRuleBasedRenderer::Rule *, QgsRuleBasedRendererCount> mFeatureCountMap;
const QScreen *mScreen = nullptr;
}; };

View File

@ -612,7 +612,7 @@ void QgsSimpleLineSymbolLayerWidget::updatePatternIcon()
//create an icon pixmap //create an icon pixmap
const std::unique_ptr< QgsLineSymbol > previewSymbol = std::make_unique< QgsLineSymbol >( QgsSymbolLayerList() << layerCopy.release() ); const std::unique_ptr< QgsLineSymbol > previewSymbol = std::make_unique< QgsLineSymbol >( QgsSymbolLayerList() << layerCopy.release() );
const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize ); const QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( previewSymbol.get(), currentIconSize, 0, nullptr, screen() );
mChangePatternButton->setIconSize( currentIconSize ); mChangePatternButton->setIconSize( currentIconSize );
mChangePatternButton->setIcon( icon ); mChangePatternButton->setIcon( icon );
@ -621,7 +621,7 @@ void QgsSimpleLineSymbolLayerWidget::updatePatternIcon()
const int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 ); const int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * fontMetrics().horizontalAdvance( 'X' ) * 23 );
const int height = static_cast< int >( width / 1.61803398875 ); // golden ratio const int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20 ); const QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( previewSymbol.get(), QSize( width, height ), height / 20, nullptr, false, nullptr, nullptr, screen() );
QByteArray data; QByteArray data;
QBuffer buffer( &data ); QBuffer buffer( &data );
pm.save( &buffer, "PNG", 100 ); pm.save( &buffer, "PNG", 100 );

View File

@ -60,7 +60,7 @@ QgsSymbolLevelsWidget::QgsSymbolLevelsWidget( const QgsLegendSymbolList &symbols
QgsSymbol *sym = mLegendSymbols.at( i ).symbol(); QgsSymbol *sym = mLegendSymbols.at( i ).symbol();
// set icons for the rows // set icons for the rows
QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( sym, QSize( iconSize, iconSize ) ); QIcon icon = QgsSymbolLayerUtils::symbolPreviewIcon( sym, QSize( iconSize, iconSize ), 0, nullptr, screen() );
tableLevels->setVerticalHeaderItem( i, new QTableWidgetItem( icon, QString() ) ); tableLevels->setVerticalHeaderItem( i, new QTableWidgetItem( icon, QString() ) );
// find out max. number of layers per symbol // find out max. number of layers per symbol

View File

@ -163,7 +163,7 @@ class SymbolLayerItem : public QStandardItem
{ {
QgsExpressionContext expContext; QgsExpressionContext expContext;
expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) ); expContext.appendScopes( QgsExpressionContextUtils::globalProjectLayerScopes( mVectorLayer ) );
icon = QIcon( QgsSymbolLayerUtils::symbolPreviewPixmap( mSymbol, mSize, 0, nullptr, false, &expContext, nullptr ) ); icon = QIcon( QgsSymbolLayerUtils::symbolPreviewPixmap( mSymbol, mSize, 0, nullptr, false, &expContext, nullptr, mScreen ) );
} }
setIcon( icon ); setIcon( icon );
@ -461,7 +461,7 @@ void QgsSymbolSelectorWidget::updatePreview()
return; return;
std::unique_ptr< QgsSymbol > symbolClone( mSymbol->clone() ); std::unique_ptr< QgsSymbol > symbolClone( mSymbol->clone() );
const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols ); const QImage preview = symbolClone->bigSymbolPreviewImage( &mPreviewExpressionContext, Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols, screen() );
lblPreview->setPixmap( QPixmap::fromImage( preview ) ); lblPreview->setPixmap( QPixmap::fromImage( preview ) );
// Hope this is a appropriate place // Hope this is a appropriate place
if ( !mBlockModified ) if ( !mBlockModified )

View File

@ -33,9 +33,10 @@
///@cond PRIVATE ///@cond PRIVATE
QgsVectorTileBasicRendererListModel::QgsVectorTileBasicRendererListModel( QgsVectorTileBasicRenderer *r, QObject *parent ) QgsVectorTileBasicRendererListModel::QgsVectorTileBasicRendererListModel( QgsVectorTileBasicRenderer *r, QObject *parent, const QScreen *screen )
: QAbstractListModel( parent ) : QAbstractListModel( parent )
, mRenderer( r ) , mRenderer( r )
, mScreen( screen )
{ {
} }
@ -100,7 +101,7 @@ QVariant QgsVectorTileBasicRendererListModel::data( const QModelIndex &index, in
if ( index.column() == 0 && style.symbol() ) if ( index.column() == 0 && style.symbol() )
{ {
const int iconSize = QgsGuiUtils::scaleIconSize( 16 ); const int iconSize = QgsGuiUtils::scaleIconSize( 16 );
return QgsSymbolLayerUtils::symbolPreviewIcon( style.symbol(), QSize( iconSize, iconSize ) ); return QgsSymbolLayerUtils::symbolPreviewIcon( style.symbol(), QSize( iconSize, iconSize ), 0, nullptr, mScreen );
} }
break; break;
} }
@ -395,7 +396,7 @@ void QgsVectorTileBasicRendererWidget::syncToLayer( QgsMapLayer *layer )
mRenderer.reset( new QgsVectorTileBasicRenderer() ); mRenderer.reset( new QgsVectorTileBasicRenderer() );
} }
mModel = new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles ); mModel = new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles, screen() );
mProxyModel = new QgsVectorTileBasicRendererProxyModel( mModel, viewStyles ); mProxyModel = new QgsVectorTileBasicRendererProxyModel( mModel, viewStyles );
viewStyles->setModel( mProxyModel ); viewStyles->setModel( mProxyModel );

View File

@ -88,7 +88,7 @@ class QgsVectorTileBasicRendererListModel : public QAbstractListModel
Filter Filter
}; };
QgsVectorTileBasicRendererListModel( QgsVectorTileBasicRenderer *r, QObject *parent = nullptr ); QgsVectorTileBasicRendererListModel( QgsVectorTileBasicRenderer *r, QObject *parent = nullptr, const QScreen *screen = nullptr );
int rowCount( const QModelIndex &parent = QModelIndex() ) const override; int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override; int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
@ -109,6 +109,7 @@ class QgsVectorTileBasicRendererListModel : public QAbstractListModel
private: private:
QgsVectorTileBasicRenderer *mRenderer = nullptr; QgsVectorTileBasicRenderer *mRenderer = nullptr;
const QScreen *mScreen = nullptr;
}; };
class QgsVectorTileBasicRendererProxyModel : public QSortFilterProxyModel class QgsVectorTileBasicRendererProxyModel : public QSortFilterProxyModel