From 3e00c9491fd09a0eb5cde25af47d73d544d45cdf Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sun, 3 Nov 2024 12:01:18 -0500 Subject: [PATCH 1/2] Utils: Try to set monospace font size up to 6 times in SpyderApplication This prevents Spyder to get stuck in an infinite loop for monospace fonts that don't have an xHeight that matches the app font one in a close range of sizes around the app font size. --- spyder/utils/qthelpers.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/spyder/utils/qthelpers.py b/spyder/utils/qthelpers.py index da19778976b..97fb1762d35 100644 --- a/spyder/utils/qthelpers.py +++ b/spyder/utils/qthelpers.py @@ -835,18 +835,25 @@ def set_monospace_interface_font(self, app_font): plain_font.setPointSize(size) # Select a size that matches the app font one, so that the UI looks - # consistent. We only check three point sizes above and below the app - # font to avoid getting stuck in an infinite loop. + # consistent. + attempts = 0 monospace_size = size while ( + # Keep going until the xHeight's of both fonts match QFontMetrics(plain_font).xHeight() != x_height + # We only check three point sizes above and below the app font to + # avoid getting stuck in an infinite loop. and ((size - 4) < monospace_size < (size + 4)) + # Do this up to six times to not get stuck in an infinite loop. + # Fixes spyder-ide/spyder#22661 + and attempts < 6 ): if QFontMetrics(plain_font).xHeight() > x_height: monospace_size -= 1 else: monospace_size += 1 plain_font.setPointSize(monospace_size) + attempts += 1 # There are some fonts (e.g. MS Serif) for which it seems that Qt # can't detect their xHeight's as expected. So, we check below From 27c770107a4de4d566e2f5a26867a7e5489ff8df Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Sun, 3 Nov 2024 12:08:54 -0500 Subject: [PATCH 2/2] Utils: Add block comments to SpyderApplication Also, make _set_monospace_interface_font private because it's not used publicly. --- spyder/utils/qthelpers.py | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/spyder/utils/qthelpers.py b/spyder/utils/qthelpers.py index 97fb1762d35..983c71efd67 100644 --- a/spyder/utils/qthelpers.py +++ b/spyder/utils/qthelpers.py @@ -788,6 +788,8 @@ def __init__(self, *args): # This is filled at startup in spyder.app.utils.create_window self._main_window: QMainWindow = None + # ---- Qt methods + # ------------------------------------------------------------------------- def event(self, event): if sys.platform == 'darwin' and event.type() == QEvent.FileOpen: @@ -803,6 +805,8 @@ def event(self, event): return QApplication.event(self, event) + # ---- Public API + # ------------------------------------------------------------------------- def set_font(self): """Set font for the entire application.""" # This selects the system font by default @@ -821,10 +825,24 @@ def set_font(self): if size > 0: app_font.setPointSize(size) - self.set_monospace_interface_font(app_font) + self._set_monospace_interface_font(app_font) self.setFont(app_font) - def set_monospace_interface_font(self, app_font): + def get_mainwindow_position(self) -> QPoint: + """Get main window position.""" + return self._main_window.pos() + + def get_mainwindow_width(self) -> int: + """Get main window width.""" + return self._main_window.width() + + def get_mainwindow_height(self) -> int: + """Get main window height.""" + return self._main_window.height() + + # ---- Private API + # ------------------------------------------------------------------------- + def _set_monospace_interface_font(self, app_font): """ Set monospace interface font in our config system according to the app one. @@ -868,18 +886,6 @@ def set_monospace_interface_font(self, app_font): self.set_conf('monospace_app_font/size', monospace_size, section='appearance') - def get_mainwindow_position(self) -> QPoint: - """Get main window position.""" - return self._main_window.pos() - - def get_mainwindow_width(self) -> int: - """Get main window width.""" - return self._main_window.width() - - def get_mainwindow_height(self) -> int: - """Get main window height.""" - return self._main_window.height() - def restore_launchservices(): """Restore LaunchServices to the previous state"""