mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
Fix pixelated icons in style lists on hi dpi displays
Use QgsScreenProperties in style model to ensure we correctly generate preview icons matching the device pixel ratio and DPI of all attached displays
This commit is contained in:
parent
b5e3af7a3a
commit
ff7a5c934c
@ -636,7 +636,7 @@ Sets the label placement ``settings``.
|
||||
.. versionadded:: 3.26
|
||||
%End
|
||||
|
||||
static QPixmap labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText = QString(), int padding = 0, double devicePixelRatio = 1 );
|
||||
static QPixmap labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText = QString(), int padding = 0, const QgsScreenProperties &screen = QgsScreenProperties() );
|
||||
%Docstring
|
||||
Returns a pixmap preview for label ``settings``.
|
||||
|
||||
@ -644,7 +644,7 @@ Returns a pixmap preview for label ``settings``.
|
||||
:param size: target pixmap size
|
||||
:param previewText: text to render in preview, or empty for default text
|
||||
:param padding: space between icon edge and color ramp
|
||||
:param devicePixelRatio: can be used to generate a pixmap using a specific device pixel ratio (since QGIS 3.32)
|
||||
:param screen: can be used to specify the destination screen properties 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)
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
@ -35,6 +35,10 @@ Constructor for QgsScreenProperties, copying
|
||||
properties from the specified ``screen``.
|
||||
%End
|
||||
|
||||
bool operator==( const QgsScreenProperties &other ) const;
|
||||
|
||||
bool operator!=( const QgsScreenProperties &other ) const;
|
||||
|
||||
bool isValid() const;
|
||||
%Docstring
|
||||
Returns ``True`` if the properties are valid.
|
||||
@ -70,6 +74,7 @@ to match the screen settings.
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsCombinedStyleModel: QConcatenateTablesProxyModel
|
||||
{
|
||||
%Docstring(signature="appended")
|
||||
@ -79,12 +77,12 @@ This allows style icons to be generated at an icon size which
|
||||
corresponds exactly to the view's icon size in which this model is used.
|
||||
%End
|
||||
|
||||
void addDesiredIconDevicePixelRatio( double ratio );
|
||||
void addTargetScreenProperties( const QgsScreenProperties &properties );
|
||||
%Docstring
|
||||
Adds an additional icon device pixel ``ratio`` to generate for Qt.DecorationRole data.
|
||||
Adds additional target screen ``properties`` to use when generating icons for Qt.DecorationRole data.
|
||||
|
||||
This allows style icons to be generated at an icon device pixel ratio which
|
||||
corresponds exactly to the view's icon size in which this model is used.
|
||||
This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
corresponds exactly to the view's screen properties in which this model is used.
|
||||
|
||||
.. versionadded:: 3.32
|
||||
%End
|
||||
|
@ -90,12 +90,12 @@ This allows style icons to be generated at an icon size which
|
||||
corresponds exactly to the view's icon size in which this model is used.
|
||||
%End
|
||||
|
||||
void addDesiredIconDevicePixelRatio( double ratio );
|
||||
void addTargetScreenProperties( const QgsScreenProperties &properties );
|
||||
%Docstring
|
||||
Adds an additional icon device pixel ``ratio`` to generate for Qt.DecorationRole data.
|
||||
Adds additional target screen ``properties`` to use when generating icons for Qt.DecorationRole data.
|
||||
|
||||
This allows style icons to be generated at an icon device pixel ratio which
|
||||
corresponds exactly to the view's icon size in which this model is used.
|
||||
This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
corresponds exactly to the view's screen properties in which this model is used.
|
||||
|
||||
.. versionadded:: 3.32
|
||||
%End
|
||||
@ -364,12 +364,12 @@ This allows style icons to be generated at an icon size which
|
||||
corresponds exactly to the view's icon size in which this model is used.
|
||||
%End
|
||||
|
||||
void addDesiredIconDevicePixelRatio( double ratio );
|
||||
void addTargetScreenProperties( const QgsScreenProperties &properties );
|
||||
%Docstring
|
||||
Adds an additional icon device pixel ``ratio`` to generate for Qt.DecorationRole data.
|
||||
Adds additional target screen ``properties`` to use when generating icons for Qt.DecorationRole data.
|
||||
|
||||
This allows style icons to be generated at an icon device pixel ratio which
|
||||
corresponds exactly to the view's icon size in which this model is used.
|
||||
This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
corresponds exactly to the view's screen properties in which this model is used.
|
||||
|
||||
.. versionadded:: 3.32
|
||||
%End
|
||||
|
@ -718,7 +718,7 @@ Updates the format by evaluating current values of data defined properties.
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
static QPixmap textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText = QString(), int padding = 0, double devicePixelRatio = 1 );
|
||||
static QPixmap textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText = QString(), int padding = 0, const QgsScreenProperties &screen = QgsScreenProperties() );
|
||||
%Docstring
|
||||
Returns a pixmap preview for a text ``format``.
|
||||
|
||||
@ -726,7 +726,7 @@ Returns a pixmap preview for a text ``format``.
|
||||
:param size: target pixmap size
|
||||
:param previewText: text to render in preview, or empty for default text
|
||||
:param padding: space between icon edge and color ramp
|
||||
:param devicePixelRatio: can be used to generate a pixmap using a specific device pixel ratio (since QGIS 3.32)
|
||||
:param screen: can be used to specify the destination screen properties 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)
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
@ -1357,8 +1357,10 @@ void QgsPalLayerSettings::setCallout( QgsCallout *callout )
|
||||
mCallout.reset( callout );
|
||||
}
|
||||
|
||||
QPixmap QgsPalLayerSettings::labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText, int padding, double devicePixelRatio )
|
||||
QPixmap QgsPalLayerSettings::labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText, int padding, const QgsScreenProperties &screen )
|
||||
{
|
||||
const double devicePixelRatio = screen.isValid() ? screen.devicePixelRatio() : 1;
|
||||
|
||||
// for now, just use format
|
||||
QgsTextFormat tempFormat = settings.format();
|
||||
QPixmap pixmap( size * devicePixelRatio );
|
||||
@ -1406,10 +1408,24 @@ QPixmap QgsPalLayerSettings::labelSettingsPreviewPixmap( const QgsPalLayerSettin
|
||||
context.setMapToPixel( newCoordXForm );
|
||||
context.setFlag( Qgis::RenderContextFlag::Antialiasing, true );
|
||||
|
||||
QWidget *activeWindow = QApplication::activeWindow();
|
||||
const double physicalDpiX = activeWindow && activeWindow->screen() ? activeWindow->screen()->physicalDotsPerInchX() : 96.0;
|
||||
context.setScaleFactor( physicalDpiX / 25.4 );
|
||||
context.setDevicePixelRatio( devicePixelRatio );
|
||||
if ( screen.isValid() )
|
||||
{
|
||||
screen.updateRenderContextForScreen( context );
|
||||
}
|
||||
else
|
||||
{
|
||||
QWidget *activeWindow = QApplication::activeWindow();
|
||||
if ( QScreen *screen = activeWindow ? activeWindow->screen() : nullptr )
|
||||
{
|
||||
context.setScaleFactor( screen->physicalDotsPerInch() / 25.4 );
|
||||
context.setDevicePixelRatio( screen->devicePixelRatio() );
|
||||
}
|
||||
else
|
||||
{
|
||||
context.setScaleFactor( 96.0 / 25.4 );
|
||||
context.setDevicePixelRatio( 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
context.setUseAdvancedEffects( true );
|
||||
context.setPainter( &painter );
|
||||
|
@ -968,10 +968,10 @@ class CORE_EXPORT QgsPalLayerSettings
|
||||
* \param size target pixmap size
|
||||
* \param previewText text to render in preview, or empty for default text
|
||||
* \param padding space between icon edge and color ramp
|
||||
* \param devicePixelRatio can be used to generate a pixmap using a specific device pixel ratio (since QGIS 3.32)
|
||||
* \param screen can be used to specify the destination screen properties 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)
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
static QPixmap labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText = QString(), int padding = 0, double devicePixelRatio = 1 );
|
||||
static QPixmap labelSettingsPreviewPixmap( const QgsPalLayerSettings &settings, QSize size, const QString &previewText = QString(), int padding = 0, const QgsScreenProperties &screen = QgsScreenProperties() );
|
||||
|
||||
/**
|
||||
* Returns the layer's unplaced label visibility.
|
||||
|
@ -16,6 +16,8 @@
|
||||
#define QGSSCREENPROPERTIES_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include "qgis.h"
|
||||
|
||||
class QScreen;
|
||||
class QgsRenderContext;
|
||||
@ -46,6 +48,18 @@ class CORE_EXPORT QgsScreenProperties
|
||||
*/
|
||||
explicit QgsScreenProperties( const QScreen *screen );
|
||||
|
||||
bool operator==( const QgsScreenProperties &other ) const
|
||||
{
|
||||
return mValid == other.mValid
|
||||
&& mDevicePixelRatio == other.mDevicePixelRatio
|
||||
&& mPhysicalDpi == other.mPhysicalDpi;
|
||||
}
|
||||
|
||||
bool operator!=( const QgsScreenProperties &other ) const
|
||||
{
|
||||
return !( *this == other );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the properties are valid.
|
||||
*/
|
||||
@ -84,4 +98,14 @@ class CORE_EXPORT QgsScreenProperties
|
||||
double mPhysicalDpi = 96;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a hash for a screen \a properties.
|
||||
*
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
CORE_EXPORT inline uint qHash( const QgsScreenProperties &properties ) SIP_SKIP
|
||||
{
|
||||
return qHash( properties.devicePixelRatio() ) + qHash( properties.physicalDpi() );
|
||||
}
|
||||
|
||||
#endif // QGSSCREENPROPERTIES_H
|
||||
|
@ -76,9 +76,9 @@ void QgsCombinedStyleModel::addStyle( QgsStyle *style )
|
||||
styleModel->addDesiredIconSize( size );
|
||||
}
|
||||
|
||||
for ( double ratio : std::as_const( mDevicePixelRatios ) )
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
styleModel->addDesiredIconDevicePixelRatio( ratio );
|
||||
styleModel->addTargetScreenProperties( *it );
|
||||
}
|
||||
|
||||
addSourceModel( styleModel );
|
||||
@ -135,9 +135,9 @@ void QgsCombinedStyleModel::addDefaultStyle()
|
||||
styleModel->addDesiredIconSize( size );
|
||||
}
|
||||
|
||||
for ( double ratio : std::as_const( mDevicePixelRatios ) )
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
styleModel->addDesiredIconDevicePixelRatio( ratio );
|
||||
styleModel->addTargetScreenProperties( *it );
|
||||
}
|
||||
|
||||
addSourceModel( styleModel );
|
||||
@ -164,18 +164,18 @@ void QgsCombinedStyleModel::addDesiredIconSize( QSize size )
|
||||
}
|
||||
}
|
||||
|
||||
void QgsCombinedStyleModel::addDesiredIconDevicePixelRatio( double ratio )
|
||||
void QgsCombinedStyleModel::addTargetScreenProperties( const QgsScreenProperties &properties )
|
||||
{
|
||||
if ( !mDevicePixelRatios.contains( ratio ) )
|
||||
mDevicePixelRatios.append( ratio );
|
||||
if ( !mTargetScreenProperties.contains( properties ) )
|
||||
mTargetScreenProperties.insert( properties );
|
||||
|
||||
for ( auto it = mOwnedStyleModels.constBegin(); it != mOwnedStyleModels.constEnd(); ++it )
|
||||
{
|
||||
it.value()->addDesiredIconDevicePixelRatio( ratio );
|
||||
it.value()->addTargetScreenProperties( properties );
|
||||
}
|
||||
|
||||
if ( mStyles.contains( QgsStyle::defaultStyle() ) )
|
||||
{
|
||||
QgsApplication::defaultStyleModel()->addDesiredIconDevicePixelRatio( ratio );
|
||||
QgsApplication::defaultStyleModel()->addTargetScreenProperties( properties );
|
||||
}
|
||||
}
|
||||
|
@ -19,13 +19,13 @@
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <QSet>
|
||||
#include <QConcatenateTablesProxyModel>
|
||||
|
||||
class QgsStyle;
|
||||
class QgsStyleModel;
|
||||
class QgsSingleItemModel;
|
||||
|
||||
class QgsScreenProperties;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
@ -92,14 +92,14 @@ class CORE_EXPORT QgsCombinedStyleModel: public QConcatenateTablesProxyModel
|
||||
void addDesiredIconSize( QSize size );
|
||||
|
||||
/**
|
||||
* Adds an additional icon device pixel \a ratio to generate for Qt::DecorationRole data.
|
||||
* Adds additional target screen \a properties to use when generating icons for Qt::DecorationRole data.
|
||||
*
|
||||
* This allows style icons to be generated at an icon device pixel ratio which
|
||||
* corresponds exactly to the view's icon size in which this model is used.
|
||||
* This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
* corresponds exactly to the view's screen properties in which this model is used.
|
||||
*
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
void addDesiredIconDevicePixelRatio( double ratio );
|
||||
void addTargetScreenProperties( const QgsScreenProperties &properties );
|
||||
|
||||
private:
|
||||
|
||||
@ -108,7 +108,7 @@ class CORE_EXPORT QgsCombinedStyleModel: public QConcatenateTablesProxyModel
|
||||
QHash< QgsStyle *, QgsSingleItemModel * > mTitleModels;
|
||||
|
||||
QList< QSize > mAdditionalSizes;
|
||||
QList< double > mDevicePixelRatios;
|
||||
QSet< QgsScreenProperties > mTargetScreenProperties;
|
||||
|
||||
};
|
||||
|
||||
|
@ -39,13 +39,6 @@ QgsAbstractStyleEntityIconGenerator *QgsStyleModel::sIconGenerator = nullptr;
|
||||
QgsAbstractStyleEntityIconGenerator::QgsAbstractStyleEntityIconGenerator( QObject *parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
// Default to generating icons using the application devicePixelRatio.
|
||||
// Additional ratios may be added by individual views to this model (eg on
|
||||
// different screens with different pixel ratios)
|
||||
if ( QGuiApplication *guiApplication = qobject_cast< QGuiApplication * >( QApplication::instance() ) )
|
||||
mDevicePixelRatios.append( guiApplication->devicePixelRatio() );
|
||||
else
|
||||
mDevicePixelRatios.append( 1.0 );
|
||||
}
|
||||
|
||||
void QgsAbstractStyleEntityIconGenerator::setIconSizes( const QList<QSize> &sizes )
|
||||
@ -58,14 +51,14 @@ QList<QSize> QgsAbstractStyleEntityIconGenerator::iconSizes() const
|
||||
return mIconSizes;
|
||||
}
|
||||
|
||||
void QgsAbstractStyleEntityIconGenerator::setDevicePixelRatios( const QList<double> &ratios )
|
||||
void QgsAbstractStyleEntityIconGenerator::setTargetScreenProperties( const QSet<QgsScreenProperties> &properties )
|
||||
{
|
||||
mDevicePixelRatios = ratios;
|
||||
mTargetScreenProperties = properties;
|
||||
}
|
||||
|
||||
QList<double> QgsAbstractStyleEntityIconGenerator::devicePixelRatios() const
|
||||
QSet<QgsScreenProperties> QgsAbstractStyleEntityIconGenerator::targetScreenProperties() const
|
||||
{
|
||||
return mDevicePixelRatios;
|
||||
return mTargetScreenProperties;
|
||||
}
|
||||
|
||||
|
||||
@ -79,19 +72,15 @@ QgsStyleModel::QgsStyleModel( QgsStyle *style, QObject *parent )
|
||||
{
|
||||
Q_ASSERT( mStyle );
|
||||
|
||||
// Default to generating icons using the application devicePixelRatio.
|
||||
// Additional ratios may be added by individual views to this model (eg on
|
||||
// different screens with different pixel ratios)
|
||||
if ( QGuiApplication *guiApplication = qobject_cast< QGuiApplication * >( QApplication::instance() ) )
|
||||
mDevicePixelRatios.append( guiApplication->devicePixelRatio() );
|
||||
else
|
||||
mDevicePixelRatios.append( 1.0 );
|
||||
|
||||
for ( QgsStyle::StyleEntity entity : ENTITIES )
|
||||
{
|
||||
mEntityNames.insert( entity, mStyle->allNames( entity ) );
|
||||
}
|
||||
|
||||
// ensure we always generate icons using default screen properties
|
||||
// in addition to actual target screen properties (ie device pixel ratio of 1, 96 dpi)
|
||||
mTargetScreenProperties.insert( QgsScreenProperties() );
|
||||
|
||||
connect( mStyle, &QgsStyle::entityAdded, this, &QgsStyleModel::onEntityAdded );
|
||||
connect( mStyle, &QgsStyle::entityRemoved, this, &QgsStyleModel::onEntityRemoved );
|
||||
connect( mStyle, &QgsStyle::entityRenamed, this, &QgsStyleModel::onEntityRename );
|
||||
@ -149,6 +138,14 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
QString tooltip = QStringLiteral( "<h3>%1</h3><p><i>%2</i>" ).arg( name,
|
||||
tags.count() > 0 ? tags.join( QLatin1String( ", " ) ) : tr( "Not tagged" ) );
|
||||
|
||||
// generate tooltips targeting the largest device pixel ratio for all attached screens
|
||||
QgsScreenProperties maxDevicePixelRatioScreen;
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
if ( !maxDevicePixelRatioScreen.isValid() || it->devicePixelRatio() > maxDevicePixelRatioScreen.devicePixelRatio() )
|
||||
maxDevicePixelRatioScreen = *it;
|
||||
}
|
||||
|
||||
switch ( entityType )
|
||||
{
|
||||
case QgsStyle::SymbolEntity:
|
||||
@ -159,11 +156,11 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * QFontMetrics( data( index, Qt::FontRole ).value< QFont >() ).horizontalAdvance( 'X' ) * 23 );
|
||||
int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
|
||||
QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), QSize( width, height ), height / 20, nullptr, false, mExpressionContext.get() );
|
||||
QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), QSize( width, height ), height / 20, nullptr, false, mExpressionContext.get(), nullptr, maxDevicePixelRatioScreen );
|
||||
QByteArray data;
|
||||
QBuffer buffer( &data );
|
||||
pm.save( &buffer, "PNG", 100 );
|
||||
tooltip += QStringLiteral( "<p><img src='data:image/png;base64, %3'>" ).arg( QString( data.toBase64() ) );
|
||||
tooltip += QStringLiteral( "<p><img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString( data.toBase64() ) ).arg( width );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -173,8 +170,7 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * QFontMetrics( data( index, Qt::FontRole ).value< QFont >() ).horizontalAdvance( 'X' ) * 23 );
|
||||
int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
|
||||
const QgsTextFormat format = mStyle->textFormat( name );
|
||||
const double maxDevicePixelRatio = *std::max_element( mDevicePixelRatios.constBegin(), mDevicePixelRatios.constEnd() );
|
||||
QPixmap pm = QgsTextFormat::textFormatPreviewPixmap( format, QSize( width, height ), QString(), height / 20, maxDevicePixelRatio );
|
||||
QPixmap pm = QgsTextFormat::textFormatPreviewPixmap( format, QSize( width, height ), QString(), height / 20, maxDevicePixelRatioScreen );
|
||||
QByteArray data;
|
||||
QBuffer buffer( &data );
|
||||
pm.save( &buffer, "PNG", 100 );
|
||||
@ -186,9 +182,8 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
int width = static_cast< int >( Qgis::UI_SCALE_FACTOR * QFontMetrics( data( index, Qt::FontRole ).value< QFont >() ).horizontalAdvance( 'X' ) * 23 );
|
||||
int height = static_cast< int >( width / 1.61803398875 ); // golden ratio
|
||||
const double maxDevicePixelRatio = *std::max_element( mDevicePixelRatios.constBegin(), mDevicePixelRatios.constEnd() );
|
||||
const QgsPalLayerSettings settings = mStyle->labelSettings( name );
|
||||
QPixmap pm = QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, QSize( width, height ), QString(), height / 20, maxDevicePixelRatio );
|
||||
QPixmap pm = QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, QSize( width, height ), QString(), height / 20, maxDevicePixelRatioScreen );
|
||||
QByteArray data;
|
||||
QBuffer buffer( &data );
|
||||
pm.save( &buffer, "PNG", 100 );
|
||||
@ -204,11 +199,11 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
const QgsLegendPatchShape shape = mStyle->legendPatchShape( name );
|
||||
if ( const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
|
||||
{
|
||||
QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, QSize( width, height ), height / 20, nullptr, false, nullptr, &shape );
|
||||
QPixmap pm = QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, QSize( width, height ), height / 20, nullptr, false, nullptr, &shape, maxDevicePixelRatioScreen );
|
||||
QByteArray data;
|
||||
QBuffer buffer( &data );
|
||||
pm.save( &buffer, "PNG", 100 );
|
||||
tooltip += QStringLiteral( "<p><img src='data:image/png;base64, %3'>" ).arg( QString( data.toBase64() ) );
|
||||
tooltip += QStringLiteral( "<p><img src='data:image/png;base64, %3' width=\"%4\">" ).arg( QString( data.toBase64() ) ).arg( width );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -262,12 +257,15 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
std::unique_ptr< QgsSymbol > symbol( mStyle->symbol( name ) );
|
||||
if ( symbol )
|
||||
{
|
||||
if ( mAdditionalSizes.isEmpty() )
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), QSize( 24, 24 ), 1, nullptr, false, mExpressionContext.get() ) );
|
||||
|
||||
for ( const QSize &s : mAdditionalSizes )
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), s, static_cast< int >( s.width() * ICON_PADDING_FACTOR ), nullptr, false, mExpressionContext.get() ) );
|
||||
if ( mAdditionalSizes.isEmpty() )
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), QSize( 24, 24 ), 1, nullptr, false, mExpressionContext.get(), nullptr, *it ) );
|
||||
|
||||
for ( const QSize &s : mAdditionalSizes )
|
||||
{
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol.get(), s, static_cast< int >( s.width() * ICON_PADDING_FACTOR ), nullptr, false, mExpressionContext.get(), nullptr, *it ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -304,13 +302,13 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
return icon;
|
||||
|
||||
const QgsTextFormat format( mStyle->textFormat( name ) );
|
||||
for ( const double pixelRatio : std::as_const( mDevicePixelRatios ) )
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
if ( mAdditionalSizes.isEmpty() )
|
||||
icon.addPixmap( QgsTextFormat::textFormatPreviewPixmap( format, QSize( 24, 24 ), QString(), 1, pixelRatio ) );
|
||||
icon.addPixmap( QgsTextFormat::textFormatPreviewPixmap( format, QSize( 24, 24 ), QString(), 1, *it ) );
|
||||
for ( const QSize &s : mAdditionalSizes )
|
||||
{
|
||||
icon.addPixmap( QgsTextFormat::textFormatPreviewPixmap( format, s, QString(), static_cast< int >( s.width() * ICON_PADDING_FACTOR ), pixelRatio ) );
|
||||
icon.addPixmap( QgsTextFormat::textFormatPreviewPixmap( format, s, QString(), static_cast< int >( s.width() * ICON_PADDING_FACTOR ), *it ) );
|
||||
}
|
||||
}
|
||||
mIconCache[ entityType ].insert( name, icon );
|
||||
@ -325,13 +323,13 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
return icon;
|
||||
|
||||
const QgsPalLayerSettings settings( mStyle->labelSettings( name ) );
|
||||
for ( const double pixelRatio : std::as_const( mDevicePixelRatios ) )
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
if ( mAdditionalSizes.isEmpty() )
|
||||
icon.addPixmap( QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, QSize( 24, 24 ), QString(), 1, pixelRatio ) );
|
||||
icon.addPixmap( QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, QSize( 24, 24 ), QString(), 1, *it ) );
|
||||
for ( const QSize &s : mAdditionalSizes )
|
||||
{
|
||||
icon.addPixmap( QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, s, QString(), static_cast< int >( s.width() * ICON_PADDING_FACTOR ), pixelRatio ) );
|
||||
icon.addPixmap( QgsPalLayerSettings::labelSettingsPreviewPixmap( settings, s, QString(), static_cast< int >( s.width() * ICON_PADDING_FACTOR ), *it ) );
|
||||
}
|
||||
}
|
||||
mIconCache[ entityType ].insert( name, icon );
|
||||
@ -348,14 +346,17 @@ QVariant QgsStyleModel::data( const QModelIndex &index, int role ) const
|
||||
const QgsLegendPatchShape shape = mStyle->legendPatchShape( name );
|
||||
if ( !shape.isNull() )
|
||||
{
|
||||
if ( const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
|
||||
for ( auto it = mTargetScreenProperties.constBegin(); it != mTargetScreenProperties.constEnd(); ++it )
|
||||
{
|
||||
if ( mAdditionalSizes.isEmpty() )
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, QSize( 24, 24 ), 1, nullptr, false, mExpressionContext.get(), &shape ) );
|
||||
|
||||
for ( const QSize &s : mAdditionalSizes )
|
||||
if ( const QgsSymbol *symbol = mStyle->previewSymbolForPatchShape( shape ) )
|
||||
{
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, s, static_cast< int >( s.width() * ICON_PADDING_FACTOR ), nullptr, false, mExpressionContext.get(), &shape ) );
|
||||
if ( mAdditionalSizes.isEmpty() )
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, QSize( 24, 24 ), 1, nullptr, false, mExpressionContext.get(), &shape, *it ) );
|
||||
|
||||
for ( const QSize &s : mAdditionalSizes )
|
||||
{
|
||||
icon.addPixmap( QgsSymbolLayerUtils::symbolPreviewPixmap( symbol, s, static_cast< int >( s.width() * ICON_PADDING_FACTOR ), nullptr, false, mExpressionContext.get(), &shape, *it ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -628,15 +629,15 @@ void QgsStyleModel::addDesiredIconSize( QSize size )
|
||||
mIconCache.clear();
|
||||
}
|
||||
|
||||
void QgsStyleModel::addDesiredIconDevicePixelRatio( double ratio )
|
||||
void QgsStyleModel::addTargetScreenProperties( const QgsScreenProperties &properties )
|
||||
{
|
||||
if ( mDevicePixelRatios.contains( ratio ) )
|
||||
if ( mTargetScreenProperties.contains( properties ) )
|
||||
return;
|
||||
|
||||
mDevicePixelRatios << ratio;
|
||||
mTargetScreenProperties.insert( properties );
|
||||
|
||||
if ( sIconGenerator )
|
||||
sIconGenerator->setDevicePixelRatios( mDevicePixelRatios );
|
||||
sIconGenerator->setTargetScreenProperties( mTargetScreenProperties );
|
||||
|
||||
mIconCache.clear();
|
||||
}
|
||||
@ -995,12 +996,12 @@ void QgsStyleProxyModel::addDesiredIconSize( QSize size )
|
||||
mCombinedModel->addDesiredIconSize( size );
|
||||
}
|
||||
|
||||
void QgsStyleProxyModel::addDesiredIconDevicePixelRatio( double ratio )
|
||||
void QgsStyleProxyModel::addTargetScreenProperties( const QgsScreenProperties &properties )
|
||||
{
|
||||
if ( mModel )
|
||||
mModel->addDesiredIconDevicePixelRatio( ratio );
|
||||
mModel->addTargetScreenProperties( properties );
|
||||
if ( mCombinedModel )
|
||||
mCombinedModel->addDesiredIconDevicePixelRatio( ratio );
|
||||
mCombinedModel->addTargetScreenProperties( properties );
|
||||
}
|
||||
|
||||
bool QgsStyleProxyModel::symbolTypeFilterEnabled() const
|
||||
|
@ -74,20 +74,26 @@ class CORE_EXPORT QgsAbstractStyleEntityIconGenerator : public QObject
|
||||
QList< QSize > iconSizes() const;
|
||||
|
||||
/**
|
||||
* Sets the list of icon device pixel \a ratios to generate.
|
||||
* Sets the target screen \a properties to use when generating icons.
|
||||
*
|
||||
* \see devicePixelRatios()
|
||||
* This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
* corresponds exactly to the view's screen properties in which this model is used.
|
||||
*
|
||||
* \see targetScreenProperties()
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
void setDevicePixelRatios( const QList< double > &ratios );
|
||||
void setTargetScreenProperties( const QSet< QgsScreenProperties > &properties );
|
||||
|
||||
/**
|
||||
* Returns the list of icon device pixel ratios to generate.
|
||||
* Returns the target screen properties to use when generating icons.
|
||||
*
|
||||
* \see setDevicePixelRatios()
|
||||
* This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
* corresponds exactly to the view's screen properties in which this model is used.
|
||||
*
|
||||
* \see setTargetScreenProperties()
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
QList< double > devicePixelRatios() const;
|
||||
QSet< QgsScreenProperties > targetScreenProperties() const;
|
||||
|
||||
signals:
|
||||
|
||||
@ -100,7 +106,7 @@ class CORE_EXPORT QgsAbstractStyleEntityIconGenerator : public QObject
|
||||
private:
|
||||
|
||||
QList< QSize > mIconSizes;
|
||||
QList< double > mDevicePixelRatios;
|
||||
QSet< QgsScreenProperties > mTargetScreenProperties;
|
||||
|
||||
};
|
||||
|
||||
@ -183,14 +189,14 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
|
||||
void addDesiredIconSize( QSize size );
|
||||
|
||||
/**
|
||||
* Adds an additional icon device pixel \a ratio to generate for Qt::DecorationRole data.
|
||||
* Adds additional target screen \a properties to use when generating icons for Qt::DecorationRole data.
|
||||
*
|
||||
* This allows style icons to be generated at an icon device pixel ratio which
|
||||
* corresponds exactly to the view's icon size in which this model is used.
|
||||
* This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
* corresponds exactly to the view's screen properties in which this model is used.
|
||||
*
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
void addDesiredIconDevicePixelRatio( double ratio );
|
||||
void addTargetScreenProperties( const QgsScreenProperties &properties );
|
||||
|
||||
/**
|
||||
* Sets the icon \a generator to use for deferred style entity icon generation.
|
||||
@ -219,7 +225,7 @@ class CORE_EXPORT QgsStyleModel: public QAbstractItemModel
|
||||
|
||||
QHash< QgsStyle::StyleEntity, QStringList > mEntityNames;
|
||||
|
||||
QList< double > mDevicePixelRatios;
|
||||
QSet< QgsScreenProperties > mTargetScreenProperties;
|
||||
|
||||
QList< QSize > mAdditionalSizes;
|
||||
mutable std::unique_ptr< QgsExpressionContext > mExpressionContext;
|
||||
@ -483,14 +489,14 @@ class CORE_EXPORT QgsStyleProxyModel: public QSortFilterProxyModel
|
||||
void addDesiredIconSize( QSize size );
|
||||
|
||||
/**
|
||||
* Adds an additional icon device pixel \a ratio to generate for Qt::DecorationRole data.
|
||||
* Adds additional target screen \a properties to use when generating icons for Qt::DecorationRole data.
|
||||
*
|
||||
* This allows style icons to be generated at an icon device pixel ratio which
|
||||
* corresponds exactly to the view's icon size in which this model is used.
|
||||
* This allows style icons to be generated at an icon device pixel ratio and DPI which
|
||||
* corresponds exactly to the view's screen properties in which this model is used.
|
||||
*
|
||||
* \since QGIS 3.32
|
||||
*/
|
||||
void addDesiredIconDevicePixelRatio( double ratio );
|
||||
void addTargetScreenProperties( const QgsScreenProperties &properties );
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -1104,8 +1104,9 @@ void QgsTextFormat::updateDataDefinedProperties( QgsRenderContext &context )
|
||||
mMaskSettings.updateDataDefinedProperties( context, d->mDataDefinedProperties );
|
||||
}
|
||||
|
||||
QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText, int padding, double devicePixelRatio )
|
||||
QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText, int padding, const QgsScreenProperties &screen )
|
||||
{
|
||||
const double devicePixelRatio = screen.isValid() ? screen.devicePixelRatio() : 1;
|
||||
QgsTextFormat tempFormat = format;
|
||||
QPixmap pixmap( size * devicePixelRatio );
|
||||
pixmap.fill( Qt::transparent );
|
||||
@ -1152,10 +1153,24 @@ QPixmap QgsTextFormat::textFormatPreviewPixmap( const QgsTextFormat &format, QSi
|
||||
newCoordXForm.setParameters( 1, 0, 0, 0, 0, 0 );
|
||||
context.setMapToPixel( newCoordXForm );
|
||||
|
||||
QWidget *activeWindow = QApplication::activeWindow();
|
||||
const double physicalDpiX = ( activeWindow && activeWindow->screen() ? activeWindow->screen()->physicalDotsPerInch() : 96.0 );
|
||||
context.setScaleFactor( physicalDpiX / 25.4 );
|
||||
context.setDevicePixelRatio( devicePixelRatio );
|
||||
if ( screen.isValid() )
|
||||
{
|
||||
screen.updateRenderContextForScreen( context );
|
||||
}
|
||||
else
|
||||
{
|
||||
QWidget *activeWindow = QApplication::activeWindow();
|
||||
if ( QScreen *screen = activeWindow ? activeWindow->screen() : nullptr )
|
||||
{
|
||||
context.setScaleFactor( screen->physicalDotsPerInch() / 25.4 );
|
||||
context.setDevicePixelRatio( screen->devicePixelRatio() );
|
||||
}
|
||||
else
|
||||
{
|
||||
context.setScaleFactor( 96.0 / 25.4 );
|
||||
context.setDevicePixelRatio( 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
context.setUseAdvancedEffects( true );
|
||||
context.setFlag( Qgis::RenderContextFlag::Antialiasing, true );
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "qgstextshadowsettings.h"
|
||||
#include "qgstextmasksettings.h"
|
||||
#include "qgsstringutils.h"
|
||||
#include "qgsscreenproperties.h"
|
||||
|
||||
#include <QSharedDataPointer>
|
||||
|
||||
@ -651,10 +652,10 @@ class CORE_EXPORT QgsTextFormat
|
||||
* \param size target pixmap size
|
||||
* \param previewText text to render in preview, or empty for default text
|
||||
* \param padding space between icon edge and color ramp
|
||||
* \param devicePixelRatio can be used to generate a pixmap using a specific device pixel ratio (since QGIS 3.32)
|
||||
* \param screen can be used to specify the destination screen properties 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)
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
static QPixmap textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText = QString(), int padding = 0, double devicePixelRatio = 1 );
|
||||
static QPixmap textFormatPreviewPixmap( const QgsTextFormat &format, QSize size, const QString &previewText = QString(), int padding = 0, const QgsScreenProperties &screen = QgsScreenProperties() );
|
||||
|
||||
private:
|
||||
|
||||
|
@ -16,12 +16,10 @@
|
||||
|
||||
#include "qgsstyleitemslistwidget.h"
|
||||
#include "qgsstylemanagerdialog.h"
|
||||
#include "qgsstylesavedialog.h"
|
||||
#include "qgspanelwidget.h"
|
||||
#include "qgssettings.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgswindowmanagerinterface.h"
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsproject.h"
|
||||
#include "qgsprojectstylesettings.h"
|
||||
#include <QScrollBar>
|
||||
@ -253,7 +251,7 @@ void QgsStyleItemsListWidget::setStyle( QgsStyle *style )
|
||||
mModel->addDesiredIconSize( viewSymbols->iconSize() );
|
||||
mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
|
||||
|
||||
mModel->addDesiredIconDevicePixelRatio( mSymbolTreeView->devicePixelRatioF() );
|
||||
mModel->addTargetScreenProperties( QgsScreenProperties( screen() ) );
|
||||
|
||||
viewSymbols->setTextElideMode( Qt::TextElideMode::ElideRight );
|
||||
|
||||
|
@ -20,9 +20,6 @@
|
||||
#include "qgsapplication.h"
|
||||
#include "qgsstyle.h"
|
||||
#include "qgssymbol.h"
|
||||
#include "qgssymbollayerutils.h"
|
||||
#include "qgscolorramp.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsnetworkcontentfetchertask.h"
|
||||
#include "qgsstylegroupselectiondialog.h"
|
||||
#include "qgsguiutils.h"
|
||||
@ -128,7 +125,7 @@ QgsStyleExportImportDialog::QgsStyleExportImportDialog( QgsStyle *style, QWidget
|
||||
mModel = new QgsStyleProxyModel( dialogStyle, this );
|
||||
|
||||
mModel->addDesiredIconSize( listItems->iconSize() );
|
||||
mModel->addDesiredIconDevicePixelRatio( listItems->devicePixelRatioF() );
|
||||
mModel->addTargetScreenProperties( QgsScreenProperties( screen() ) );
|
||||
|
||||
listItems->setModel( mModel );
|
||||
|
||||
|
@ -502,7 +502,7 @@ void QgsStyleManagerDialog::setCurrentStyle( QgsStyle *style )
|
||||
}
|
||||
mModel->addDesiredIconSize( mSymbolTreeView->iconSize() );
|
||||
mModel->addDesiredIconSize( listItems->iconSize() );
|
||||
mModel->addDesiredIconDevicePixelRatio( listItems->devicePixelRatioF() );
|
||||
mModel->addTargetScreenProperties( QgsScreenProperties( screen() ) );
|
||||
|
||||
mModel->setFilterString( searchBox->text() );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user