Skip to content

Commit 071e4b5

Browse files
authoredJul 14, 2021
Merge pull request #44132 from m-kuhn/respect_screen_dpi
Allow using physical DPI for map canvas
2 parents c09443a + 598e2bd commit 071e4b5

File tree

16 files changed

+254
-10
lines changed

16 files changed

+254
-10
lines changed
 

‎python/core/auto_generated/settings/qgssettingsregistry.sip.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ The ``searchChildRegistries`` parameter specifies if child registries should be
4646
void addSubRegistry( const QgsSettingsRegistry *settingsRegistry );
4747
%Docstring
4848
Append a child ``settingsRegistry`` to the register.
49+
%End
50+
51+
void removeSubRegistry( const QgsSettingsRegistry *settingsRegistry );
52+
%Docstring
53+
Remove a child ``settingsRegistry`` from the register.
4954
%End
5055

5156
QList<const QgsSettingsRegistry *> subRegistries() const;

‎python/gui/auto_generated/qgsgui.sip.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,13 @@ Returns a pointer to the singleton instance.
3838
%End
3939

4040

41+
static QgsSettingsRegistryGui *settingsRegistryGui() /KeepReference/;
42+
%Docstring
43+
Returns the gui's settings registry, used for managing gui settings.
44+
45+
.. versionadded:: 3.22
46+
%End
47+
4148
static QgsEditorWidgetRegistry *editorWidgetRegistry() /KeepReference/;
4249
%Docstring
4350
Returns the global editor widget registry, used for managing all known edit widget factories.

‎python/gui/auto_generated/qgsmapcanvas.sip.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,8 @@ called when panning is in action, reset indicates end of panning
13141314
virtual void dropEvent( QDropEvent *event );
13151315

13161316

1317+
virtual void showEvent( QShowEvent *event );
1318+
13171319

13181320

13191321

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/************************************************************************
2+
* This file has been generated automatically from *
3+
* *
4+
* src/gui/settings/qgssettingsregistrygui.h *
5+
* *
6+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
7+
************************************************************************/
8+
9+
10+
11+
12+
class QgsSettingsRegistryGui : QgsSettingsRegistry
13+
{
14+
%Docstring(signature="appended")
15+
:py:class:`QgsSettingsRegistryGui` is used for settings introspection and collects all
16+
:py:class:`QgsSettingsEntry` instances of gui.
17+
18+
.. versionadded:: 3.22
19+
%End
20+
21+
%TypeHeaderCode
22+
#include "qgssettingsregistrygui.h"
23+
%End
24+
public:
25+
26+
QgsSettingsRegistryGui();
27+
%Docstring
28+
Constructor for QgsSettingsRegistryGui.
29+
%End
30+
31+
virtual ~QgsSettingsRegistryGui();
32+
33+
34+
};
35+
36+
/************************************************************************
37+
* This file has been generated automatically from *
38+
* *
39+
* src/gui/settings/qgssettingsregistrygui.h *
40+
* *
41+
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
42+
************************************************************************/

‎python/gui/gui_auto.sip

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@
425425
%Include auto_generated/symbology/qgssymbolslistwidget.sip
426426
%Include auto_generated/symbology/qgssymbolwidgetcontext.sip
427427
%Include auto_generated/symbology/qgsvectorfieldsymbollayerwidget.sip
428+
%Include auto_generated/settings/qgssettingsregistrygui.sip
428429
%Include auto_generated/tableeditor/qgstableeditordialog.sip
429430
%Include auto_generated/tableeditor/qgstableeditorwidget.sip
430431
%Include auto_generated/editorwidgets/qgsqmlwidgetwrapper.sip

‎src/app/options/qgsoptions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
#include "qgsclipboard.h"
5656
#include "qgssettings.h"
5757
#include "qgssettingsregistrycore.h"
58+
#include "qgssettingsregistrygui.h"
5859
#include "qgsoptionswidgetfactory.h"
5960
#include "qgslocatorwidget.h"
6061
#include "qgslocatoroptionswidget.h"
@@ -740,6 +741,8 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
740741
mMapTipsDelaySpinBox->setValue( mSettings->value( QStringLiteral( "qgis/mapTipsDelay" ), 850 ).toInt() );
741742
mMapTipsDelaySpinBox->setClearValue( 850 );
742743

744+
mRespectScreenDpiCheckBox->setChecked( QgsSettingsRegistryGui::settingsRespectScreenDPI.value() );
745+
743746
//
744747
// Raster properties
745748
//
@@ -1606,6 +1609,8 @@ void QgsOptions::saveOptions()
16061609

16071610
mSettings->setValue( QStringLiteral( "/qgis/defaultLegendGraphicResolution" ), mLegendGraphicResolutionSpinBox->value() );
16081611
mSettings->setValue( QStringLiteral( "/qgis/mapTipsDelay" ), mMapTipsDelaySpinBox->value() );
1612+
QgsSettingsRegistryGui::settingsRespectScreenDPI.setValue( mRespectScreenDpiCheckBox->isChecked() );
1613+
16091614
mSettings->setEnumValue( QStringLiteral( "/qgis/copyFeatureFormat" ), ( QgsClipboard::CopyFormat )mComboCopyFeatureFormat->currentData().toInt() );
16101615
QgisApp::instance()->setMapTipsDelay( mMapTipsDelaySpinBox->value() );
16111616

‎src/core/settings/qgssettingsregistry.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,23 @@ void QgsSettingsRegistry::addSubRegistry( const QgsSettingsRegistry *settingsReg
9898
mSettingsRegistryChildList.append( settingsRegistry );
9999
}
100100

101+
void QgsSettingsRegistry::removeSubRegistry( const QgsSettingsRegistry *settingsRegistry )
102+
{
103+
if ( !settingsRegistry )
104+
{
105+
QgsDebugMsg( QStringLiteral( "Trying to unregister a nullptr child settings registry." ) );
106+
return;
107+
}
108+
109+
if ( mSettingsRegistryChildList.contains( settingsRegistry ) )
110+
{
111+
QgsDebugMsg( QStringLiteral( "Child register is not registered." ) );
112+
return;
113+
}
114+
115+
mSettingsRegistryChildList.removeAll( settingsRegistry );
116+
}
117+
101118
QList<const QgsSettingsRegistry *> QgsSettingsRegistry::subRegistries() const
102119
{
103120
return mSettingsRegistryChildList;

‎src/core/settings/qgssettingsregistry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ class CORE_EXPORT QgsSettingsRegistry
6262
*/
6363
void addSubRegistry( const QgsSettingsRegistry *settingsRegistry );
6464

65+
/**
66+
* Remove a child \a settingsRegistry from the register.
67+
*/
68+
void removeSubRegistry( const QgsSettingsRegistry *settingsRegistry );
69+
6570
/**
6671
* Returns the list of registered child QgsSettingsRegistry.
6772
*/

‎src/gui/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ set(QGIS_GUI_SRCS
368368
providers/ogr/qgsogritemguiprovider.cpp
369369
providers/ogr/qgsgeopackageprojectstorageguiprovider.cpp
370370

371+
settings/qgssettingsregistrygui.cpp
372+
371373
tableeditor/qgstableeditordialog.cpp
372374
tableeditor/qgstableeditorformattingwidget.cpp
373375
tableeditor/qgstableeditorwidget.cpp
@@ -1241,6 +1243,8 @@ set(QGIS_GUI_HDRS
12411243
symbology/qgssymbolwidgetcontext.h
12421244
symbology/qgsvectorfieldsymbollayerwidget.h
12431245

1246+
settings/qgssettingsregistrygui.h
1247+
12441248
tableeditor/qgstableeditordialog.h
12451249
tableeditor/qgstableeditorformattingwidget.h
12461250
tableeditor/qgstableeditorwidget.h
@@ -1423,9 +1427,10 @@ target_include_directories(qgis_gui PUBLIC
14231427
${CMAKE_SOURCE_DIR}/src/gui/providers/ogr
14241428
${CMAKE_SOURCE_DIR}/src/gui/pointcloud
14251429
${CMAKE_SOURCE_DIR}/src/gui/raster
1430+
${CMAKE_SOURCE_DIR}/src/gui/settings
1431+
${CMAKE_SOURCE_DIR}/src/gui/tableeditor
14261432
${CMAKE_SOURCE_DIR}/src/gui/vector
14271433
${CMAKE_SOURCE_DIR}/src/gui/vectortile
1428-
${CMAKE_SOURCE_DIR}/src/gui/tableeditor
14291434

14301435
${CMAKE_BINARY_DIR}/src/gui
14311436
${CMAKE_BINARY_DIR}/src/ui

‎src/gui/qgsgui.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
#include "qgssubsetstringeditorproviderregistry.h"
6262
#include "qgsprovidersourcewidgetproviderregistry.h"
6363
#include "qgsrelationwidgetregistry.h"
64+
#include "qgssettingsregistrygui.h"
6465

6566
QgsGui *QgsGui::instance()
6667
{
@@ -73,6 +74,11 @@ QgsNative *QgsGui::nativePlatformInterface()
7374
return instance()->mNative;
7475
}
7576

77+
QgsSettingsRegistryGui *QgsGui::settingsRegistryGui()
78+
{
79+
return instance()->mSettingsRegistryGui;
80+
}
81+
7682
QgsEditorWidgetRegistry *QgsGui::editorWidgetRegistry()
7783
{
7884
return instance()->mEditorWidgetRegistry;
@@ -204,6 +210,7 @@ QgsGui::~QgsGui()
204210
delete mSubsetStringEditorProviderRegistry;
205211
delete mProviderSourceWidgetProviderRegistry;
206212
delete mRelationEditorRegistry;
213+
delete mSettingsRegistryGui;
207214
}
208215

209216
QColor QgsGui::sampleColor( QPoint point )
@@ -249,6 +256,8 @@ QgsGui::QgsGui()
249256
mNative = new QgsNative();
250257
#endif
251258

259+
mSettingsRegistryGui = new QgsSettingsRegistryGui();
260+
252261
mCodeEditorColorSchemeRegistry = new QgsCodeEditorColorSchemeRegistry();
253262

254263
// provider gui registry initialize QgsProviderRegistry too

‎src/gui/qgsgui.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <QWidget>
2424
#include <memory>
2525

26+
class QgsSettingsRegistryGui;
2627
class QgsEditorWidgetRegistry;
2728
class QgsShortcutsManager;
2829
class QgsLayerTreeEmbeddedWidgetRegistry;
@@ -84,6 +85,12 @@ class GUI_EXPORT QgsGui : public QObject
8485
*/
8586
SIP_SKIP static QgsNative *nativePlatformInterface();
8687

88+
/**
89+
* Returns the gui's settings registry, used for managing gui settings.
90+
* \since QGIS 3.22
91+
*/
92+
static QgsSettingsRegistryGui *settingsRegistryGui() SIP_KEEPREFERENCE;
93+
8794
/**
8895
* Returns the global editor widget registry, used for managing all known edit widget factories.
8996
*/
@@ -261,6 +268,7 @@ class GUI_EXPORT QgsGui : public QObject
261268

262269
QgsGui();
263270

271+
QgsSettingsRegistryGui *mSettingsRegistryGui = nullptr;
264272
QgsProviderGuiRegistry *mProviderGuiRegistry = nullptr;
265273
QgsWidgetStateHelper *mWidgetStateHelper = nullptr;
266274
QgsNative *mNative = nullptr;

‎src/gui/qgsmapcanvas.cpp

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ email : sherman at mrcc.com
9191
#include "qgscoordinatereferencesystemregistry.h"
9292
#include "qgslabelingresults.h"
9393
#include "qgsmaplayerutils.h"
94+
#include "qgssettingsregistrygui.h"
9495

9596
/**
9697
* \ingroup gui
@@ -205,19 +206,12 @@ QgsMapCanvas::QgsMapCanvas( QWidget *parent )
205206

206207
QSize s = viewport()->size();
207208
mSettings.setOutputSize( s );
208-
mSettings.setDevicePixelRatio( devicePixelRatio() );
209+
209210
setSceneRect( 0, 0, s.width(), s.height() );
210211
mScene->setSceneRect( QRectF( 0, 0, s.width(), s.height() ) );
211212

212213
moveCanvasContents( true );
213214

214-
// keep device pixel ratio up to date on screen or resolution change
215-
if ( window()->windowHandle() )
216-
{
217-
connect( window()->windowHandle(), &QWindow::screenChanged, this, [ = ]( QScreen * ) {mSettings.setDevicePixelRatio( devicePixelRatio() );} );
218-
connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, [ = ]( qreal ) {mSettings.setDevicePixelRatio( devicePixelRatio() );} );
219-
}
220-
221215
connect( &mMapUpdateTimer, &QTimer::timeout, this, &QgsMapCanvas::mapUpdateTimeout );
222216
mMapUpdateTimer.setInterval( 250 );
223217

@@ -245,7 +239,6 @@ QgsMapCanvas::QgsMapCanvas( QWidget *parent )
245239
setCanvasColor( mSettings.backgroundColor() );
246240

247241
setTemporalRange( mSettings.temporalRange() );
248-
249242
refresh();
250243
}
251244

@@ -968,6 +961,22 @@ void QgsMapCanvas::showContextMenu( QgsMapMouseEvent *event )
968961
menu.exec( event->globalPos() );
969962
}
970963

964+
void QgsMapCanvas::updateDevicePixelFromScreen()
965+
{
966+
mSettings.setDevicePixelRatio( devicePixelRatio() );
967+
// TODO: QGIS 4 -> always respect screen dpi
968+
if ( QgsSettingsRegistryGui::settingsRespectScreenDPI.value() )
969+
{
970+
if ( window()->windowHandle() )
971+
mSettings.setOutputDpi( window()->windowHandle()->screen()->physicalDotsPerInch() );
972+
}
973+
else
974+
{
975+
// Fallback: compatibility with QGIS <= 3.20; always assume low dpi screens
976+
mSettings.setOutputDpi( window()->windowHandle()->screen()->logicalDotsPerInch() );
977+
}
978+
}
979+
971980
void QgsMapCanvas::setTemporalRange( const QgsDateTimeRange &dateTimeRange )
972981
{
973982
if ( temporalRange() == dateTimeRange )
@@ -2569,6 +2578,24 @@ void QgsMapCanvas::dropEvent( QDropEvent *event )
25692578
}
25702579
}
25712580

2581+
void QgsMapCanvas::showEvent( QShowEvent *event )
2582+
{
2583+
Q_UNUSED( event )
2584+
updateDevicePixelFromScreen();
2585+
// keep device pixel ratio up to date on screen or resolution change
2586+
if ( window()->windowHandle() )
2587+
{
2588+
connect( window()->windowHandle(), &QWindow::screenChanged, this, [ = ]( QScreen * )
2589+
{
2590+
disconnect( mScreenDpiChangedConnection );
2591+
mScreenDpiChangedConnection = connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, &QgsMapCanvas::updateDevicePixelFromScreen );
2592+
updateDevicePixelFromScreen();
2593+
} );
2594+
2595+
mScreenDpiChangedConnection = connect( window()->windowHandle()->screen(), &QScreen::physicalDotsPerInchChanged, this, &QgsMapCanvas::updateDevicePixelFromScreen );
2596+
}
2597+
}
2598+
25722599
QPoint QgsMapCanvas::mouseLastXY()
25732600
{
25742601
return mCanvasProperties->mouseLastXY;

‎src/gui/qgsmapcanvas.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex
981981
//! Renames the active map theme called \a theme to \a newTheme
982982
void mapThemeRenamed( const QString &theme, const QString &newTheme );
983983

984+
void updateDevicePixelFromScreen();
985+
984986
signals:
985987

986988
/**
@@ -1181,6 +1183,7 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex
11811183

11821184
void dropEvent( QDropEvent *event ) override;
11831185

1186+
void showEvent( QShowEvent *event ) override;
11841187

11851188
/// implementation struct
11861189
class CanvasProperties;
@@ -1358,6 +1361,8 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView, public QgsExpressionContex
13581361

13591362
int mBlockItemPositionUpdates = 0;
13601363

1364+
QMetaObject::Connection mScreenDpiChangedConnection;
1365+
13611366
/**
13621367
* Returns the last cursor position on the canvas in geographical coordinates
13631368
* \since QGIS 3.4
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/***************************************************************************
2+
qgssettingsregistrygui.cpp
3+
--------------------------------------
4+
Date : July 2021
5+
Copyright : (C) 2021 by Damiano Lombardi
6+
Email : damiano at opengis dot ch
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgssettingsregistrygui.h"
17+
18+
#include "qgsapplication.h"
19+
#include "qgssettingsregistrycore.h"
20+
21+
QgsSettingsRegistryGui::QgsSettingsRegistryGui()
22+
: QgsSettingsRegistry()
23+
{
24+
addSettingsEntry( &settingsRespectScreenDPI );
25+
26+
QgsApplication::settingsRegistryCore()->addSubRegistry( this );
27+
}
28+
29+
QgsSettingsRegistryGui::~QgsSettingsRegistryGui()
30+
{
31+
QgsApplication::settingsRegistryCore()->removeSubRegistry( this );
32+
}
33+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/***************************************************************************
2+
qgssettingsregistrygui.h
3+
--------------------------------------
4+
Date : July 2021
5+
Copyright : (C) 2021 by Damiano Lombardi
6+
Email : damiano at opengis dot ch
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
17+
#ifndef QGSSETTINGSREGISTRYGUI_H
18+
#define QGSSETTINGSREGISTRYGUI_H
19+
20+
#include "qgis_gui.h"
21+
#include "qgis_sip.h"
22+
#include "qgssettingsregistry.h"
23+
#include "qgssettingsentry.h"
24+
25+
/**
26+
* \ingroup gui
27+
* \class QgsSettingsRegistryGui
28+
* QgsSettingsRegistryGui is used for settings introspection and collects all
29+
* QgsSettingsEntry instances of gui.
30+
*
31+
* \since QGIS 3.22
32+
*/
33+
class GUI_EXPORT QgsSettingsRegistryGui : public QgsSettingsRegistry
34+
{
35+
public:
36+
37+
/**
38+
* Constructor for QgsSettingsRegistryGui.
39+
*/
40+
QgsSettingsRegistryGui();
41+
42+
/**
43+
* Destructor for QgsSettingsRegistryGui.
44+
*/
45+
virtual ~QgsSettingsRegistryGui();
46+
47+
#ifndef SIP_RUN
48+
//! Settings entry respect screen dpi
49+
static const inline QgsSettingsEntryBool settingsRespectScreenDPI = QgsSettingsEntryBool( QStringLiteral( "qgis/respect_screen_dpi" ), QgsSettings::Gui, false );
50+
#endif
51+
52+
};
53+
54+
#endif // QGSSETTINGSREGISTRYGUI_H

‎src/ui/qgsoptionsbase.ui

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3629,6 +3629,25 @@
36293629
</layout>
36303630
</widget>
36313631
</item>
3632+
<item>
3633+
<widget class="QgsCollapsibleGroupBox" name="groupBox_32">
3634+
<property name="title">
3635+
<string>DPI</string>
3636+
</property>
3637+
<layout class="QGridLayout" name="gridLayout_38">
3638+
<item row="0" column="0">
3639+
<widget class="QCheckBox" name="mRespectScreenDpiCheckBox">
3640+
<property name="toolTip">
3641+
<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>
3642+
</property>
3643+
<property name="text">
3644+
<string>Respect screen DPI</string>
3645+
</property>
3646+
</widget>
3647+
</item>
3648+
</layout>
3649+
</widget>
3650+
</item>
36323651
<item>
36333652
<spacer>
36343653
<property name="orientation">

0 commit comments

Comments
 (0)
Please sign in to comment.