diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index bfd0be9a..c50b327d 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -43,8 +43,8 @@ from PyQt5.QtCore import ( pyqtSignal, pyqtSlot ) from PyQt5.QtGui import ( - QColor, QCursor, QFont, QKeyEvent, QKeySequence, QMouseEvent, QPalette, - QPixmap, QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption + QColor, QCursor, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap, + QResizeEvent, QTextBlock, QTextCursor, QTextDocument, QTextOption ) from PyQt5.QtWidgets import ( QAction, QApplication, QFrame, QGridLayout, QHBoxLayout, QLabel, QLineEdit, @@ -329,10 +329,7 @@ class GuiDocEditor(QPlainTextEdit): SHARED.updateSpellCheckLanguage() # Set font - font = QFont() - font.setFamily(CONFIG.textFont) - font.setPointSize(CONFIG.textSize) - self._qDocument.setDefaultFont(font) + self.initFont() # Update highlighter settings self._qDocument.syntaxHighlighter.initHighlighter() @@ -382,6 +379,23 @@ class GuiDocEditor(QPlainTextEdit): return + def initFont(self) -> None: + """Set the font of the main widget and sub-widgets. This needs + special attention since there appears to be a bug in Qt 5.15.3. + See issues #1862 and #1875. + """ + font = self.font() + font.setFamily(CONFIG.textFont) + font.setPointSize(CONFIG.textSize) + self.setFont(font) + + # Reset sub-widget font to GUI font + self.docHeader.updateFont() + self.docFooter.updateFont() + self.docSearch.updateFont() + + return + def loadText(self, tHandle: str, tLine: int | None = None) -> bool: """Load text from a document into the editor. If we have an I/O error, we must handle this and clear the editor so that we don't @@ -2396,9 +2410,6 @@ class GuiDocEditSearch(QFrame): iSz = SHARED.theme.baseIconSize mPx = CONFIG.pxInt(6) - self.boxFont = SHARED.theme.guiFont - self.boxFont.setPointSizeF(0.9*SHARED.theme.fontPointSize) - self.setContentsMargins(0, 0, 0, 0) self.setAutoFillBackground(True) self.setFrameStyle(QFrame.Shape.StyledPanel | QFrame.Shadow.Plain) @@ -2410,12 +2421,10 @@ class GuiDocEditSearch(QFrame): # ========== self.searchBox = QLineEdit(self) - self.searchBox.setFont(self.boxFont) self.searchBox.setPlaceholderText(self.tr("Search for")) self.searchBox.returnPressed.connect(self._doSearch) self.replaceBox = QLineEdit(self) - self.replaceBox.setFont(self.boxFont) self.replaceBox.setPlaceholderText(self.tr("Replace with")) self.replaceBox.returnPressed.connect(self._doReplace) @@ -2425,12 +2434,9 @@ class GuiDocEditSearch(QFrame): self.searchOpt.setContentsMargins(0, 0, 0, 0) self.searchLabel = QLabel(self.tr("Search"), self) - self.searchLabel.setFont(self.boxFont) self.searchLabel.setIndent(CONFIG.pxInt(6)) self.resultLabel = QLabel("?/?", self) - self.resultLabel.setFont(self.boxFont) - self.resultLabel.setMinimumWidth(SHARED.theme.getTextWidth("?/?", self.boxFont)) self.toggleCase = QAction(self.tr("Case Sensitive"), self) self.toggleCase.setCheckable(True) @@ -2515,6 +2521,7 @@ class GuiDocEditSearch(QFrame): self.replaceButton.setVisible(False) self.adjustSize() + self.updateFont() self.updateTheme() logger.debug("Ready: GuiDocEditSearch") @@ -2598,7 +2605,9 @@ class GuiDocEditSearch(QFrame): numCount = f"{lim:n}+" if (resCount or 0) > lim else f"{resCount:n}" sCurrRes = "?" if currRes is None else str(currRes) sResCount = "?" if resCount is None else numCount - minWidth = SHARED.theme.getTextWidth(f"{sResCount}//{sResCount}", self.boxFont) + minWidth = SHARED.theme.getTextWidth( + f"{sResCount}//{sResCount}", SHARED.theme.guiFontSmall + ) self.resultLabel.setText(f"{sCurrRes}/{sResCount}") self.resultLabel.setMinimumWidth(minWidth) self.adjustSize() @@ -2609,6 +2618,18 @@ class GuiDocEditSearch(QFrame): # Methods ## + def updateFont(self) -> None: + """Update the font settings.""" + self.setFont(SHARED.theme.guiFont) + self.searchBox.setFont(SHARED.theme.guiFontSmall) + self.replaceBox.setFont(SHARED.theme.guiFontSmall) + self.searchLabel.setFont(SHARED.theme.guiFontSmall) + self.resultLabel.setFont(SHARED.theme.guiFontSmall) + self.resultLabel.setMinimumWidth( + SHARED.theme.getTextWidth("?/?", SHARED.theme.guiFontSmall) + ) + return + def updateTheme(self) -> None: """Update theme elements.""" qPalette = QApplication.palette() @@ -2793,10 +2814,6 @@ class GuiDocEditHeader(QWidget): self.itemTitle.setAlignment(QtAlignCenterTop) self.itemTitle.setFixedHeight(iPx) - lblFont = self.itemTitle.font() - lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize) - self.itemTitle.setFont(lblFont) - # Other Widgets self.outlineMenu = QMenu(self) @@ -2850,6 +2867,7 @@ class GuiDocEditHeader(QWidget): self.setContentsMargins(0, 0, 0, 0) self.setMinimumHeight(iPx + 2*mPx) + self.updateFont() self.updateTheme() logger.debug("Ready: GuiDocEditHeader") @@ -2888,6 +2906,12 @@ class GuiDocEditHeader(QWidget): logger.debug("Document outline updated in %.3f ms", 1000*(time() - tStart)) return + def updateFont(self) -> None: + """Update the font settings.""" + self.setFont(SHARED.theme.guiFont) + self.itemTitle.setFont(SHARED.theme.guiFontSmall) + return + def updateTheme(self) -> None: """Update theme elements.""" self.tbButton.setThemeIcon("menu") @@ -3001,9 +3025,6 @@ class GuiDocEditFooter(QWidget): bSp = CONFIG.pxInt(4) hSp = CONFIG.pxInt(6) - lblFont = self.font() - lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize) - # Cached Translations self._trLineCount = self.tr("Line: {0} ({1})") self._trWordCount = self.tr("Words: {0} ({1})") @@ -3026,7 +3047,6 @@ class GuiDocEditFooter(QWidget): self.statusText.setAutoFillBackground(True) self.statusText.setFixedHeight(fPx) self.statusText.setAlignment(QtAlignLeftTop) - self.statusText.setFont(lblFont) # Lines self.linesIcon = QLabel("", self) @@ -3041,7 +3061,6 @@ class GuiDocEditFooter(QWidget): self.linesText.setAutoFillBackground(True) self.linesText.setFixedHeight(fPx) self.linesText.setAlignment(QtAlignLeftTop) - self.linesText.setFont(lblFont) # Words self.wordsIcon = QLabel("", self) @@ -3056,7 +3075,6 @@ class GuiDocEditFooter(QWidget): self.wordsText.setAutoFillBackground(True) self.wordsText.setFixedHeight(fPx) self.wordsText.setAlignment(QtAlignLeftTop) - self.wordsText.setFont(lblFont) # Assemble Layout self.outerBox = QHBoxLayout() @@ -3079,6 +3097,7 @@ class GuiDocEditFooter(QWidget): self.setMinimumHeight(fPx + 2*mPx) # Fix the Colours + self.updateFont() self.updateTheme() # Initialise Info @@ -3092,6 +3111,14 @@ class GuiDocEditFooter(QWidget): # Methods ## + def updateFont(self) -> None: + """Update the font settings.""" + self.setFont(SHARED.theme.guiFont) + self.statusText.setFont(SHARED.theme.guiFontSmall) + self.linesText.setFont(SHARED.theme.guiFontSmall) + self.wordsText.setFont(SHARED.theme.guiFontSmall) + return + def updateTheme(self) -> None: """Update theme elements.""" iPx = round(0.9*SHARED.theme.baseIconHeight) diff --git a/novelwriter/gui/docviewer.py b/novelwriter/gui/docviewer.py index f5fbec42..afaeb366 100644 --- a/novelwriter/gui/docviewer.py +++ b/novelwriter/gui/docviewer.py @@ -31,10 +31,7 @@ import logging from enum import Enum from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot -from PyQt5.QtGui import ( - QCursor, QFont, QMouseEvent, QPalette, QResizeEvent, QTextCursor, - QTextOption -) +from PyQt5.QtGui import QCursor, QMouseEvent, QPalette, QResizeEvent, QTextCursor, QTextOption from PyQt5.QtWidgets import ( QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser, QToolButton, QWidget @@ -141,12 +138,7 @@ class GuiDocViewer(QTextBrowser): def initViewer(self) -> None: """Set editor settings from main config.""" self._makeStyleSheet() - - # Set Font - font = QFont() - font.setFamily(CONFIG.textFont) - font.setPointSize(CONFIG.textSize) - self.document().setDefaultFont(font) + self.initFont() # Set the widget colours to match syntax theme mainPalette = self.palette() @@ -189,6 +181,22 @@ class GuiDocViewer(QTextBrowser): return + def initFont(self) -> None: + """Set the font of the main widget and sub-widgets. This needs + special attention since there appears to be a bug in Qt 5.15.3. + See issues #1862 and #1875. + """ + font = self.font() + font.setFamily(CONFIG.textFont) + font.setPointSize(CONFIG.textSize) + self.setFont(font) + + # Reset sub-widget font to GUI font + self.docHeader.updateFont() + self.docFooter.updateFont() + + return + def loadText(self, tHandle: str, updateHistory: bool = True) -> bool: """Load text into the viewer from an item handle.""" if not SHARED.project.tree.checkType(tHandle, nwItemType.FILE): @@ -646,10 +654,6 @@ class GuiDocViewHeader(QWidget): self.itemTitle.setAlignment(QtAlignCenterTop) self.itemTitle.setFixedHeight(iPx) - lblFont = self.itemTitle.font() - lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize) - self.itemTitle.setFont(lblFont) - # Other Widgets self.outlineMenu = QMenu(self) @@ -700,7 +704,7 @@ class GuiDocViewHeader(QWidget): self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx) self.setMinimumHeight(iPx + 2*mPx) - # Fix the Colours + self.updateFont() self.updateTheme() logger.debug("Ready: GuiDocViewHeader") @@ -745,6 +749,12 @@ class GuiDocViewHeader(QWidget): self._docOutline = data return + def updateFont(self) -> None: + """Update the font settings.""" + self.setFont(SHARED.theme.guiFont) + self.itemTitle.setFont(SHARED.theme.guiFontSmall) + return + def updateTheme(self) -> None: """Update theme elements.""" self.outlineButton.setThemeIcon("list") @@ -886,11 +896,6 @@ class GuiDocViewFooter(QWidget): self.showSynopsis.toggled.connect(self._doToggleSynopsis) self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments")) - lblFont = self.font() - lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize) - self.showComments.setFont(lblFont) - self.showSynopsis.setFont(lblFont) - # Assemble Layout self.outerBox = QHBoxLayout() self.outerBox.addWidget(self.showHide, 0) @@ -906,7 +911,7 @@ class GuiDocViewFooter(QWidget): self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx) self.setMinimumHeight(iPx + 2*mPx) - # Fix the Colours + self.updateFont() self.updateTheme() logger.debug("Ready: GuiDocViewFooter") @@ -917,6 +922,13 @@ class GuiDocViewFooter(QWidget): # Methods ## + def updateFont(self) -> None: + """Update the font settings.""" + self.setFont(SHARED.theme.guiFont) + self.showComments.setFont(SHARED.theme.guiFontSmall) + self.showSynopsis.setFont(SHARED.theme.guiFontSmall) + return + def updateTheme(self) -> None: """Update theme elements.""" # Icons diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index c13283f4..6af30b8d 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -30,9 +30,7 @@ from math import ceil from pathlib import Path from PyQt5.QtCore import QSize, Qt -from PyQt5.QtGui import ( - QPalette, QColor, QIcon, QFont, QFontMetrics, QFontDatabase, QPixmap -) +from PyQt5.QtGui import QColor, QFont, QFontDatabase, QFontMetrics, QIcon, QPalette, QPixmap from PyQt5.QtWidgets import QApplication from novelwriter import CONFIG @@ -154,6 +152,8 @@ class GuiTheme: self.guiFont = QApplication.font() self.guiFontB = QApplication.font() self.guiFontB.setBold(True) + self.guiFontSmall = QApplication.font() + self.guiFontSmall.setPointSizeF(0.9*self.guiFont.pointSizeF()) qMetric = QFontMetrics(self.guiFont) fHeight = qMetric.height() diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index 17909a8d..12ca8212 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -31,7 +31,7 @@ from time import time from typing import TYPE_CHECKING from PyQt5.QtCore import Qt, QTimer, QUrl, pyqtSignal, pyqtSlot -from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QFont, QPalette, QResizeEvent +from PyQt5.QtGui import QCloseEvent, QColor, QCursor, QPalette, QResizeEvent from PyQt5.QtPrintSupport import QPrinter, QPrintPreviewDialog from PyQt5.QtWidgets import ( QAbstractItemView, QApplication, QDialog, QFormLayout, QGridLayout, @@ -761,7 +761,6 @@ class _PreviewWidget(QTextBrowser): self.setPalette(dPalette) self.setMinimumWidth(40*SHARED.theme.textNWidth) - self.setTextFont(CONFIG.textFont, CONFIG.textSize) self.setTabStopDistance(CONFIG.getTabWidth()) self.setOpenExternalLinks(False) @@ -802,6 +801,8 @@ class _PreviewWidget(QTextBrowser): self._updateDocMargins() self._updateBuildAge() + self.setTextFont(CONFIG.textFont, CONFIG.textSize) + # Age Timer self.ageTimer = QTimer(self) self.ageTimer.setInterval(10000) @@ -831,12 +832,17 @@ class _PreviewWidget(QTextBrowser): return def setTextFont(self, family: str, size: int) -> None: - """Set the text font properties.""" - if family: - font = QFont() + """Set the text font properties and then reset for sub-widgets. + This needs special attention since there appears to be a bug in + Qt 5.15.3. See issues #1862 and #1875. + """ + if family and size > 4: + font = self.font() font.setFamily(family) font.setPointSize(size) - self.document().setDefaultFont(font) + self.setFont(font) + self.buildProgress.setFont(SHARED.theme.guiFont) + self.ageLabel.setFont(SHARED.theme.guiFontSmall) return ##