Skip to content

Commit edbb256

Browse files
Copilotfabiencastan
andcommitted
Implement core high-DPI scaling infrastructure
Co-authored-by: fabiencastan <[email protected]>
1 parent eae5176 commit edbb256

File tree

5 files changed

+408
-5
lines changed

5 files changed

+408
-5
lines changed

meshroom/ui/app.py

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from PySide6 import __version__ as PySideVersion
88
from PySide6 import QtCore
9-
from PySide6.QtCore import QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings
9+
from PySide6.QtCore import QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings, Qt
1010
from PySide6.QtGui import QIcon
1111
from PySide6.QtQml import QQmlDebuggingEnabler
1212
from PySide6.QtQuickControls2 import QQuickStyle
@@ -211,14 +211,26 @@ def __init__(self, inputArgs):
211211

212212
logging.getLogger().setLevel(meshroom.logStringToPython[args.verbose])
213213

214+
# Enable high-DPI scaling before creating QApplication
215+
QApplication.setHighDpiScaleFactorRoundingPolicy(Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
216+
QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)
217+
QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps, True)
218+
214219
super().__init__(inputArgs[:1] + qtArgs)
215220

221+
# Get DPI information and calculate scaling factors
222+
self._dpiInfo = self._getDpiInfo()
223+
self._scalingSettings = self._loadScalingSettings()
224+
216225
self.setOrganizationName('AliceVision')
217226
self.setApplicationName('Meshroom')
218227
self.setApplicationVersion(meshroom.__version_label__)
219228

229+
# Apply font scaling
220230
font = self.font()
221-
font.setPointSize(9)
231+
basePointSize = 9
232+
scaledPointSize = int(basePointSize * self._scalingSettings["fontScale"])
233+
font.setPointSize(scaledPointSize)
222234
self.setFont(font)
223235

224236
# Use Fusion style by default.
@@ -331,6 +343,120 @@ def __init__(self, inputArgs):
331343

332344
self.engine.load(os.path.normpath(url))
333345

346+
def _getDpiInfo(self):
347+
"""Get DPI information from the primary screen."""
348+
screen = self.primaryScreen()
349+
if screen:
350+
dpi = screen.logicalDotsPerInch()
351+
physicalDpi = screen.physicalDotsPerInch()
352+
devicePixelRatio = screen.devicePixelRatio()
353+
return {
354+
"logicalDpi": dpi,
355+
"physicalDpi": physicalDpi,
356+
"devicePixelRatio": devicePixelRatio,
357+
"isHighDpi": dpi > 96 or devicePixelRatio > 1.0
358+
}
359+
return {"logicalDpi": 96, "physicalDpi": 96, "devicePixelRatio": 1.0, "isHighDpi": False}
360+
361+
def _calculateAutoScaleFactor(self):
362+
"""Calculate automatic UI scale factor based on DPI."""
363+
dpi = self._dpiInfo["logicalDpi"]
364+
deviceRatio = self._dpiInfo["devicePixelRatio"]
365+
366+
# Base DPI is 96 (typical for 1x scaling)
367+
baseDpi = 96
368+
369+
# Calculate scale factor from DPI
370+
dpiScale = dpi / baseDpi
371+
372+
# Use the maximum of DPI scale and device pixel ratio
373+
autoScale = max(dpiScale, deviceRatio)
374+
375+
# Clamp to reasonable values (0.5x to 4.0x)
376+
return max(0.5, min(4.0, autoScale))
377+
378+
def _loadScalingSettings(self):
379+
"""Load scaling settings from QSettings with automatic defaults."""
380+
settings = QSettings()
381+
settings.beginGroup("Display")
382+
383+
autoScale = self._calculateAutoScaleFactor()
384+
385+
scalingSettings = {
386+
"uiScale": settings.value("uiScale", autoScale, type=float),
387+
"fontScale": settings.value("fontScale", autoScale, type=float),
388+
"autoDetect": settings.value("autoDetect", True, type=bool)
389+
}
390+
391+
settings.endGroup()
392+
return scalingSettings
393+
394+
def _saveScalingSettings(self):
395+
"""Save current scaling settings to QSettings."""
396+
settings = QSettings()
397+
settings.beginGroup("Display")
398+
399+
settings.setValue("uiScale", self._scalingSettings["uiScale"])
400+
settings.setValue("fontScale", self._scalingSettings["fontScale"])
401+
settings.setValue("autoDetect", self._scalingSettings["autoDetect"])
402+
403+
settings.endGroup()
404+
settings.sync()
405+
406+
@Slot(float)
407+
def setUiScale(self, scale):
408+
"""Set UI scale factor."""
409+
self._scalingSettings["uiScale"] = max(0.5, min(4.0, scale))
410+
self._saveScalingSettings()
411+
self.scalingSettingsChanged.emit()
412+
413+
@Slot(float)
414+
def setFontScale(self, scale):
415+
"""Set font scale factor."""
416+
self._scalingSettings["fontScale"] = max(0.5, min(4.0, scale))
417+
418+
# Apply font scaling immediately
419+
font = self.font()
420+
basePointSize = 9
421+
scaledPointSize = int(basePointSize * scale)
422+
font.setPointSize(scaledPointSize)
423+
self.setFont(font)
424+
425+
self._saveScalingSettings()
426+
self.scalingSettingsChanged.emit()
427+
428+
@Slot(bool)
429+
def setAutoDetect(self, autoDetect):
430+
"""Enable/disable automatic DPI detection."""
431+
self._scalingSettings["autoDetect"] = autoDetect
432+
433+
if autoDetect:
434+
autoScale = self._calculateAutoScaleFactor()
435+
self.setUiScale(autoScale)
436+
self.setFontScale(autoScale)
437+
438+
self._saveScalingSettings()
439+
440+
@Slot()
441+
def resetScalingToDefaults(self):
442+
"""Reset scaling settings to automatic defaults."""
443+
autoScale = self._calculateAutoScaleFactor()
444+
self._scalingSettings = {
445+
"uiScale": autoScale,
446+
"fontScale": autoScale,
447+
"autoDetect": True
448+
}
449+
450+
# Apply font scaling immediately
451+
font = self.font()
452+
basePointSize = 9
453+
scaledPointSize = int(basePointSize * autoScale)
454+
font.setPointSize(scaledPointSize)
455+
self.setFont(font)
456+
457+
self._saveScalingSettings()
458+
self.scalingSettingsChanged.emit()
459+
334460
def terminateManual(self):
335461
self.engine.clearComponentCache()
336462
self.engine.collectGarbage()
@@ -702,6 +828,12 @@ def _getEnvironmentVariableValue(self, key: str, defaultValue: bool) -> bool:
702828
activeProjectChanged = Signal()
703829
activeProject = Property(Variant, lambda self: self._activeProject, notify=activeProjectChanged)
704830

831+
scalingSettingsChanged = Signal()
832+
dpiInfo = Property("QVariantMap", lambda self: self._dpiInfo, constant=True)
833+
uiScale = Property(float, lambda self: self._scalingSettings["uiScale"], notify=scalingSettingsChanged)
834+
fontScale = Property(float, lambda self: self._scalingSettings["fontScale"], notify=scalingSettingsChanged)
835+
autoDetectDpi = Property(bool, lambda self: self._scalingSettings["autoDetect"], notify=scalingSettingsChanged)
836+
705837
changelogModel = Property("QVariantList", _changelogModel, constant=True)
706838
licensesModel = Property("QVariantList", _licensesModel, constant=True)
707839
pipelineTemplateFilesChanged = Signal()

meshroom/ui/qml/Application.qml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,10 @@ Page {
519519
id: dialogsFactory
520520
}
521521

522+
DisplaySettingsDialog {
523+
id: displaySettingsDialog
524+
}
525+
522526
CompatibilityManager {
523527
id: compatibilityManager
524528
uigraph: _reconstruction
@@ -624,7 +628,7 @@ Page {
624628
id: homeButton
625629
text: MaterialIcons.home
626630

627-
font.pointSize: 18
631+
font.pointSize: UISettings.headerFont
628632

629633
background: Rectangle {
630634
color: homeButton.hovered ? activePalette.highlight : Qt.darker(activePalette.window, 1.15)
@@ -874,6 +878,11 @@ Page {
874878
ToolTip.visible: hovered && pasteAction.enabled
875879
ToolTip.text: pasteAction.tooltip
876880
}
881+
MenuSeparator {}
882+
MenuItem {
883+
text: "Display Settings..."
884+
onTriggered: displaySettingsDialog.open()
885+
}
877886
}
878887
Menu {
879888
title: "View"
@@ -1027,7 +1036,7 @@ Page {
10271036
RowLayout {
10281037
spacing: 0
10291038
MaterialToolButton {
1030-
font.pointSize: 8
1039+
font.pointSize: UISettings.smallFont
10311040
text: MaterialIcons.folder_open
10321041
ToolTip.text: "Open Cache Folder"
10331042
onClicked: Qt.openUrlExternally(Filepath.stringToUrl(_reconstruction.graph.cacheDir))
@@ -1170,7 +1179,7 @@ Page {
11701179
text: MaterialIcons.sync
11711180
ToolTip.text: "Refresh Nodes Status"
11721181
ToolTip.visible: hovered
1173-
font.pointSize: 11
1182+
font.pointSize: UISettings.mediumFont
11741183
padding: 2
11751184
onClicked: {
11761185
updatingStatus = true

0 commit comments

Comments
 (0)