From 064176690286938a6015ae409ae36419cb15abaf Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 21 Jun 2023 17:33:14 +1000 Subject: [PATCH] Fix incorrect sizing & pixelation of symbol previews on hidpi displays --- .../auto_generated/symbology/qgssymbol.sip.in | 13 ++++---- .../symbology/qgssymbollayerutils.sip.in | 31 ++++++------------- .../qgsrulebasedrendererwidget.sip.in | 2 +- src/core/symbology/qgssymbol.cpp | 25 ++++++++++++--- src/core/symbology/qgssymbol.h | 11 ++++--- src/core/symbology/qgssymbollayerutils.cpp | 16 ++++++---- src/core/symbology/qgssymbollayerutils.h | 19 ++++++------ src/gui/qgslegendpatchshapebutton.cpp | 2 +- src/gui/qgsmasksourceselectionwidget.cpp | 2 +- src/gui/qgssymbolbutton.cpp | 6 ++-- src/gui/qgssymbollayerselectionwidget.cpp | 2 +- .../qgscategorizedsymbolrendererwidget.cpp | 7 +++-- .../qgscategorizedsymbolrendererwidget.h | 3 +- .../qgsdatadefinedsizelegendwidget.cpp | 4 +-- .../qgsgraduatedsymbolrendererwidget.cpp | 7 +++-- .../qgsgraduatedsymbolrendererwidget.h | 3 +- .../symbology/qgsrulebasedrendererwidget.cpp | 7 +++-- .../symbology/qgsrulebasedrendererwidget.h | 3 +- src/gui/symbology/qgssymbollayerwidget.cpp | 4 +-- src/gui/symbology/qgssymbollevelsdialog.cpp | 2 +- src/gui/symbology/qgssymbolselectordialog.cpp | 4 +-- .../qgsvectortilebasicrendererwidget.cpp | 7 +++-- .../qgsvectortilebasicrendererwidget.h | 3 +- 23 files changed, 99 insertions(+), 84 deletions(-) diff --git a/python/core/auto_generated/symbology/qgssymbol.sip.in b/python/core/auto_generated/symbology/qgssymbol.sip.in index 95cdf1c9263..6a7f44c3a0e 100644 --- a/python/core/auto_generated/symbology/qgssymbol.sip.in +++ b/python/core/auto_generated/symbology/qgssymbol.sip.in @@ -9,6 +9,7 @@ + typedef QList QgsSymbolLayerList; class QgsSymbolAnimationSettings @@ -334,7 +335,7 @@ layer. %End 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 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 size: size of the icon :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 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:`asImage` -.. note:: - - Parameter selected added in QGIS 3.10 - .. versionadded:: 2.6 %End @@ -383,13 +381,14 @@ matches the settings from that context. .. seealso:: :py:func:`drawPreviewIcon` %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 Returns a large (roughly 100x100 pixel) preview image for the symbol. :param expressionContext: optional expression context, for evaluation of data defined symbol properties :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` diff --git a/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in b/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in index 4e31f977b15..0576f0ff409 100644 --- a/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in +++ b/python/core/auto_generated/symbology/qgssymbollayerutils.sip.in @@ -276,7 +276,7 @@ Decodes a symbol scale method from a string. 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 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 padding: space between icon edge and symbol :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` %End static QPixmap symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding = 0, QgsRenderContext *customContext = 0, bool selected = false, const QgsExpressionContext *expressionContext = 0, - const QgsLegendPatchShape *shape = 0 ); + const QgsLegendPatchShape *shape = 0, + const QScreen *screen = 0 ); %Docstring Returns a pixmap preview for a color ramp. :param symbol: symbol :param size: target pixmap size :param padding: space between icon edge and symbol -:param customContext: render context to use when rendering symbol -:param selected: set to ``True`` to render the symbol in a selected state -:param expressionContext: optional custom expression context -:param shape: optional legend patch shape to use for rendering the preview icon - -.. 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 +: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 (since QGIS 3.10) +:param expressionContext: optional custom expression context (since QGIS 3.10) +: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) .. seealso:: :py:func:`symbolPreviewIcon` %End diff --git a/python/gui/auto_generated/symbology/qgsrulebasedrendererwidget.sip.in b/python/gui/auto_generated/symbology/qgsrulebasedrendererwidget.sip.in index 8a9b518c67d..a753eb3a0e5 100644 --- a/python/gui/auto_generated/symbology/qgsrulebasedrendererwidget.sip.in +++ b/python/gui/auto_generated/symbology/qgsrulebasedrendererwidget.sip.in @@ -27,7 +27,7 @@ Tree model for the rules: %End public: - QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent ); + QgsRuleBasedRendererModel( QgsRuleBasedRenderer *renderer, QObject *parent, const QScreen *screen = 0 ); %Docstring Constructor for QgsRuleBasedRendererModel, for the specified ``renderer``. %End diff --git a/src/core/symbology/qgssymbol.cpp b/src/core/symbology/qgssymbol.cpp index 56858cc36ff..03b55deb872 100644 --- a/src/core/symbology/qgssymbol.cpp +++ b/src/core/symbology/qgssymbol.cpp @@ -923,7 +923,7 @@ QColor QgsSymbol::color() const 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; std::unique_ptr< QgsRenderContext > tempContext; @@ -934,6 +934,12 @@ void QgsSymbol::drawPreviewIcon( QPainter *painter, QSize size, QgsRenderContext context->setFlag( Qgis::RenderContextFlag::RenderSymbolPreview, true ); } + if ( screen ) + { + context->setScaleFactor( screen->physicalDotsPerInch() / 25.4 ); + context->setDevicePixelRatio( screen->devicePixelRatio() ); + } + const bool prevForceVector = context->forceVectorOutput(); 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.setDevicePixelRatio( devicePixelRatio ); QPainter p( &preview ); p.setRenderHint( QPainter::Antialiasing ); @@ -1067,8 +1075,8 @@ QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext if ( mType == Qgis::SymbolType::Marker && flags & Qgis::SymbolPreviewFlag::FlagIncludeCrosshairsForMarkerSymbols ) { p.setPen( QPen( Qt::gray ) ); - p.drawLine( 0, 50, 100, 50 ); - p.drawLine( 50, 0, 50, 100 ); + p.drawLine( QLineF( 0, 50, 100, 50 ) ); + p.drawLine( QLineF( 50, 0, 50, 100 ) ); } QgsRenderContext context = QgsRenderContext::fromQPainter( &p ); @@ -1076,6 +1084,13 @@ QImage QgsSymbol::bigSymbolPreviewImage( QgsExpressionContext *expressionContext context.setFlag( Qgis::RenderContextFlag::Antialiasing ); context.setFlag( Qgis::RenderContextFlag::HighQualityImageTransforms ); context.setPainterFlagsUsingContext( &p ); + context.setDevicePixelRatio( devicePixelRatio ); + + if ( screen ) + { + context.setScaleFactor( screen->physicalDotsPerInch() / 25.4 ); + } + if ( expressionContext ) context.setExpressionContext( *expressionContext ); diff --git a/src/core/symbology/qgssymbol.h b/src/core/symbology/qgssymbol.h index 602c575b334..f6f9a9b0a4a 100644 --- a/src/core/symbology/qgssymbol.h +++ b/src/core/symbology/qgssymbol.h @@ -26,6 +26,8 @@ class QgsLegendPatchShape; class QgsSymbolRenderContext; class QgsLineSymbolLayer; +class QScreen; + typedef QList QgsSymbolLayerList; /** @@ -371,17 +373,17 @@ class CORE_EXPORT QgsSymbol * \param painter destination painter * \param size size of the icon * \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 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 asImage() - * \note Parameter selected added in QGIS 3.10 * \since QGIS 2.6 */ 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. @@ -411,11 +413,12 @@ class CORE_EXPORT QgsSymbol * \param expressionContext optional expression context, for evaluation of * data defined symbol properties * \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 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. diff --git a/src/core/symbology/qgssymbollayerutils.cpp b/src/core/symbology/qgssymbollayerutils.cpp index 1e78fef7c8e..975c254fe4d 100644 --- a/src/core/symbology/qgssymbollayerutils.cpp +++ b/src/core/symbology/qgssymbollayerutils.cpp @@ -868,15 +868,19 @@ QPainter::CompositionMode QgsSymbolLayerUtils::decodeBlendMode( const QString &s 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 ); - 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 ); @@ -919,12 +923,12 @@ QPixmap QgsSymbolLayerUtils::symbolPreviewPixmap( const QgsSymbol *symbol, QSize prop.setActive( false ); } } - symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape ); + symbol_noDD->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen ); } else { std::unique_ptr symbolClone( symbol->clone( ) ); - symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape ); + symbolClone->drawPreviewIcon( &painter, size, customContext, selected, expressionContext, shape, screen ); } painter.end(); diff --git a/src/core/symbology/qgssymbollayerutils.h b/src/core/symbology/qgssymbollayerutils.h index 4c5818af361..d7ca5cc6595 100644 --- a/src/core/symbology/qgssymbollayerutils.h +++ b/src/core/symbology/qgssymbollayerutils.h @@ -281,28 +281,27 @@ class CORE_EXPORT QgsSymbolLayerUtils * \param size target pixmap size * \param padding space between icon edge and symbol * \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() */ - 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. * \param symbol symbol * \param size target pixmap size * \param padding space between icon edge and symbol - * \param customContext render context to use when rendering symbol - * \param selected set to TRUE to render the symbol in a selected state - * \param expressionContext optional custom expression context - * \param shape optional legend patch shape to use for rendering the preview icon - * \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 + * \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 (since QGIS 3.10) + * \param expressionContext optional custom expression context (since QGIS 3.10) + * \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) * \see symbolPreviewIcon() */ static QPixmap symbolPreviewPixmap( const QgsSymbol *symbol, QSize size, int padding = 0, QgsRenderContext *customContext = nullptr, bool selected = false, const QgsExpressionContext *expressionContext = nullptr, - const QgsLegendPatchShape *shape = nullptr ); + const QgsLegendPatchShape *shape = nullptr, + const QScreen *screen = nullptr ); /** * Draws a symbol layer preview to a QPicture diff --git a/src/gui/qgslegendpatchshapebutton.cpp b/src/gui/qgslegendpatchshapebutton.cpp index 68636539ad7..6370d78bc8c 100644 --- a/src/gui/qgslegendpatchshapebutton.cpp +++ b/src/gui/qgslegendpatchshapebutton.cpp @@ -287,7 +287,7 @@ void QgsLegendPatchShapeButton::updatePreview() } //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 ); setIcon( icon ); diff --git a/src/gui/qgsmasksourceselectionwidget.cpp b/src/gui/qgsmasksourceselectionwidget.cpp index a9e6d30de76..f3e61865435 100644 --- a/src/gui/qgsmasksourceselectionwidget.cpp +++ b/src/gui/qgsmasksourceselectionwidget.cpp @@ -125,7 +125,7 @@ void QgsMaskSourceSelectionWidget::update() return true; 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 ); if ( visitSymbol( symbolItem.get(), leaf.identifier, symbol, {} ) ) diff --git a/src/gui/qgssymbolbutton.cpp b/src/gui/qgssymbolbutton.cpp index a946e4586ad..5d988c19b82 100644 --- a/src/gui/qgssymbolbutton.cpp +++ b/src/gui/qgssymbolbutton.cpp @@ -507,7 +507,7 @@ void QgsSymbolButton::prepareMenu() std::unique_ptr< QgsSymbol > tempSymbol( QgsSymbolLayerUtils::symbolFromMimeData( QApplication::clipboard()->mimeData() ) ); 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 { @@ -528,7 +528,7 @@ void QgsSymbolButton::prepareMenu() if ( mDefaultSymbol ) { 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 ); connect( defaultSymbolAction, &QAction::triggered, this, &QgsSymbolButton::setToDefaultSymbol ); } @@ -703,7 +703,7 @@ void QgsSymbolButton::updatePreview( const QColor &color, QgsSymbol *tempSymbol previewSymbol->setColor( color ); //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 ); setIcon( icon ); diff --git a/src/gui/qgssymbollayerselectionwidget.cpp b/src/gui/qgssymbollayerselectionwidget.cpp index b57c84012da..5f09c61c3b2 100644 --- a/src/gui/qgssymbollayerselectionwidget.cpp +++ b/src/gui/qgssymbollayerselectionwidget.cpp @@ -119,7 +119,7 @@ void QgsSymbolLayerSelectionWidget::setLayer( const QgsVectorLayer *layer ) // either leaf.description or mCurrentDescription is defined 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->setIcon( 0, icon ); mLayerItem->addChild( symbolItem ); diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp index 21359bcb579..b2a8a90b190 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.cpp @@ -51,8 +51,9 @@ ///@cond PRIVATE -QgsCategorizedSymbolRendererModel::QgsCategorizedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent ) +QgsCategorizedSymbolRendererModel::QgsCategorizedSymbolRendererModel( QObject *parent, const QScreen *screen ) : QAbstractItemModel( parent ) , mMimeFormat( QStringLiteral( "application/x-qgscategorizedsymbolrendererv2model" ) ) + , mScreen( screen ) { } @@ -197,7 +198,7 @@ QVariant QgsCategorizedSymbolRendererModel::data( const QModelIndex &index, int if ( index.column() == 0 && category.symbol() ) { 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; } @@ -669,7 +670,7 @@ QgsCategorizedSymbolRendererWidget::QgsCategorizedSymbolRendererWidget( QgsVecto btnChangeCategorizedSymbol->setSymbol( mCategorizedSymbol->clone() ); } - mModel = new QgsCategorizedSymbolRendererModel( this ); + mModel = new QgsCategorizedSymbolRendererModel( this, screen() ); mModel->setRenderer( mRenderer.get() ); // update GUI from renderer diff --git a/src/gui/symbology/qgscategorizedsymbolrendererwidget.h b/src/gui/symbology/qgscategorizedsymbolrendererwidget.h index 21b49cd85ed..4a7a368166b 100644 --- a/src/gui/symbology/qgscategorizedsymbolrendererwidget.h +++ b/src/gui/symbology/qgscategorizedsymbolrendererwidget.h @@ -37,7 +37,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererModel : public QAbstractItemModel { Q_OBJECT public: - QgsCategorizedSymbolRendererModel( QObject *parent = nullptr ); + QgsCategorizedSymbolRendererModel( QObject *parent = nullptr, const QScreen *screen = nullptr ); Qt::ItemFlags flags( const QModelIndex &index ) const override; Qt::DropActions supportedDropActions() const override; QVariant data( const QModelIndex &index, int role ) const override; @@ -66,6 +66,7 @@ class GUI_EXPORT QgsCategorizedSymbolRendererModel : public QAbstractItemModel private: QgsCategorizedSymbolRenderer *mRenderer = nullptr; QString mMimeFormat; + const QScreen *mScreen = nullptr; }; /** diff --git a/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp b/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp index 56e8ab06d43..cd124a1a6ab 100644 --- a/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp +++ b/src/gui/symbology/qgsdatadefinedsizelegendwidget.cpp @@ -82,7 +82,7 @@ QgsDataDefinedSizeLegendWidget::QgsDataDefinedSizeLegendWidget( const QgsDataDef 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 ); editTitle->setText( ddsLegend ? ddsLegend->title() : QString() ); @@ -212,7 +212,7 @@ void QgsDataDefinedSizeLegendWidget::changeSymbol() return; 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 ); emit widgetChanged(); diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp index 93bdf380c15..390275477c0 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.cpp @@ -61,8 +61,9 @@ ///@cond PRIVATE -QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent ) : QAbstractItemModel( parent ) +QgsGraduatedSymbolRendererModel::QgsGraduatedSymbolRendererModel( QObject *parent, const QScreen *screen ) : QAbstractItemModel( parent ) , 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() ) { 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 ) { @@ -481,7 +482,7 @@ QgsGraduatedSymbolRendererWidget::QgsGraduatedSymbolRendererWidget( QgsVectorLay connect( methodComboBox, static_cast( &QComboBox::currentIndexChanged ), this, &QgsGraduatedSymbolRendererWidget::methodComboBox_currentIndexChanged ); this->layout()->setContentsMargins( 0, 0, 0, 0 ); - mModel = new QgsGraduatedSymbolRendererModel( this ); + mModel = new QgsGraduatedSymbolRendererModel( this, screen() ); mExpressionWidget->setFilters( QgsFieldProxyModel::Numeric | QgsFieldProxyModel::Date ); mExpressionWidget->setLayer( mLayer ); diff --git a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.h b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.h index c1ee8b48d60..60a420a184a 100644 --- a/src/gui/symbology/qgsgraduatedsymbolrendererwidget.h +++ b/src/gui/symbology/qgsgraduatedsymbolrendererwidget.h @@ -39,7 +39,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererModel : public QAbstractItemModel { Q_OBJECT public: - QgsGraduatedSymbolRendererModel( QObject *parent = nullptr ); + QgsGraduatedSymbolRendererModel( QObject *parent = nullptr, const QScreen *screen = nullptr ); Qt::ItemFlags flags( const QModelIndex &index ) const override; Qt::DropActions supportedDropActions() const override; QVariant data( const QModelIndex &index, int role ) const override; @@ -70,6 +70,7 @@ class GUI_EXPORT QgsGraduatedSymbolRendererModel : public QAbstractItemModel private: QgsGraduatedSymbolRenderer *mRenderer = nullptr; QString mMimeFormat; + const QScreen *mScreen = nullptr; }; // View style which shows drop indicator line between items diff --git a/src/gui/symbology/qgsrulebasedrendererwidget.cpp b/src/gui/symbology/qgsrulebasedrendererwidget.cpp index a854f8b310b..c2585dac904 100644 --- a/src/gui/symbology/qgsrulebasedrendererwidget.cpp +++ b/src/gui/symbology/qgsrulebasedrendererwidget.cpp @@ -76,7 +76,7 @@ QgsRuleBasedRendererWidget::QgsRuleBasedRendererWidget( QgsVectorLayer *layer, Q setupUi( this ); this->layout()->setContentsMargins( 0, 0, 0, 0 ); - mModel = new QgsRuleBasedRendererModel( mRenderer.get(), viewRules ); + mModel = new QgsRuleBasedRendererModel( mRenderer.get(), viewRules, screen() ); #ifdef ENABLE_MODELTEST new ModelTest( mModel, this ); // for model validity checking #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 ) , 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() ) { 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 ) { diff --git a/src/gui/symbology/qgsrulebasedrendererwidget.h b/src/gui/symbology/qgsrulebasedrendererwidget.h index 18713bf7bed..9318fe9d9d6 100644 --- a/src/gui/symbology/qgsrulebasedrendererwidget.h +++ b/src/gui/symbology/qgsrulebasedrendererwidget.h @@ -53,7 +53,7 @@ class GUI_EXPORT QgsRuleBasedRendererModel : public QAbstractItemModel /** * 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; QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override; @@ -103,6 +103,7 @@ class GUI_EXPORT QgsRuleBasedRendererModel : public QAbstractItemModel protected: QgsRuleBasedRenderer *mR = nullptr; QHash mFeatureCountMap; + const QScreen *mScreen = nullptr; }; diff --git a/src/gui/symbology/qgssymbollayerwidget.cpp b/src/gui/symbology/qgssymbollayerwidget.cpp index dbc4887a850..f73027a4de7 100644 --- a/src/gui/symbology/qgssymbollayerwidget.cpp +++ b/src/gui/symbology/qgssymbollayerwidget.cpp @@ -612,7 +612,7 @@ void QgsSimpleLineSymbolLayerWidget::updatePatternIcon() //create an icon pixmap 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->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 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; QBuffer buffer( &data ); pm.save( &buffer, "PNG", 100 ); diff --git a/src/gui/symbology/qgssymbollevelsdialog.cpp b/src/gui/symbology/qgssymbollevelsdialog.cpp index 333c2de5442..8083145e521 100644 --- a/src/gui/symbology/qgssymbollevelsdialog.cpp +++ b/src/gui/symbology/qgssymbollevelsdialog.cpp @@ -60,7 +60,7 @@ QgsSymbolLevelsWidget::QgsSymbolLevelsWidget( const QgsLegendSymbolList &symbols QgsSymbol *sym = mLegendSymbols.at( i ).symbol(); // 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() ) ); // find out max. number of layers per symbol diff --git a/src/gui/symbology/qgssymbolselectordialog.cpp b/src/gui/symbology/qgssymbolselectordialog.cpp index 855612757ff..c0654e8e626 100644 --- a/src/gui/symbology/qgssymbolselectordialog.cpp +++ b/src/gui/symbology/qgssymbolselectordialog.cpp @@ -163,7 +163,7 @@ class SymbolLayerItem : public QStandardItem { QgsExpressionContext expContext; 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 ); @@ -461,7 +461,7 @@ void QgsSymbolSelectorWidget::updatePreview() return; 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 ) ); // Hope this is a appropriate place if ( !mBlockModified ) diff --git a/src/gui/vectortile/qgsvectortilebasicrendererwidget.cpp b/src/gui/vectortile/qgsvectortilebasicrendererwidget.cpp index 9f471aa6bd0..a59783c36bf 100644 --- a/src/gui/vectortile/qgsvectortilebasicrendererwidget.cpp +++ b/src/gui/vectortile/qgsvectortilebasicrendererwidget.cpp @@ -33,9 +33,10 @@ ///@cond PRIVATE -QgsVectorTileBasicRendererListModel::QgsVectorTileBasicRendererListModel( QgsVectorTileBasicRenderer *r, QObject *parent ) +QgsVectorTileBasicRendererListModel::QgsVectorTileBasicRendererListModel( QgsVectorTileBasicRenderer *r, QObject *parent, const QScreen *screen ) : QAbstractListModel( parent ) , mRenderer( r ) + , mScreen( screen ) { } @@ -100,7 +101,7 @@ QVariant QgsVectorTileBasicRendererListModel::data( const QModelIndex &index, in if ( index.column() == 0 && style.symbol() ) { 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; } @@ -395,7 +396,7 @@ void QgsVectorTileBasicRendererWidget::syncToLayer( QgsMapLayer *layer ) mRenderer.reset( new QgsVectorTileBasicRenderer() ); } - mModel = new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles ); + mModel = new QgsVectorTileBasicRendererListModel( mRenderer.get(), viewStyles, screen() ); mProxyModel = new QgsVectorTileBasicRendererProxyModel( mModel, viewStyles ); viewStyles->setModel( mProxyModel ); diff --git a/src/gui/vectortile/qgsvectortilebasicrendererwidget.h b/src/gui/vectortile/qgsvectortilebasicrendererwidget.h index 41136bf8156..6ea6875ab1e 100644 --- a/src/gui/vectortile/qgsvectortilebasicrendererwidget.h +++ b/src/gui/vectortile/qgsvectortilebasicrendererwidget.h @@ -88,7 +88,7 @@ class QgsVectorTileBasicRendererListModel : public QAbstractListModel 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 columnCount( const QModelIndex &parent = QModelIndex() ) const override; @@ -109,6 +109,7 @@ class QgsVectorTileBasicRendererListModel : public QAbstractListModel private: QgsVectorTileBasicRenderer *mRenderer = nullptr; + const QScreen *mScreen = nullptr; }; class QgsVectorTileBasicRendererProxyModel : public QSortFilterProxyModel