Skip to content
Permalink
Browse files
Respect screen DPI
QGIS currently renders symbology too small on high dpi screens.
This commit adds a new option to actually respect the screen DPI.

A new option was added (opt-in) to make sure that projects continue
to look the same.
The default for this option is planned to change with QGIS 4.
  • Loading branch information
m-kuhn committed Jul 7, 2021
1 parent aaff7ce commit 2705e0117a5780650b0c69a2f6d4dc7c17a944a7
Showing with 59 additions and 5 deletions.
  1. +4 −0 src/app/options/qgsoptions.cpp
  2. +31 −4 src/gui/qgsmapcanvas.cpp
  3. +4 −0 src/gui/qgsmapcanvas.h
  4. +20 −1 src/ui/qgsoptionsbase.ui
@@ -740,6 +740,8 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
mMapTipsDelaySpinBox->setValue( mSettings->value( QStringLiteral( "qgis/mapTipsDelay" ), 850 ).toInt() );
mMapTipsDelaySpinBox->setClearValue( 850 );

mRespectScreenDpiCheckBox->setChecked( mSettings->value( QStringLiteral( "qgis/respect_screen_dpi" ), QStringLiteral( "false" ), QgsSettings::Section::Gui ) == QStringLiteral( "true" ) );

//
// Raster properties
//
@@ -1606,6 +1608,8 @@ void QgsOptions::saveOptions()

mSettings->setValue( QStringLiteral( "/qgis/defaultLegendGraphicResolution" ), mLegendGraphicResolutionSpinBox->value() );
mSettings->setValue( QStringLiteral( "/qgis/mapTipsDelay" ), mMapTipsDelaySpinBox->value() );
mSettings->setValue( QStringLiteral( "qgis/respect_screen_dpi" ), mRespectScreenDpiCheckBox->isChecked() ? QStringLiteral( "true" ) : QStringLiteral( "false" ), QgsSettings::Section::Gui );

mSettings->setEnumValue( QStringLiteral( "/qgis/copyFeatureFormat" ), ( QgsClipboard::CopyFormat )mComboCopyFeatureFormat->currentData().toInt() );
QgisApp::instance()->setMapTipsDelay( mMapTipsDelaySpinBox->value() );

@@ -205,17 +205,30 @@ QgsMapCanvas::QgsMapCanvas( QWidget *parent )

QSize s = viewport()->size();
mSettings.setOutputSize( s );
mSettings.setDevicePixelRatio( devicePixelRatio() );
updateDevicePixelFromScreen();
setSceneRect( 0, 0, s.width(), s.height() );
mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );

moveCanvasContents( true );


// keep device pixel ratio up to date on screen or resolution change
if ( window()->windowHandle() )
{
connect( window()->windowHandle(), &QWindow::screenChanged, this, [ = ]( QScreen * ) {mSettings.setDevicePixelRatio( devicePixelRatio() );} );
connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, [ = ]( qreal ) {mSettings.setDevicePixelRatio( devicePixelRatio() );} );
connect( window()->windowHandle(), &QWindow::screenChanged, this, [ = ]( QScreen * )
{
disconnect( mScreenDpiChangedConnection );
mScreenDpiChangedConnection = connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, [ = ]( qreal )
{
updateDevicePixelFromScreen();
} );
updateDevicePixelFromScreen();
} );

mScreenDpiChangedConnection = connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, [ = ]( qreal )
{
updateDevicePixelFromScreen();
} );
}

connect( &mMapUpdateTimer, &QTimer::timeout, this, &QgsMapCanvas::mapUpdateTimeout );
@@ -245,7 +258,6 @@ QgsMapCanvas::QgsMapCanvas( QWidget *parent )
setCanvasColor( mSettings.backgroundColor() );

setTemporalRange( mSettings.temporalRange() );

refresh();
}

@@ -968,6 +980,21 @@ void QgsMapCanvas::showContextMenu( QgsMapMouseEvent *event )
menu.exec( event->globalPos() );
}

void QgsMapCanvas::updateDevicePixelFromScreen()
{
mSettings.setDevicePixelRatio( devicePixelRatio() );
// TODO: QGIS 4 -> always respect screen dpi
if ( QgsSettings().value( QStringLiteral( "qgis/respect_screen_dpi" ), QStringLiteral( "false" ), QgsSettings::Section::Gui ) == QLatin1String( "true" ) )
{
mSettings.setOutputDpi( screen()->physicalDotsPerInch() );
}
else
{
// Fallback: compatibility with QGIS <= 3.20; always assume low dpi screens
mSettings.setOutputDpi( 96.0 );
}
}

void QgsMapCanvas::setTemporalRange( const QgsDateTimeRange &dateTimeRange )
{
if ( temporalRange() == dateTimeRange )
@@ -1358,6 +1358,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex

int mBlockItemPositionUpdates = 0;

QMetaObject::Connection mScreenDpiChangedConnection;

/**
* Returns the last cursor position on the canvas in geographical coordinates
* \since QGIS 3.4
@@ -1428,6 +1430,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex

void showContextMenu( QgsMapMouseEvent *event );

void updateDevicePixelFromScreen();

friend class TestQgsMapCanvas;

}; // class QgsMapCanvas
@@ -332,7 +332,7 @@
<item>
<widget class="QStackedWidget" name="mOptionsStackedWidget">
<property name="currentIndex">
<number>0</number>
<number>6</number>
</property>
<widget class="QWidget" name="mOptionsPageGeneral">
<layout class="QVBoxLayout" name="verticalLayout_3">
@@ -3629,6 +3629,25 @@
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="groupBox_32">
<property name="title">
<string>DPI</string>
</property>
<layout class="QGridLayout" name="gridLayout_38">
<item row="0" column="0">
<widget class="QCheckBox" name="mRespectScreenDpiCheckBox">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If respect screen DPI is activated, symbology on the map canvas will be rendered with appropriate screen DPI. This means that a symbol with 1mm size will be rendered with 1mm size on every screen (provided it is configured correctly at the system).&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Note:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This is only possible since QGIS 3.20.&lt;/p&gt;&lt;p&gt;Any earlier version of QGIS will render symbology on the map canvas smaller on HiDPI screens.&lt;/p&gt;&lt;p&gt;Requires a restart&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Respect screen DPI</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer>
<property name="orientation">

0 comments on commit 2705e01

Please sign in to comment.