From 3e6d197c78526e5f548c4d6592a41541df8a72bb Mon Sep 17 00:00:00 2001 From: Lucas Brown Date: Fri, 2 May 2025 17:02:53 -0500 Subject: [PATCH 1/3] * Fixed fonts leaking out to host apps like Maya * Refactored where the font db is loaded * Reliably getting fonts out of the db by id * Fixed a bug with how the code editor number bar was dealing with fonts Fixes #284 --- nxt_editor/constants.py | 15 ++++++++++++-- nxt_editor/dockwidgets/code_editor.py | 26 +++++++++++++----------- nxt_editor/main_window.py | 29 +++++++++++---------------- 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/nxt_editor/constants.py b/nxt_editor/constants.py index 66a3d48..d98d763 100644 --- a/nxt_editor/constants.py +++ b/nxt_editor/constants.py @@ -1,7 +1,8 @@ # Builtin import os import json - +# External +from Qt import QtGui # Internal from nxt.constants import USER_DIR @@ -22,8 +23,18 @@ class EDITOR_VERSION(object): class FONTS(object): - DEFAULT_FAMILY = 'Roboto Mono' DEFAULT_SIZE = 10 + # Load fonts once + _font_db = QtGui.QFontDatabase() + _roboto_id = _font_db.addApplicationFont(":/fonts/fonts/Roboto/Roboto-Regular.ttf") + _mono_id = _font_db.addApplicationFont(":/fonts/fonts/RobotoMono/RobotoMono-Regular.ttf") + + # Get actual family names from font DB + ROBOTO_FAMILY = _font_db.applicationFontFamilies(_roboto_id)[0] if _roboto_id != -1 else "Sans Serif" + ROBOTO_MONO_FAMILY = _font_db.applicationFontFamilies(_mono_id)[0] if _mono_id != -1 else "Monospace" + + DEFAULT_FAMILY = ROBOTO_FAMILY + CODE_EDITOR_FAMILY = ROBOTO_MONO_FAMILY PREF_DIR_INT = EDITOR_VERSION.MAJOR diff --git a/nxt_editor/dockwidgets/code_editor.py b/nxt_editor/dockwidgets/code_editor.py index dd1b42d..d85f33c 100644 --- a/nxt_editor/dockwidgets/code_editor.py +++ b/nxt_editor/dockwidgets/code_editor.py @@ -16,6 +16,7 @@ from nxt import DATA_STATE, nxt_path from nxt.nxt_node import INTERNAL_ATTRS from nxt_editor.dockwidgets import syntax +from nxt_editor.constants import FONTS import nxt_editor logger = logging.getLogger(nxt_editor.LOGGER_NAME) @@ -72,7 +73,7 @@ def __init__(self, title='Code Editor', parent=None, minimum_width=500): self.details_layout.addLayout(self.name_layout) self.name_label = LabelEdit(parent=self.details_frame) - self.name_label.setFont(QtGui.QFont("Roboto", 14)) + self.name_label.setFont(QtGui.QFont(FONTS.DEFAULT_FAMILY, 14)) self.name_label.nameChangeRequested.connect(self.edit_name) self.name_layout.addWidget(self.name_label, 0, QtCore.Qt.AlignLeft) @@ -86,7 +87,7 @@ def __init__(self, title='Code Editor', parent=None, minimum_width=500): self.name_layout.addWidget(self.name_edit_button, 0, QtCore.Qt.AlignLeft) self.path_label = QtWidgets.QLabel(parent=self.details_frame) - self.path_label.setFont(QtGui.QFont("Roboto Mono", 8)) + self.path_label.setFont(QtGui.QFont(FONTS.CODE_EDITOR_FAMILY, 8)) self.path_label.setStyleSheet('color: grey') self.details_layout.addWidget(self.path_label) @@ -600,8 +601,8 @@ def __init__(self, show_line_numbers=True, highlight_current_line=True, self.setFocusPolicy(QtCore.Qt.ClickFocus) # font settings - self.font_size = 10 - self.font_family = 'Roboto Mono' + self.font_family = FONTS.CODE_EDITOR_FAMILY + self.font_size = FONTS.DEFAULT_SIZE self.setFont(QtGui.QFont(self.font_family, self.font_size)) self.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) @@ -754,7 +755,9 @@ def set_font_size(self, delta=0.0, default=False): self.font_size = 10 else: self.font_size += delta - self.setFont(QtGui.QFont(self.font_family, self.font_size)) + font = self.font() + font.setPointSize(self.font_size) + self.setFont(font) def update_previous_scroll_positions(self): self.prev_v_scroll_value = self.verticalScrollBar().value() @@ -1217,7 +1220,6 @@ def __init__(self, editor, color): self.editor = editor self.editor.blockCountChanged.connect(self.update_width) self.editor.updateRequest.connect(self.update_contents) - self.font = QtGui.QFont() self.color = QtGui.QColor(color) self.update_width() @@ -1231,7 +1233,7 @@ def paintEvent(self, event): changed_lines = [] # Iterate over all visible text blocks in the document. while block.isValid(): - self.font.setBold(False) + self.font().setBold(False) block_number = block.blockNumber() block_top = self.editor.blockBoundingGeometry(block).translated( self.editor.contentOffset()).top() @@ -1241,7 +1243,7 @@ def paintEvent(self, event): # We want the line number for the selected line to be bold. painter.setPen(QtGui.QColor(colors.LIGHTER_TEXT)) if block_number == self.editor.textCursor().blockNumber(): - self.font.setBold(True) + self.font().setBold(True) else: painter.setPen(colors.DEFAULT_TEXT) # Draw the line number right justified at the position of the line. @@ -1252,7 +1254,7 @@ def paintEvent(self, event): painter.fillRect(paint_rect, colors.UNSAVED) painter.setPen(colors.LIGHTEST_TEXT) changed_lines.remove(block_number) - painter.setFont(self.font) + painter.setFont(self.font()) text_rect = paint_rect.marginsAdded(QtCore.QMargins(0, 0, -4, 0)) painter.drawText(text_rect, QtCore.Qt.AlignRight, str(block_number + 1)) @@ -1288,8 +1290,8 @@ def update_contents(self, rect, scroll): if rect.contains(self.editor.viewport().rect()): font_size = self.editor.currentCharFormat().font().pointSize() - self.font.setPointSize(font_size) - self.font.setStyle(QtGui.QFont.StyleNormal) + self.font().setPointSize(font_size) + self.font().setStyle(QtGui.QFont.StyleNormal) self.update_width() @@ -1310,7 +1312,7 @@ def __init__(self, parent=None): def paintEvent(self, event): painter = QtGui.QPainter() painter.begin(self) - painter.setFont(QtGui.QFont("Roboto", 14)) + painter.setFont(QtGui.QFont(FONTS.CODE_EDITOR_FAMILY, 14)) font_metrics = QtGui.QFontMetrics(painter.font()) painter.setRenderHint(QtGui.QPainter.Antialiasing) # actual_display_state diff --git a/nxt_editor/main_window.py b/nxt_editor/main_window.py index a478e59..b437220 100644 --- a/nxt_editor/main_window.py +++ b/nxt_editor/main_window.py @@ -122,11 +122,7 @@ def __init__(self, filepath=None, parent=None, start_rpc=False): style_file.open(QtCore.QFile.ReadOnly) self.stylesheet = str(style_file.readAll()) self.setStyleSheet(self.stylesheet) - - # fonts - font_db = QtGui.QFontDatabase() - font_db.addApplicationFont(":fonts/fonts/RobotoMono/RobotoMono-Regular.ttf") - font_db.addApplicationFont(":fonts/fonts/Roboto/Roboto-Regular.ttf") + self.setFont(QtGui.QFont(FONTS.DEFAULT_FAMILY, FONTS.DEFAULT_SIZE)) # nxt object in charge of loaded graphs self.nxt = Session() @@ -365,24 +361,23 @@ def decrease_font_size(self): self._change_font_size(-1) def _change_font_size(self, delta, absolute=False, save=True): - app = QtWidgets.QApplication.instance() if absolute: font_size = delta else: - font_size = app.font().pointSize() + delta + font_size = self.font().pointSize() + delta self.font_size_changed.emit(delta) if save: user_dir.user_prefs[user_dir.USER_PREF.FONT_SIZE] = font_size - font = QtGui.QFont(FONTS.DEFAULT_FAMILY, font_size) - app.setFont(font) - - widgets_with_fonts = ["QMenuBar", "QTabWidget", "QMenu", "QTableView", - "QLineEdit", "QComboBox", "QLabel", - "QPushButton", "QTextEdit", "QWidget", - "QListWidget", "QTabelWidget", "QTreeWidget", - "QSpinBox", "QDoubleSpinBox", "QCheckBox"] - for widget in widgets_with_fonts: - app.setFont(font, widget) + main_font = self.font() + main_font.setPointSize(font_size) + self.setFont(main_font) + self.setUpdatesEnabled(False) + for widget in self.findChildren(QtWidgets.QWidget): + update_font = widget.font() + update_font.setPointSize(font_size) + widget.setFont(update_font) + self.setUpdatesEnabled(True) + QtWidgets.QApplication.processEvents() new_cb_stylesheet = ''' QCheckBox::indicator { From a651444a1c243221e91dfcabae101cf43532062f Mon Sep 17 00:00:00 2001 From: ImLucasBrown <54835354+imlucasbrown@users.noreply.github.com> Date: Sun, 4 May 2025 09:42:14 -0500 Subject: [PATCH 2/3] * Rebuilt the FONTS constant to be robust in cases where no QApp is running. --- nxt_editor/constants.py | 50 +++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/nxt_editor/constants.py b/nxt_editor/constants.py index d98d763..6ab2edd 100644 --- a/nxt_editor/constants.py +++ b/nxt_editor/constants.py @@ -2,7 +2,7 @@ import os import json # External -from Qt import QtGui +from Qt import QtGui, QtWidgets # Internal from nxt.constants import USER_DIR @@ -22,21 +22,47 @@ class EDITOR_VERSION(object): VERSION = VERSION_STR -class FONTS(object): - DEFAULT_SIZE = 10 - # Load fonts once - _font_db = QtGui.QFontDatabase() - _roboto_id = _font_db.addApplicationFont(":/fonts/fonts/Roboto/Roboto-Regular.ttf") - _mono_id = _font_db.addApplicationFont(":/fonts/fonts/RobotoMono/RobotoMono-Regular.ttf") +class _FontManager: + def __init__(self): + self._initialized = False + self._font_db = QtGui.QFontDatabase() + self.DEFAULT_SIZE = 10 + self._default_family = "Sans Serif" + self._code_family = "Monospace" - # Get actual family names from font DB - ROBOTO_FAMILY = _font_db.applicationFontFamilies(_roboto_id)[0] if _roboto_id != -1 else "Sans Serif" - ROBOTO_MONO_FAMILY = _font_db.applicationFontFamilies(_mono_id)[0] if _mono_id != -1 else "Monospace" + def initialize(self): + if self._initialized: + return + if not QtWidgets.QApplication.instance(): + return + roboto_id = self._font_db.addApplicationFont(":/fonts/fonts/Roboto/Roboto-Regular.ttf") + mono_id = self._font_db.addApplicationFont(":/fonts/fonts/RobotoMono/RobotoMono-Regular.ttf") - DEFAULT_FAMILY = ROBOTO_FAMILY - CODE_EDITOR_FAMILY = ROBOTO_MONO_FAMILY + if roboto_id != -1: + self._default_family = self._font_db.applicationFontFamilies(roboto_id)[0] + if mono_id != -1: + self._code_family = self._font_db.applicationFontFamilies(mono_id)[0] + self._initialized = True + @property + def DEFAULT_FAMILY(self): + self.initialize() + return self._default_family + + @property + def MONOSPACE(self): + self.initialize() + return self._code_family + + def default_font(self, size=None): + return QtGui.QFont(self.DEFAULT_FAMILY, size or self.DEFAULT_SIZE) + + def monospace_font(self, size=None): + return QtGui.QFont(self.MONOSPACE, size or self.DEFAULT_SIZE) + + +FONTS = _FontManager() PREF_DIR_INT = EDITOR_VERSION.MAJOR PREF_DIR_NAME = 'prefs' _pref_dir_num = str(PREF_DIR_INT) From d802ba9881ca65c02e44c9586373bef47062069c Mon Sep 17 00:00:00 2001 From: ImLucasBrown <54835354+imlucasbrown@users.noreply.github.com> Date: Sun, 4 May 2025 09:43:13 -0500 Subject: [PATCH 3/3] ... Refactored how fonts are accessed to be consistent and easier to maintain. --- nxt_editor/dockwidgets/code_editor.py | 7 +++---- nxt_editor/dockwidgets/hotkey_editor.py | 9 +++++---- nxt_editor/dockwidgets/output_log.py | 13 +++++++------ nxt_editor/dockwidgets/property_editor.py | 5 +++-- nxt_editor/main_window.py | 2 +- nxt_editor/node_graphics_item.py | 5 +++-- nxt_editor/stage_view.py | 5 +++-- 7 files changed, 25 insertions(+), 21 deletions(-) diff --git a/nxt_editor/dockwidgets/code_editor.py b/nxt_editor/dockwidgets/code_editor.py index d85f33c..037c548 100644 --- a/nxt_editor/dockwidgets/code_editor.py +++ b/nxt_editor/dockwidgets/code_editor.py @@ -87,7 +87,7 @@ def __init__(self, title='Code Editor', parent=None, minimum_width=500): self.name_layout.addWidget(self.name_edit_button, 0, QtCore.Qt.AlignLeft) self.path_label = QtWidgets.QLabel(parent=self.details_frame) - self.path_label.setFont(QtGui.QFont(FONTS.CODE_EDITOR_FAMILY, 8)) + self.path_label.setFont(QtGui.QFont(FONTS.MONOSPACE, 8)) self.path_label.setStyleSheet('color: grey') self.details_layout.addWidget(self.path_label) @@ -601,9 +601,8 @@ def __init__(self, show_line_numbers=True, highlight_current_line=True, self.setFocusPolicy(QtCore.Qt.ClickFocus) # font settings - self.font_family = FONTS.CODE_EDITOR_FAMILY self.font_size = FONTS.DEFAULT_SIZE - self.setFont(QtGui.QFont(self.font_family, self.font_size)) + self.setFont(FONTS.monospace_font(self.font_size)) self.setLineWrapMode(QtWidgets.QPlainTextEdit.NoWrap) # display settings @@ -1312,7 +1311,7 @@ def __init__(self, parent=None): def paintEvent(self, event): painter = QtGui.QPainter() painter.begin(self) - painter.setFont(QtGui.QFont(FONTS.CODE_EDITOR_FAMILY, 14)) + painter.setFont(QtGui.QFont(FONTS.MONOSPACE, 14)) font_metrics = QtGui.QFontMetrics(painter.font()) painter.setRenderHint(QtGui.QPainter.Antialiasing) # actual_display_state diff --git a/nxt_editor/dockwidgets/hotkey_editor.py b/nxt_editor/dockwidgets/hotkey_editor.py index d7bc6a7..62debc3 100644 --- a/nxt_editor/dockwidgets/hotkey_editor.py +++ b/nxt_editor/dockwidgets/hotkey_editor.py @@ -6,6 +6,7 @@ # Internal import nxt_editor +from nxt_editor.constants import FONTS from nxt_editor.dockwidgets.dock_widget_base import DockWidgetBase from nxt_editor import colors, dialogs @@ -28,14 +29,14 @@ 'other shortcut.

') TOOLTIP_STYLE = '''QToolTip { - font-family: Roboto Mono; + font-family: %s; background-color: #3E3E3E; border: 1px solid #232323; - }''' + }''' % (FONTS.MONOSPACE,) TABLE_STYLE = '''QTableView { - font-family: Roboto Mono; - }''' + font-family: %s; + }''' % (FONTS.MONOSPACE,) class HotkeyEditor(DockWidgetBase): diff --git a/nxt_editor/dockwidgets/output_log.py b/nxt_editor/dockwidgets/output_log.py index 0ec8508..95fb276 100644 --- a/nxt_editor/dockwidgets/output_log.py +++ b/nxt_editor/dockwidgets/output_log.py @@ -12,6 +12,7 @@ # Internal import nxt_editor from nxt_editor import user_dir +from nxt_editor.constants import FONTS from nxt_editor.dockwidgets.dock_widget_base import DockWidgetBase from nxt import nxt_log from nxt_editor import LoggingSignaler, colors @@ -99,7 +100,7 @@ def format(self, record): links = [] if links: text = self.format_links(text, links) - msg = '{}'.format(text) + msg = '{}'.format(FONTS.MONOSPACE, text) if multi: replacement = (msg, record.msg[1]) else: @@ -377,10 +378,10 @@ def write_rich_output(self, val, level=None): else: text = val color = colors.LOGGING_COLORS.get(level, 'white') - html = ''.format(color) + html = ''.format(FONTS.MONOSPACE, color) style = ("") + "pre {margin: 0; font-family: '%s';} " + "" % (FONTS.DEFAULT_FAMILY,)) text = style + ("
{}
".format(text)) html += text + '
' self.rich_output_textedit.insertHtml(html) @@ -431,7 +432,7 @@ def __init__(self, parent): self._parent = parent self.setStyleSheet(self.parent().parent().styleSheet()) self.setReadOnly(True) - self.setFont(QtGui.QFont('Roboto Mono', 10)) + self.setFont(QtGui.QFont(FONTS.MONOSPACE, 10)) def contextMenuEvent(self, event): menu = self.createStandardContextMenu() @@ -447,7 +448,7 @@ def __init__(self, parent): self.anchorClicked.connect(self.parent().link_clicked) self.setStyleSheet(self.parent().parent().styleSheet()) self.setOpenLinks(False) - self.setFont(QtGui.QFont('Roboto Mono', 10)) + self.setFont(QtGui.QFont(FONTS.MONOSPACE, 10)) def contextMenuEvent(self, event): menu = self.createStandardContextMenu() diff --git a/nxt_editor/dockwidgets/property_editor.py b/nxt_editor/dockwidgets/property_editor.py index 2c114e0..b492a5e 100644 --- a/nxt_editor/dockwidgets/property_editor.py +++ b/nxt_editor/dockwidgets/property_editor.py @@ -16,6 +16,7 @@ # Internal from nxt_editor import user_dir +from nxt_editor.constants import FONTS from nxt_editor.dockwidgets.dock_widget_base import DockWidgetBase from nxt_editor.pixmap_button import PixmapButton from nxt_editor.label_edit import LabelEdit @@ -1481,11 +1482,11 @@ def __init__(self, parent=None): } QToolTip { - font-family: Roboto Mono; + font-family: %s; color: white; border: 1px solid #3E3E3E } - ''' + ''' % (FONTS.MONOSPACE,) self.setStyleSheet(style) self._parent = parent self.node_path_delegate = NodePathBtnDelegate(self) diff --git a/nxt_editor/main_window.py b/nxt_editor/main_window.py index b437220..2328c76 100644 --- a/nxt_editor/main_window.py +++ b/nxt_editor/main_window.py @@ -122,7 +122,7 @@ def __init__(self, filepath=None, parent=None, start_rpc=False): style_file.open(QtCore.QFile.ReadOnly) self.stylesheet = str(style_file.readAll()) self.setStyleSheet(self.stylesheet) - self.setFont(QtGui.QFont(FONTS.DEFAULT_FAMILY, FONTS.DEFAULT_SIZE)) + self.setFont(FONTS.default_font()) # nxt object in charge of loaded graphs self.nxt = Session() diff --git a/nxt_editor/node_graphics_item.py b/nxt_editor/node_graphics_item.py index 128f4b7..845acb9 100644 --- a/nxt_editor/node_graphics_item.py +++ b/nxt_editor/node_graphics_item.py @@ -13,6 +13,7 @@ import nxt_editor from nxt import nxt_path, nxt_node from nxt.nxt_layer import LAYERS +from nxt_editor.constants import FONTS from . import colors from nxt.stage import INTERNAL_ATTRS from .label_edit import NameEditDialog @@ -57,8 +58,8 @@ def __init__(self, model, node_path, view): self.setAcceptHoverEvents(True) # draw settings - self.title_font = QtGui.QFont("Roboto Mono", 14) - self.attr_font = QtGui.QFont("Roboto Mono", 9) + self.title_font = QtGui.QFont(FONTS.MONOSPACE, 14) + self.attr_font = QtGui.QFont(FONTS.MONOSPACE, 9) self.title_rect_height = 39 self.attr_rect_height = 26 self.attr_rect_opacity = 0.9 diff --git a/nxt_editor/stage_view.py b/nxt_editor/stage_view.py index d6ad664..d0f8680 100644 --- a/nxt_editor/stage_view.py +++ b/nxt_editor/stage_view.py @@ -13,6 +13,7 @@ # Interal import nxt_editor from nxt import nxt_node, tokens +from nxt_editor.constants import FONTS from nxt_editor.node_graphics_item import NodeGraphicsItem, NodeGraphicsPlug from nxt_editor.connection_graphics_item import AttrConnectionGraphic from nxt_editor.dialogs import NxtWarningDialog @@ -265,14 +266,14 @@ def update_style_sheet(self): light_color.setHsv(color_obj.hsvHue(), color_obj.hsvSaturation() * 0.3, color_obj.value()) style = ''' QToolTip { - font-family: Roboto Mono; + font-family: %s; background-color: %s } QRubberBand { selection-background-color: %s } - ''' % (light_color.name(), layer_color) + ''' % (FONTS.DEFAULT_FAMILY, light_color.name(), layer_color) self.setStyleSheet(style) def clear(self):