mirror of https://gitlab.com/openlp/openlp.git
High DPI Fixes
This commit is contained in:
parent
8ddab1dc16
commit
cf558fbe9b
|
@ -39,6 +39,7 @@ from PyQt5 import QtCore, QtGui, QtWebEngineWidgets, QtWidgets # noqa
|
|||
|
||||
from openlp.core.api.deploy import check_for_remote_update
|
||||
from openlp.core.common.applocation import AppLocation
|
||||
from openlp.core.common.enum import HiDPIMode
|
||||
from openlp.core.common.i18n import LanguageManager, UiStrings, translate
|
||||
from openlp.core.common.mixins import LogMixin
|
||||
from openlp.core.common.path import create_paths, resolve
|
||||
|
@ -395,6 +396,51 @@ def backup_if_version_changed(settings):
|
|||
return True
|
||||
|
||||
|
||||
def apply_dpi_adjustments_stage_qt(hidpi_mode, qt_args):
|
||||
if hidpi_mode == HiDPIMode.Windows_Unaware:
|
||||
os.environ['QT_SCALE_FACTOR'] = '1'
|
||||
os.environ['QT_AUTO_SCREEN_SCALE_FACTOR'] = '0'
|
||||
os.environ['QT_ENABLE_HIGHDPI_SCALING'] = '0'
|
||||
if is_win():
|
||||
try:
|
||||
platform_index = qt_args.index('-platform')
|
||||
qt_args[platform_index + 1] += ' windows:dpiawareness=0'
|
||||
except ValueError:
|
||||
qt_args.extend(['-platform', 'windows:dpiawareness=0'])
|
||||
else:
|
||||
QtWidgets.QApplication.setAttribute(QtCore.Qt.ApplicationAttribute.AA_EnableHighDpiScaling)
|
||||
if hidpi_mode == HiDPIMode.Default:
|
||||
no_custom_factor_rounding = not ('QT_SCALE_FACTOR_ROUNDING_POLICY' in os.environ
|
||||
and bool(os.environ['QT_SCALE_FACTOR_ROUNDING_POLICY'].strip()))
|
||||
if no_custom_factor_rounding:
|
||||
# TODO Won't be needed on PyQt6, PassThrough is the default
|
||||
os.environ['QT_SCALE_FACTOR_ROUNDING_POLICY'] = 'PassThrough'
|
||||
|
||||
|
||||
def apply_dpi_adjustments_stage_application(hidpi_mode, application):
|
||||
"""
|
||||
Apply OpenLP DPI adjustments to bypass Windows and QT bugs (unless disabled on settings)
|
||||
|
||||
:param args: OpenLP startup arguments
|
||||
:param settings: The settings object
|
||||
:param stage: The stage of app
|
||||
"""
|
||||
if hidpi_mode == HiDPIMode.Default:
|
||||
no_custom_factor_rounding = not ('QT_SCALE_FACTOR_ROUNDING_POLICY' in os.environ
|
||||
and bool(os.environ['QT_SCALE_FACTOR_ROUNDING_POLICY'].strip()))
|
||||
if no_custom_factor_rounding and hasattr(QtWidgets.QApplication, 'setHighDpiScaleFactorRoundingPolicy'):
|
||||
# TODO Won't be needed on PyQt6, PassThrough is the default
|
||||
application.setHighDpiScaleFactorRoundingPolicy(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
|
||||
if is_win() and application.devicePixelRatio() > 1.0:
|
||||
# Increasing font size to match pixel ratio (Windows only)
|
||||
# TODO: Review on PyQt6 migration
|
||||
font = application.font()
|
||||
font.setPointSizeF(font.pointSizeF() * application.devicePixelRatio())
|
||||
application.setFont(font)
|
||||
if hidpi_mode != HiDPIMode.Windows_Unaware:
|
||||
application.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
|
||||
|
||||
|
||||
def main():
|
||||
"""
|
||||
The main function which parses command line options and then runs
|
||||
|
@ -423,6 +469,11 @@ def main():
|
|||
'lib' / 'QtWebEngineCore.framework' / 'Versions' / '5' /
|
||||
'Helpers' / 'QtWebEngineProcess.app' / 'Contents' / 'MacOS' /
|
||||
'QtWebEngineProcess')
|
||||
no_custom_factor_rounding = not ('QT_SCALE_FACTOR_ROUNDING_POLICY' in os.environ
|
||||
and bool(os.environ['QT_SCALE_FACTOR_ROUNDING_POLICY'].strip()))
|
||||
if no_custom_factor_rounding:
|
||||
# TODO Won't be needed on PyQt6
|
||||
os.environ['QT_SCALE_FACTOR_ROUNDING_POLICY'] = 'PassThrough'
|
||||
# Initialise the resources
|
||||
qInitResources()
|
||||
# Now create and actually run the application.
|
||||
|
@ -433,6 +484,15 @@ def main():
|
|||
application.setOrganizationDomain('openlp.org')
|
||||
application.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
|
||||
application.setAttribute(QtCore.Qt.AA_DontCreateNativeWidgetSiblings, True)
|
||||
if no_custom_factor_rounding and hasattr(QtWidgets.QApplication, 'setHighDpiScaleFactorRoundingPolicy'):
|
||||
# TODO: Check won't be needed on PyQt6
|
||||
application.setHighDpiScaleFactorRoundingPolicy(QtCore.Qt.HighDpiScaleFactorRoundingPolicy.PassThrough)
|
||||
if is_win() and application.devicePixelRatio() > 1.0:
|
||||
# Increasing font size to match pixel ratio (Windows only)
|
||||
font = application.font()
|
||||
# font.setPointSizeF(font.pointSizeF() * application.devicePixelRatio())
|
||||
font.setPointSizeF(font.pointSizeF() * application.devicePixelRatio())
|
||||
application.setFont(font)
|
||||
if args.portable:
|
||||
application.setApplicationName('OpenLPPortable')
|
||||
Settings.setDefaultFormat(Settings.IniFormat)
|
||||
|
@ -447,7 +507,6 @@ def main():
|
|||
portable_path = resolve(portable_path)
|
||||
data_path = portable_path / 'Data'
|
||||
set_up_logging(portable_path / 'Other')
|
||||
set_up_web_engine_cache(portable_path / 'Other' / 'web_cache')
|
||||
log.info('Running portable')
|
||||
portable_settings_path = data_path / 'OpenLP.ini'
|
||||
# Make this our settings file
|
||||
|
@ -463,7 +522,6 @@ def main():
|
|||
else:
|
||||
application.setApplicationName('OpenLP')
|
||||
set_up_logging(AppLocation.get_directory(AppLocation.CacheDir))
|
||||
set_up_web_engine_cache(AppLocation.get_directory(AppLocation.CacheDir) / 'web_cache')
|
||||
# Set the libvlc environment variable if we're frozen
|
||||
if getattr(sys, 'frozen', False):
|
||||
# Path to libvlc and the plugins
|
||||
|
@ -482,6 +540,23 @@ def main():
|
|||
# Initialise the Registry
|
||||
Registry.create()
|
||||
settings = Settings()
|
||||
# Doing HiDPI adjustments that need to be done before QCoreApplication instantiation.
|
||||
hidpi_mode = settings.value('advanced/hidpi mode')
|
||||
apply_dpi_adjustments_stage_qt(hidpi_mode, qt_args)
|
||||
# Instantiating QCoreApplication
|
||||
application = QtWidgets.QApplication(qt_args)
|
||||
application.setOrganizationName('OpenLP')
|
||||
application.setOrganizationDomain('openlp.org')
|
||||
application.setAttribute(QtCore.Qt.AA_DontCreateNativeWidgetSiblings, True)
|
||||
# Doing HiDPI adjustments that need to be done after QCoreApplication instantiation.
|
||||
apply_dpi_adjustments_stage_application(hidpi_mode, application)
|
||||
settings.init_default_shortcuts()
|
||||
if args.portable:
|
||||
application.setApplicationName('OpenLPPortable')
|
||||
set_up_web_engine_cache(portable_path / 'Other' / 'web_cache')
|
||||
else:
|
||||
application.setApplicationName('OpenLP')
|
||||
set_up_web_engine_cache(AppLocation.get_directory(AppLocation.CacheDir) / 'web_cache')
|
||||
Registry().register('settings', settings)
|
||||
if settings.value('advanced/protect data directory'):
|
||||
# attempt to create a file lock
|
||||
|
|
|
@ -156,3 +156,12 @@ class SongFirstSlideMode(IntEnum):
|
|||
Default = 0 # No cover
|
||||
Songbook = 1
|
||||
Footer = 2
|
||||
|
||||
|
||||
@unique
|
||||
class HiDPIMode(IntEnum):
|
||||
Default = 0,
|
||||
# Legacy HiDPI mode is the default Qt behavior, without any OpenLP-specific HiDPI modifications
|
||||
Legacy = 1,
|
||||
# (Windows only) Make the OpenLP run unaware of any screen scaling.
|
||||
Windows_Unaware = 2
|
||||
|
|
|
@ -32,7 +32,7 @@ from tempfile import gettempdir
|
|||
from PyQt5 import QtCore, QtGui
|
||||
|
||||
from openlp.core.common import SlideLimits, ThemeLevel
|
||||
from openlp.core.common.enum import AlertLocation, BibleSearch, CustomSearch, ImageThemeMode, LayoutStyle, \
|
||||
from openlp.core.common.enum import AlertLocation, BibleSearch, CustomSearch, HiDPIMode, ImageThemeMode, LayoutStyle, \
|
||||
DisplayStyle, LanguageSelection, SongFirstSlideMode, SongSearch, PluginStatus
|
||||
from openlp.core.common.json import OpenLPJSONDecoder, OpenLPJSONEncoder, is_serializable
|
||||
from openlp.core.common.path import files_to_paths, str_to_path
|
||||
|
@ -200,6 +200,7 @@ class Settings(QtCore.QSettings):
|
|||
'advanced/search as type': True,
|
||||
'advanced/ui_theme_name': UiThemes.Automatic,
|
||||
'advanced/delete service item confirmation': False,
|
||||
'advanced/hidpi mode': HiDPIMode.Default,
|
||||
'alerts/font face': QtGui.QFont().family(),
|
||||
'alerts/font size': 40,
|
||||
'alerts/db type': 'sqlite',
|
||||
|
@ -528,6 +529,8 @@ class Settings(QtCore.QSettings):
|
|||
QtCore.QSettings.__init__(self, Settings.__file_path__, Settings.IniFormat)
|
||||
else:
|
||||
QtCore.QSettings.__init__(self, *args)
|
||||
|
||||
def init_default_shortcuts(self):
|
||||
# Add shortcuts here so QKeySequence has a QApplication instance to use.
|
||||
Settings.__default_settings__.update({
|
||||
'shortcuts/aboutItem': [QtGui.QKeySequence(QtCore.Qt.CTRL + QtCore.Qt.Key_F1)],
|
||||
|
|
|
@ -110,6 +110,22 @@ class AdvancedTab(SettingsTab):
|
|||
self.prefer_windowed_capture_check_box.setObjectName('prefer_windowed_capture_check_box')
|
||||
self.display_workaround_layout.addWidget(self.prefer_windowed_capture_check_box)
|
||||
self.left_layout.addWidget(self.display_workaround_group_box)
|
||||
# Misc Workarounds
|
||||
self.misc_workaround_group_box = QtWidgets.QGroupBox(self.left_column)
|
||||
self.misc_workaround_group_box.setObjectName('misc_workaround_group_box')
|
||||
self.misc_workaround_layout = QtWidgets.QVBoxLayout(self.misc_workaround_group_box)
|
||||
self.misc_workaround_layout.setObjectName('misc_workaround_layout')
|
||||
self.hidpi_mode_widget = QtWidgets.QWidget(self.misc_workaround_group_box)
|
||||
self.hidpi_mode_layout = QtWidgets.QHBoxLayout(self.hidpi_mode_widget)
|
||||
self.hidpi_mode_layout.setContentsMargins(0, 0, 0, 0)
|
||||
self.hidpi_mode_label = QtWidgets.QLabel(self.hidpi_mode_widget)
|
||||
self.hidpi_mode_combobox = QtWidgets.QComboBox(self.hidpi_mode_widget)
|
||||
self.hidpi_mode_combobox.addItems(['', '', ''])
|
||||
self.hidpi_mode_layout.addWidget(self.hidpi_mode_label)
|
||||
self.hidpi_mode_layout.addWidget(self.hidpi_mode_combobox)
|
||||
self.hidpi_mode_widget.setLayout(self.hidpi_mode_layout)
|
||||
self.misc_workaround_layout.addWidget(self.hidpi_mode_widget)
|
||||
self.left_layout.addWidget(self.misc_workaround_group_box)
|
||||
# Proxies
|
||||
self.proxy_widget = ProxyWidget(self.right_column)
|
||||
self.right_layout.addWidget(self.proxy_widget)
|
||||
|
@ -117,10 +133,11 @@ class AdvancedTab(SettingsTab):
|
|||
self.left_layout.addStretch()
|
||||
self.right_layout.addStretch()
|
||||
# Set up all the connections and things
|
||||
self.alternate_rows_check_box.toggled.connect(self.on_alternate_rows_check_box_toggled)
|
||||
self.alternate_rows_check_box.toggled.connect(self.on_restart_needed)
|
||||
self.data_directory_path_edit.pathChanged.connect(self.on_data_directory_path_edit_path_changed)
|
||||
self.data_directory_cancel_button.clicked.connect(self.on_data_directory_cancel_button_clicked)
|
||||
self.data_directory_copy_check_box.toggled.connect(self.on_data_directory_copy_check_box_toggled)
|
||||
self.hidpi_mode_combobox.currentIndexChanged.connect(self.on_restart_needed)
|
||||
|
||||
def retranslate_ui(self):
|
||||
"""
|
||||
|
@ -153,6 +170,11 @@ class AdvancedTab(SettingsTab):
|
|||
translate('OpenLP.AdvancedTab', 'Disable display transparency'))
|
||||
self.prefer_windowed_capture_check_box.setText(
|
||||
translate('OpenLP.AdvancedTab', 'Prefer window capture instead of screen capture'))
|
||||
self.misc_workaround_group_box.setTitle(translate('OpenLP.AdvancedTab', 'Miscellaneous Workarounds'))
|
||||
self.hidpi_mode_label.setText(translate('OpenLP.AdvancedTab', 'HiDPI Mode:'))
|
||||
self.hidpi_mode_combobox.setItemText(0, translate('OpenLP.AdvancedTab', 'Default'))
|
||||
self.hidpi_mode_combobox.setItemText(1, translate('OpenLP.AdvancedTab', 'Legacy'))
|
||||
self.hidpi_mode_combobox.setItemText(2, translate('OpenLP.AdvancedTab', 'DPI Unaware (Windows only)'))
|
||||
self.proxy_widget.retranslate_ui()
|
||||
|
||||
def load(self):
|
||||
|
@ -178,6 +200,7 @@ class AdvancedTab(SettingsTab):
|
|||
self.data_directory_new_label.hide()
|
||||
self.data_directory_path_edit.hide()
|
||||
self.data_directory_protect_check_box.setChecked(self.settings.value('advanced/protect data directory'))
|
||||
self.hidpi_mode_combobox.setCurrentIndex(self.settings.value('advanced/hidpi mode'))
|
||||
|
||||
def save(self):
|
||||
"""
|
||||
|
@ -193,6 +216,7 @@ class AdvancedTab(SettingsTab):
|
|||
self.settings_form.register_post_process('config_screen_changed')
|
||||
self.settings.setValue('advanced/alternate rows', self.alternate_rows_check_box.isChecked())
|
||||
self.settings.setValue('advanced/protect data directory', self.data_directory_protect_check_box.isChecked())
|
||||
self.settings.setValue('advanced/hidpi mode', self.hidpi_mode_combobox.currentIndex())
|
||||
self.proxy_widget.save()
|
||||
|
||||
def cancel(self):
|
||||
|
@ -287,13 +311,14 @@ class AdvancedTab(SettingsTab):
|
|||
self.data_directory_cancel_button.hide()
|
||||
self.new_data_directory_has_files_label.hide()
|
||||
|
||||
def on_alternate_rows_check_box_toggled(self, checked):
|
||||
def on_restart_needed(self, _):
|
||||
"""
|
||||
Notify user about required restart.
|
||||
|
||||
:param checked: The state of the check box (boolean).
|
||||
"""
|
||||
QtWidgets.QMessageBox.information(self, translate('OpenLP.AdvancedTab', 'Restart Required'),
|
||||
translate('OpenLP.AdvancedTab',
|
||||
'This change will only take effect once OpenLP '
|
||||
'has been restarted.'))
|
||||
if self.isVisible():
|
||||
QtWidgets.QMessageBox.information(self, translate('OpenLP.AdvancedTab', 'Restart Required'),
|
||||
translate('OpenLP.AdvancedTab',
|
||||
'This change will only take effect once OpenLP '
|
||||
'has been restarted.'))
|
||||
|
|
|
@ -43,6 +43,6 @@ class SplashScreen(QtWidgets.QSplashScreen):
|
|||
self.setObjectName('splashScreen')
|
||||
self.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
|
||||
splash_image = QtGui.QPixmap(':/graphics/openlp-splash-screen.png')
|
||||
splash_image.setDevicePixelRatio(self.devicePixelRatioF())
|
||||
self.setPixmap(splash_image)
|
||||
self.setMask(splash_image.mask())
|
||||
self.resize(370, 370)
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 166 KiB |
|
@ -75,6 +75,7 @@ def settings(qapp, registry):
|
|||
Settings().setDefaultFormat(QtCore.QSettings.Format.IniFormat)
|
||||
# Needed on windows to make sure a Settings object is available during the tests
|
||||
sets = Settings()
|
||||
sets.init_default_shortcuts()
|
||||
sets.setValue('themes/global theme', 'my_theme')
|
||||
registry.register('settings', sets)
|
||||
registry.register('settings_thread', sets)
|
||||
|
|
Loading…
Reference in New Issue