From b66f7bf02fca3554d167675127de375e5e8163c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Wed, 7 Oct 2026 12:50:30 -0400 Subject: [PATCH 1/3] fix: SG-45066: Load annotation font list without blocking first activation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Text tool's font combo was filled in _TextOptionsPanel.__init__ by calling QFontDatabase.isSmoothlyScalable() on every installed family. Each call resolves all styles of the family, so building the dock froze RV the first time the beta annotate tool was opened: 650 to 870 ms measured on macOS with a warm font cache, and about 2 s reported. The cost grows with the number of installed fonts. The dock now builds without touching the font list. Once the secondary panel is shown, the list is filled in batches of about 1 ms from a QTimer, so the event loop keeps running between batches. The saved font family is selected when it is added, and a placeholder keeps the combo from auto-selecting the first font, so loading never emits font_family_changed or overwrites the saved setting. Signed-off-by: Cédrik Fuoco --- .../annotate_beta/annotate_beta_constants.py | 3 ++ .../annotate_beta/annotate_beta_widget.py | 51 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py b/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py index 5eeb9281d..bdefa49c3 100644 --- a/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py +++ b/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py @@ -48,6 +48,9 @@ class FontSize(StrEnum): DEFAULT_COLOR = "#ffdc00" DEFAULT_FONT_FAMILY = "Helvetica" +# Time spent filling the font list per event loop pass. +FONT_BATCH_SECONDS = 0.001 + SIZE_MIN = 1 SIZE_MAX = 100 DEFAULT_SIZE = 32 diff --git a/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py b/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py index 33b799632..e496c58c9 100644 --- a/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py +++ b/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py @@ -1,8 +1,10 @@ # Copyright (c) 2026 Autodesk, Inc. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 +import collections import os import sys +import time from dataclasses import dataclass from enum import Enum, auto @@ -541,13 +543,17 @@ def __init__(self, parent=None): layout.setContentsMargins(8, 8, 8, 8) layout.setSpacing(8) + self._pending_family = None + self._font_queue = None + self._font_timer = None + self._font_combo = _FontComboBox() self._font_combo.setToolTip("Font") self._font_combo.setItemDelegate(_FontNameDelegate(self._font_combo)) - for name in QtGui.QFontDatabase.families(): - if not name.startswith(".") and QtGui.QFontDatabase.isSmoothlyScalable(name): - self._font_combo.addItem(name) self._font_combo.setMaxVisibleItems(10) + # A placeholder keeps the first loaded font from being auto-selected. + self._font_combo.setPlaceholderText("Aa") + self._font_combo.currentTextChanged.connect(self._on_font_selected) self._font_combo.currentTextChanged.connect(self.font_family_changed) self._font_combo.view().setMinimumWidth(160) layout.addWidget(self._font_combo) @@ -573,12 +579,44 @@ def __init__(self, parent=None): layout.addStretch() + def start_loading_fonts(self): + """Fill the font combo in time-boxed batches so the GUI stays responsive.""" + if self._font_queue is not None: + return + self._font_queue = collections.deque( + name for name in QtGui.QFontDatabase.families() if not name.startswith(".") + ) + self._font_timer = QtCore.QTimer(self) + self._font_timer.timeout.connect(self._load_font_batch) + self._font_timer.start(0) + + def _load_font_batch(self): + # isSmoothlyScalable() is the slow call: it resolves every style of the family. + deadline = time.perf_counter() + constants.FONT_BATCH_SECONDS + combo = self._font_combo + with QtCore.QSignalBlocker(combo): + while self._font_queue and time.perf_counter() < deadline: + name = self._font_queue.popleft() + if QtGui.QFontDatabase.isSmoothlyScalable(name): + combo.addItem(name) + if name == self._pending_family: + combo.setCurrentIndex(combo.count() - 1) + if not self._font_queue: + self._font_timer.stop() + self._font_timer.deleteLater() + self._font_timer = None + + def _on_font_selected(self, name): + # Only user selections reach here: programmatic changes block signals. + self._pending_family = name + def set_font_family(self, name): + self._pending_family = name index = self._font_combo.findText(name) if index >= 0: with QtCore.QSignalBlocker(self._font_combo): self._font_combo.setCurrentIndex(index) - self._font_combo.sync_display_font(name) + self._font_combo.sync_display_font(name) def set_font_size(self, size): self._size_button.set_selection(size if self._size_button.has_item(size) else constants.FontSize.MEDIUM) @@ -660,6 +698,11 @@ def set_page_for_tool(self, tool): if page is not None: self._stack.setCurrentWidget(self._pages[page]) + def showEvent(self, event): + super().showEvent(event) + # Deferred so the dock paints before the font list starts loading. + QtCore.QTimer.singleShot(0, self._text_panel.start_loading_fonts) + def set_size(self, value): for panel in self._slider_panels: panel.set_size(value) From 3fc912862a5720401de098c7e9f1b9fc362ba04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Fri, 9 Oct 2026 14:03:47 -0400 Subject: [PATCH 2/3] fix: SG-45066: Remove redundant comment on FONT_BATCH_SECONDS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py b/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py index bdefa49c3..df5732214 100644 --- a/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py +++ b/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py @@ -48,7 +48,6 @@ class FontSize(StrEnum): DEFAULT_COLOR = "#ffdc00" DEFAULT_FONT_FAMILY = "Helvetica" -# Time spent filling the font list per event loop pass. FONT_BATCH_SECONDS = 0.001 SIZE_MIN = 1 From bcd2e253a28bc35c26949e4e03077046c0f43ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9drik=20Fuoco?= Date: Fri, 9 Oct 2026 14:08:59 -0400 Subject: [PATCH 3/3] fix: SG-45066: Rename FONT_BATCH_SECONDS to FONT_BATCH_TIME_BUDGET_SECONDS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Cédrik Fuoco --- .../rv-packages/annotate_beta/annotate_beta_constants.py | 2 +- src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py b/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py index df5732214..86dfca1ca 100644 --- a/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py +++ b/src/plugins/rv-packages/annotate_beta/annotate_beta_constants.py @@ -48,7 +48,7 @@ class FontSize(StrEnum): DEFAULT_COLOR = "#ffdc00" DEFAULT_FONT_FAMILY = "Helvetica" -FONT_BATCH_SECONDS = 0.001 +FONT_BATCH_TIME_BUDGET_SECONDS = 0.001 SIZE_MIN = 1 SIZE_MAX = 100 diff --git a/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py b/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py index e496c58c9..323138863 100644 --- a/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py +++ b/src/plugins/rv-packages/annotate_beta/annotate_beta_widget.py @@ -592,7 +592,7 @@ def start_loading_fonts(self): def _load_font_batch(self): # isSmoothlyScalable() is the slow call: it resolves every style of the family. - deadline = time.perf_counter() + constants.FONT_BATCH_SECONDS + deadline = time.perf_counter() + constants.FONT_BATCH_TIME_BUDGET_SECONDS combo = self._font_combo with QtCore.QSignalBlocker(combo): while self._font_queue and time.perf_counter() < deadline: