Allow full font style settings for GUI and editor (#1881)

This commit is contained in:
Veronica Berglyd Olsen
2024-05-20 18:37:42 +02:00
committed by GitHub
20 changed files with 193 additions and 232 deletions
+19 -20
View File
@@ -216,29 +216,28 @@ def main(sysArgs: list | None = None) -> GuiMain | None:
# Import GUI (after dependency checks), and launch
from novelwriter.guimain import GuiMain
if testMode:
nwGUI = GuiMain()
return nwGUI
# Only used for testing where the test framework creates the app
CONFIG.loadConfig()
return GuiMain()
else:
nwApp = QApplication([CONFIG.appName, (f"-style={qtStyle}")])
nwApp.setApplicationName(CONFIG.appName)
nwApp.setApplicationVersion(__version__)
nwApp.setOrganizationDomain(__domain__)
nwApp.setOrganizationName(__domain__)
nwApp.setDesktopFileName(CONFIG.appName)
app = QApplication([CONFIG.appName, (f"-style={qtStyle}")])
app.setApplicationName(CONFIG.appName)
app.setApplicationVersion(__version__)
app.setOrganizationDomain(__domain__)
app.setOrganizationName(__domain__)
app.setDesktopFileName(CONFIG.appName)
# Connect the exception handler before making the main GUI
sys.excepthook = exceptionHandler
# Connect the exception handler before making the main GUI
sys.excepthook = exceptionHandler
# Run Config steps that require the QApplication
CONFIG.initLocalisation(nwApp)
CONFIG.setTextFont(CONFIG.textFont, CONFIG.textSize) # Makes sure these are valid
# Run Config steps that require the QApplication
CONFIG.loadConfig()
CONFIG.initLocalisation(app)
# Launch main GUI
nwGUI = GuiMain()
nwGUI.postLaunchTasks(cmdOpen)
# Launch main GUI
nwGUI = GuiMain()
nwGUI.postLaunchTasks(cmdOpen)
sys.exit(nwApp.exec())
return None
sys.exit(app.exec())
+9 -1
View File
@@ -37,7 +37,7 @@ from urllib.parse import urljoin
from urllib.request import pathname2url
from PyQt5.QtCore import QCoreApplication, QUrl
from PyQt5.QtGui import QColor, QDesktopServices
from PyQt5.QtGui import QColor, QDesktopServices, QFont, QFontInfo
from novelwriter.constants import nwConst, nwLabels, nwUnicode, trConst
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
@@ -401,6 +401,14 @@ def cssCol(col: QColor, alpha: int | None = None) -> str:
return f"rgba({col.red()}, {col.green()}, {col.blue()}, {alpha or col.alpha()})"
def describeFont(font: QFont) -> str:
"""Describe a font in a way that can be displayed on the GUI."""
if isinstance(font, QFont):
info = QFontInfo(font)
return f"{font.family()} {info.styleName()} @ {font.pointSize()} pt"
return "Error"
##
# Encoder Functions
##
+95 -69
View File
@@ -36,10 +36,10 @@ from PyQt5.QtCore import (
PYQT_VERSION, PYQT_VERSION_STR, QT_VERSION, QT_VERSION_STR, QLibraryInfo,
QLocale, QStandardPaths, QSysInfo, QTranslator
)
from PyQt5.QtGui import QFontDatabase
from PyQt5.QtGui import QFont, QFontDatabase
from PyQt5.QtWidgets import QApplication
from novelwriter.common import NWConfigParser, checkInt, checkPath, formatTimeStamp
from novelwriter.common import NWConfigParser, checkInt, checkPath, describeFont, formatTimeStamp
from novelwriter.constants import nwFiles, nwUnicode
from novelwriter.error import formatException, logException
@@ -106,15 +106,14 @@ class Config:
self._recentObj = RecentProjects(self)
# General GUI Settings
self.guiLocale = self._qLocale.name()
self.guiTheme = "default" # GUI theme
self.guiSyntax = "default_light" # Syntax theme
self.guiFont = "" # Defaults to system default font in theme class
self.guiFontSize = 11 # Is overridden if system default is loaded
self.guiScale = 1.0 # Set automatically by Theme class
self.hideVScroll = False # Hide vertical scroll bars on main widgets
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
self.lastNotes = "0x0" # The latest release notes that have been shown
self.guiLocale = self._qLocale.name()
self.guiTheme = "default" # GUI theme
self.guiSyntax = "default_light" # Syntax theme
self.guiFont = QFont() # Main GUI font
self.guiScale = 1.0 # Set automatically by Theme class
self.hideVScroll = False # Hide vertical scroll bars on main widgets
self.hideHScroll = False # Hide horizontal scroll bars on main widgets
self.lastNotes = "0x0" # The latest release notes that have been shown
# Size Settings
self._mainWinSize = [1200, 650] # Last size of the main GUI window
@@ -132,43 +131,42 @@ class Config:
self.askBeforeBackup = True # Flag for asking before running automatic backup
# Text Editor Settings
self.textFont = "" # Editor font
self.textSize = 12 # Editor font size
self.textWidth = 700 # Editor text width
self.textMargin = 40 # Editor/viewer text margin
self.tabWidth = 40 # Editor tabulator width
self.textFont = QFont() # Editor font
self.textWidth = 700 # Editor text width
self.textMargin = 40 # Editor/viewer text margin
self.tabWidth = 40 # Editor tabulator width
self.focusWidth = 800 # Focus Mode text width
self.hideFocusFooter = False # Hide document footer in Focus Mode
self.showFullPath = True # Show full document path in editor header
self.autoSelect = True # Auto-select word when applying format with no selection
self.focusWidth = 800 # Focus Mode text width
self.hideFocusFooter = False # Hide document footer in Focus Mode
self.showFullPath = True # Show full document path in editor header
self.autoSelect = True # Auto-select word when applying format with no selection
self.doJustify = False # Justify text
self.showTabsNSpaces = False # Show tabs and spaces in editor
self.showLineEndings = False # Show line endings in editor
self.showMultiSpaces = True # Highlight multiple spaces in the text
self.doJustify = False # Justify text
self.showTabsNSpaces = False # Show tabs and spaces in editor
self.showLineEndings = False # Show line endings in editor
self.showMultiSpaces = True # Highlight multiple spaces in the text
self.doReplace = True # Enable auto-replace as you type
self.doReplaceSQuote = True # Smart single quotes
self.doReplaceDQuote = True # Smart double quotes
self.doReplaceDash = True # Replace multiple hyphens with dashes
self.doReplaceDots = True # Replace three dots with ellipsis
self.doReplace = True # Enable auto-replace as you type
self.doReplaceSQuote = True # Smart single quotes
self.doReplaceDQuote = True # Smart double quotes
self.doReplaceDash = True # Replace multiple hyphens with dashes
self.doReplaceDots = True # Replace three dots with ellipsis
self.autoScroll = False # Typewriter-like scrolling
self.autoScrollPos = 30 # Start point for typewriter-like scrolling
self.scrollPastEnd = True # Scroll past end of document, and centre cursor
self.autoScroll = False # Typewriter-like scrolling
self.autoScrollPos = 30 # Start point for typewriter-like scrolling
self.scrollPastEnd = True # Scroll past end of document, and centre cursor
self.dialogStyle = 2 # Quote type to use for dialogue
self.allowOpenDial = True # Allow open-ended dialogue quotes
self.narratorBreak = "" # Symbol to use for narrator break
self.dialogLine = "" # Symbol to use for dialogue line
self.altDialogOpen = "" # Alternative dialog symbol, open
self.altDialogClose = "" # Alternative dialog symbol, close
self.highlightEmph = True # Add colour to text emphasis
self.dialogStyle = 2 # Quote type to use for dialogue
self.allowOpenDial = True # Allow open-ended dialogue quotes
self.narratorBreak = "" # Symbol to use for narrator break
self.dialogLine = "" # Symbol to use for dialogue line
self.altDialogOpen = "" # Alternative dialog symbol, open
self.altDialogClose = "" # Alternative dialog symbol, close
self.highlightEmph = True # Add colour to text emphasis
self.stopWhenIdle = True # Stop the status bar clock when the user is idle
self.userIdleTime = 300 # Time of inactivity to consider user idle
self.incNotesWCount = True # The status bar word count includes notes
self.stopWhenIdle = True # Stop the status bar clock when the user is idle
self.userIdleTime = 300 # Time of inactivity to consider user idle
self.incNotesWCount = True # The status bar word count includes notes
# User-Selected Symbol Settings
self.fmtApostrophe = nwUnicode.U_RSQUO
@@ -362,23 +360,53 @@ class Config:
self._backupPath = checkPath(path, self._backPath)
return
def setTextFont(self, family: str | None, pointSize: int = 12) -> None:
def setGuiFont(self, value: QFont | str | None) -> None:
"""Update the GUI's font style from settings."""
if isinstance(value, QFont):
self.guiFont = value
elif value and isinstance(value, str):
self.guiFont = QFont()
self.guiFont.fromString(value)
else:
font = QFont()
fontDB = QFontDatabase()
if self.osWindows and "Arial" in fontDB.families():
# On Windows we default to Arial if possible
font.setFamily("Arial")
font.setPointSize(10)
else:
font = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont)
self.guiFont = font
logger.debug("GUI font set to: %s", describeFont(font))
QApplication.setFont(self.guiFont)
return
def setTextFont(self, value: QFont | str | None) -> None:
"""Set the text font if it exists. If it doesn't, or is None,
set to default font.
"""
fontDB = QFontDatabase()
fontFam = fontDB.families()
self.textSize = pointSize
if family is None or family not in fontFam:
logger.warning("Unknown font '%s'", family)
if self.osWindows and "Arial" in fontFam:
self.textFont = "Arial"
elif self.osDarwin and "Helvetica" in fontFam:
self.textFont = "Helvetica"
else:
self.textFont = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont).family()
if isinstance(value, QFont):
self.textFont = value
elif value and isinstance(value, str):
self.textFont = QFont()
self.textFont.fromString(value)
else:
self.textFont = family
fontDB = QFontDatabase()
fontFam = fontDB.families()
if self.osWindows and "Arial" in fontFam:
font = QFont()
font.setFamily("Arial")
font.setPointSize(12)
elif self.osDarwin and "Helvetica" in fontFam:
font = QFont()
font.setFamily("Helvetica")
font.setPointSize(12)
else:
font = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont)
self.textFont = font
logger.debug("Text font set to: %s", describeFont(font))
return
##
@@ -502,12 +530,6 @@ class Config:
(self._dataPath / "syntax").mkdir(exist_ok=True)
(self._dataPath / "themes").mkdir(exist_ok=True)
# Check if config file exists, and load it. If not, we save defaults
if (self._confPath / nwFiles.CONF_FILE).is_file():
self.loadConfig()
else:
self.saveConfig()
self._recentObj.loadCache()
self._checkOptionalPackages()
@@ -548,6 +570,14 @@ class Config:
conf = NWConfigParser()
cnfPath = self._confPath / nwFiles.CONF_FILE
if not cnfPath.exists():
# Initial file, so we just create one from defaults
self.setGuiFont(None)
self.setTextFont(None)
self.saveConfig()
return True
try:
with open(cnfPath, mode="r", encoding="utf-8") as inFile:
conf.read_file(inFile)
@@ -561,10 +591,9 @@ class Config:
# Main
sec = "Main"
self.setGuiFont(conf.rdStr(sec, "font", ""))
self.guiTheme = conf.rdStr(sec, "theme", self.guiTheme)
self.guiSyntax = conf.rdStr(sec, "syntax", self.guiSyntax)
self.guiFont = conf.rdStr(sec, "font", self.guiFont)
self.guiFontSize = conf.rdInt(sec, "fontsize", self.guiFontSize)
self.guiLocale = conf.rdStr(sec, "localisation", self.guiLocale)
self.hideVScroll = conf.rdBool(sec, "hidevscroll", self.hideVScroll)
self.hideHScroll = conf.rdBool(sec, "hidehscroll", self.hideHScroll)
@@ -591,8 +620,7 @@ class Config:
# Editor
sec = "Editor"
self.textFont = conf.rdStr(sec, "textfont", self.textFont)
self.textSize = conf.rdInt(sec, "textsize", self.textSize)
self.setTextFont(conf.rdStr(sec, "textfont", ""))
self.textWidth = conf.rdInt(sec, "width", self.textWidth)
self.textMargin = conf.rdInt(sec, "margin", self.textMargin)
self.tabWidth = conf.rdInt(sec, "tabwidth", self.tabWidth)
@@ -672,10 +700,9 @@ class Config:
}
conf["Main"] = {
"font": self.guiFont.toString(),
"theme": str(self.guiTheme),
"syntax": str(self.guiSyntax),
"font": str(self.guiFont),
"fontsize": str(self.guiFontSize),
"localisation": str(self.guiLocale),
"hidevscroll": str(self.hideVScroll),
"hidehscroll": str(self.hideHScroll),
@@ -702,8 +729,7 @@ class Config:
}
conf["Editor"] = {
"textfont": str(self.textFont),
"textsize": str(self.textSize),
"textfont": self.textFont.toString(),
"width": str(self.textWidth),
"margin": str(self.textMargin),
"tabwidth": str(self.tabWidth),
+1 -1
View File
@@ -76,7 +76,7 @@ SETTINGS_TEMPLATE = {
"text.includeBodyText": (bool, True),
"text.ignoredKeywords": (str, ""),
"text.addNoteHeadings": (bool, True),
"format.textFont": (str, CONFIG.textFont),
"format.textFont": (str, CONFIG.textFont.family()),
"format.textSize": (int, 12),
"format.lineHeight": (float, 1.15, 0.75, 3.0),
"format.justifyText": (bool, False),
+1 -1
View File
@@ -288,7 +288,7 @@ class NWBuildDocument:
textFont = self._build.getStr("format.textFont")
textSize = self._build.getInt("format.textSize")
fontFamily = textFont or CONFIG.textFont
fontFamily = textFont or CONFIG.textFont.family()
bldFont = QFont(fontFamily, textSize)
fontInfo = QFontInfo(bldFont)
textFixed = fontInfo.fixedPitch()
+26 -48
View File
@@ -27,7 +27,7 @@ from __future__ import annotations
import logging
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QCloseEvent, QFont, QKeyEvent, QKeySequence
from PyQt5.QtGui import QCloseEvent, QKeyEvent, QKeySequence
from PyQt5.QtWidgets import (
QAbstractButton, QApplication, QCompleter, QDialog, QDialogButtonBox,
QFileDialog, QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QVBoxLayout,
@@ -35,6 +35,7 @@ from PyQt5.QtWidgets import (
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import describeFont
from novelwriter.constants import nwConst, nwUnicode
from novelwriter.dialogs.quotes import GuiQuoteSelect
from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
@@ -135,6 +136,11 @@ class GuiPreferences(QDialog):
iSz = SHARED.theme.baseIconSize
boxFixed = 5*SHARED.theme.textNWidth
minWidth = CONFIG.pxInt(200)
fontWidth = CONFIG.pxInt(162)
# Temporary Variables
self._guiFont = CONFIG.guiFont
self._textFont = CONFIG.textFont
# Label
self.sidebar.addLabel(self.tr("General"))
@@ -174,27 +180,17 @@ class GuiPreferences(QDialog):
# Application Font Family
self.guiFont = QLineEdit(self)
self.guiFont.setReadOnly(True)
self.guiFont.setMinimumWidth(CONFIG.pxInt(162))
self.guiFont.setText(CONFIG.guiFont)
self.guiFont.setMinimumWidth(fontWidth)
self.guiFont.setText(describeFont(self._guiFont))
self.guiFont.setCursorPosition(0)
self.guiFontButton = NIconToolButton(self, iSz, "more")
self.guiFontButton.clicked.connect(self._selectGuiFont)
self.mainForm.addRow(
self.tr("Application font family"), self.guiFont,
self.tr("Application font"), self.guiFont,
self.tr("Requires restart to take effect."), stretch=(3, 2),
button=self.guiFontButton
)
# Application Font Size
self.guiFontSize = NSpinBox(self)
self.guiFontSize.setMinimum(8)
self.guiFontSize.setMaximum(60)
self.guiFontSize.setSingleStep(1)
self.guiFontSize.setValue(CONFIG.guiFontSize)
self.mainForm.addRow(
self.tr("Application font size"), self.guiFontSize,
self.tr("Requires restart to take effect."), unit=self.tr("pt")
)
# Vertical Scrollbars
self.hideVScroll = NSwitch(self)
self.hideVScroll.setChecked(CONFIG.hideVScroll)
@@ -234,27 +230,17 @@ class GuiPreferences(QDialog):
# Document Font Family
self.textFont = QLineEdit(self)
self.textFont.setReadOnly(True)
self.textFont.setMinimumWidth(CONFIG.pxInt(162))
self.textFont.setText(CONFIG.textFont)
self.textFont.setMinimumWidth(fontWidth)
self.textFont.setText(describeFont(CONFIG.textFont))
self.textFont.setCursorPosition(0)
self.textFontButton = NIconToolButton(self, iSz, "more")
self.textFontButton.clicked.connect(self._selectTextFont)
self.mainForm.addRow(
self.tr("Document font family"), self.textFont,
self.tr("Document font"), self.textFont,
self.tr("Applies to both document editor and viewer."), stretch=(3, 2),
button=self.textFontButton
)
# Document Font Size
self.textSize = NSpinBox(self)
self.textSize.setMinimum(8)
self.textSize.setMaximum(60)
self.textSize.setSingleStep(1)
self.textSize.setValue(CONFIG.textSize)
self.mainForm.addRow(
self.tr("Document font size"), self.textSize,
self.tr("Applies to both document editor and viewer."), unit=self.tr("pt")
)
# Emphasise Labels
self.emphLabels = NSwitch(self)
self.emphLabels.setChecked(CONFIG.emphLabels)
@@ -818,25 +804,21 @@ class GuiPreferences(QDialog):
@pyqtSlot()
def _selectGuiFont(self) -> None:
"""Open the QFontDialog and set a font for the font style."""
current = QFont()
current.setFamily(CONFIG.guiFont)
current.setPointSize(CONFIG.guiFontSize)
font, status = QFontDialog.getFont(current, self)
font, status = QFontDialog.getFont(self._guiFont, self)
if status:
self.guiFont.setText(font.family())
self.guiFontSize.setValue(font.pointSize())
self.guiFont.setText(describeFont(font))
self.guiFont.setCursorPosition(0)
self._guiFont = font
return
@pyqtSlot()
def _selectTextFont(self) -> None:
"""Open the QFontDialog and set a font for the font style."""
current = QFont()
current.setFamily(CONFIG.textFont)
current.setPointSize(CONFIG.textSize)
font, status = QFontDialog.getFont(current, self)
font, status = QFontDialog.getFont(CONFIG.textFont, self)
if status:
self.textFont.setText(font.family())
self.textSize.setValue(font.pointSize())
self.textFont.setText(describeFont(font))
self.textFont.setCursorPosition(0)
self._textFont = font
return
@pyqtSlot()
@@ -892,20 +874,16 @@ class GuiPreferences(QDialog):
# Appearance
guiLocale = self.guiLocale.currentData()
guiTheme = self.guiTheme.currentData()
guiFont = self.guiFont.text()
guiFontSize = self.guiFontSize.value()
updateTheme |= CONFIG.guiTheme != guiTheme
needsRestart |= CONFIG.guiLocale != guiLocale
needsRestart |= CONFIG.guiFont != guiFont
needsRestart |= CONFIG.guiFontSize != guiFontSize
needsRestart |= CONFIG.guiFont != self._guiFont
CONFIG.guiLocale = guiLocale
CONFIG.guiTheme = guiTheme
CONFIG.guiFont = guiFont
CONFIG.guiFontSize = guiFontSize
CONFIG.hideVScroll = self.hideVScroll.isChecked()
CONFIG.hideHScroll = self.hideHScroll.isChecked()
CONFIG.setGuiFont(self._guiFont)
# Document Style
guiSyntax = self.guiSyntax.currentData()
@@ -918,7 +896,7 @@ class GuiPreferences(QDialog):
CONFIG.emphLabels = emphLabels
CONFIG.showFullPath = self.showFullPath.isChecked()
CONFIG.incNotesWCount = self.incNotesWCount.isChecked()
CONFIG.setTextFont(self.textFont.text(), self.textSize.value())
CONFIG.setTextFont(self._textFont)
# Auto Save
CONFIG.autoSaveDoc = self.autoSaveDoc.value()
+1 -7
View File
@@ -377,16 +377,10 @@ class GuiDocEditor(QPlainTextEdit):
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.setFont(CONFIG.textFont)
self.docHeader.updateFont()
self.docFooter.updateFont()
self.docSearch.updateFont()
return
def loadText(self, tHandle: str, tLine: int | None = None) -> bool:
+1 -1
View File
@@ -474,7 +474,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
charFormat.setBackground(QBrush(color, Qt.BrushStyle.SolidPattern))
if size:
charFormat.setFontPointSize(round(size*CONFIG.textSize))
charFormat.setFontPointSize(round(size*CONFIG.textFont.pointSize()))
self._hStyles[name] = charFormat
+1 -7
View File
@@ -186,15 +186,9 @@ class GuiDocViewer(QTextBrowser):
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.setFont(CONFIG.textFont)
self.docHeader.updateFont()
self.docFooter.updateFont()
return
def loadText(self, tHandle: str, updateHistory: bool = True) -> bool:
-24
View File
@@ -114,9 +114,6 @@ class GuiTheme:
# Class Setup
# ===========
# Init GUI Font
self._setGuiFont()
# Load Themes
self._guiPalette = QPalette()
self._themeList: list[tuple[str, str]] = []
@@ -411,27 +408,6 @@ class GuiTheme:
self.errorText = QColor(255, 0, 0)
return
def _setGuiFont(self) -> None:
"""Update the GUI's font style from settings."""
font = QFont()
fontDB = QFontDatabase()
if CONFIG.guiFont not in fontDB.families():
if CONFIG.osWindows and "Arial" in fontDB.families():
# On Windows we default to Arial if possible
font.setFamily("Arial")
font.setPointSize(10)
else:
font = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont)
CONFIG.guiFont = font.family()
CONFIG.guiFontSize = font.pointSize()
else:
font.setFamily(CONFIG.guiFont)
font.setPointSize(CONFIG.guiFontSize)
QApplication.setFont(font)
return
def _listConf(self, targetDict: dict, checkDir: Path) -> bool:
"""Scan for theme config files and populate the dictionary."""
if not checkDir.is_dir():
+1 -1
View File
@@ -787,7 +787,7 @@ class _PreviewWidget(QTextBrowser):
self._updateDocMargins()
self._updateBuildAge()
self.setTextFont(CONFIG.textFont, CONFIG.textSize)
self.setTextFont(CONFIG.textFont.family(), CONFIG.textFont.pointSize())
# Age Timer
self.ageTimer = QTimer(self)
+1 -1
View File
@@ -1175,7 +1175,7 @@ class _FormatTab(NScrollableForm):
"""Populate the widgets."""
textFont = self._build.getStr("format.textFont")
if not textFont:
textFont = str(CONFIG.textFont)
textFont = str(CONFIG.textFont.family())
self.textFont.setText(textFont)
self.textSize.setValue(self._build.getInt("format.textSize"))
+1
View File
@@ -52,6 +52,7 @@ def resetConfigVars():
"""
CONFIG.setLastPath(_TMP_ROOT)
CONFIG.setBackupPath(_TMP_ROOT)
CONFIG.setGuiFont(None)
CONFIG.setTextFont(None)
CONFIG._homePath = _TMP_ROOT
CONFIG.guiLocale = "en_GB"
+2 -4
View File
@@ -1,11 +1,10 @@
[Meta]
timestamp = 2024-05-13 15:59:59
timestamp = 2024-05-20 16:48:20
[Main]
font =
theme = default
syntax = default_light
font =
fontsize = 11
localisation = en_GB
hidevscroll = False
hidehscroll = False
@@ -30,7 +29,6 @@ askbeforebackup = True
[Editor]
textfont =
textsize = 12
width = 700
margin = 40
tabwidth = 40
+16 -7
View File
@@ -28,16 +28,16 @@ from xml.etree import ElementTree as ET
import pytest
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QColor, QDesktopServices
from PyQt5.QtGui import QColor, QDesktopServices, QFontDatabase
from novelwriter.common import (
NWConfigParser, checkBool, checkFloat, checkInt, checkIntTuple, checkPath,
checkString, checkStringNone, checkUuid, cssCol, elide, formatFileFilter,
formatInt, formatTime, formatTimeStamp, formatVersion, fuzzyTime,
getFileSize, hexToInt, isHandle, isItemClass, isItemLayout, isItemType,
isListInstance, isTitleTag, jsonEncode, makeFileNameSafe, minmax,
numberToRoman, openExternalPath, readTextFile, simplified, transferCase,
xmlIndent, yesNo
checkString, checkStringNone, checkUuid, cssCol, describeFont, elide,
formatFileFilter, formatInt, formatTime, formatTimeStamp, formatVersion,
fuzzyTime, getFileSize, hexToInt, isHandle, isItemClass, isItemLayout,
isItemType, isListInstance, isTitleTag, jsonEncode, makeFileNameSafe,
minmax, numberToRoman, openExternalPath, readTextFile, simplified,
transferCase, xmlIndent, yesNo
)
from tests.mocked import causeOSError
@@ -487,6 +487,15 @@ def testBaseCommon_cssCol():
assert cssCol(QColor(10, 20, 30, 40)) == "rgba(10, 20, 30, 40)"
@pytest.mark.base
def testBaseCommon_describeFont():
"""Test the describeFont function."""
fontDB = QFontDatabase()
font = fontDB.systemFont(QFontDatabase.SystemFont.GeneralFont)
assert font.family() in describeFont(font)
assert describeFont(None) == "Error" # type: ignore
@pytest.mark.base
def testBaseCommon_jsonEncode():
"""Test the jsonEncode function."""
+7 -2
View File
@@ -103,15 +103,19 @@ def testBaseConfig_InitLoadSave(monkeypatch, fncPath, tstPaths):
if confFile.is_file():
confFile.unlink()
# Running init against a new oath should write a new config file
# Running init + load against a new path should write a new config file
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
assert tstConf._confPath == fncPath
assert tstConf._dataPath == fncPath
tstConf.loadConfig()
assert confFile.exists()
# Check that we have a default file
copyfile(confFile, testFile)
ignore = ("timestamp", "lastnotes", "localisation", "lastpath", "backuppath")
ignore = (
"timestamp", "lastnotes", "localisation",
"lastpath", "backuppath", "font", "textfont"
)
assert cmpFiles(testFile, compFile, ignoreStart=ignore)
tstConf.errorText() # This clears the error cache
@@ -136,6 +140,7 @@ def testBaseConfig_InitLoadSave(monkeypatch, fncPath, tstPaths):
newConf = Config()
newConf.initConfig(confPath=fncPath, dataPath=fncPath)
newConf.loadConfig()
assert newConf.guiTheme == "foo"
assert newConf.guiSyntax == "bar"
+7 -13
View File
@@ -23,7 +23,7 @@ from __future__ import annotations
import pytest
from PyQt5.QtCore import QEvent, Qt
from PyQt5.QtGui import QFontDatabase, QKeyEvent
from PyQt5.QtGui import QFont, QFontDatabase, QKeyEvent
from PyQt5.QtWidgets import QAction, QFileDialog, QFontDialog
from novelwriter import CONFIG, SHARED
@@ -173,32 +173,28 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, tstPaths):
prefs.guiLocale.setCurrentIndex(prefs.guiLocale.findData("en_US"))
prefs.guiTheme.setCurrentIndex(prefs.guiTheme.findData("default_dark"))
with monkeypatch.context() as mp:
mp.setattr(QFontDialog, "getFont", lambda *a: (MockFont(), True))
mp.setattr(QFontDialog, "getFont", lambda *a: (QFont(), True))
prefs.guiFontButton.click()
prefs.guiFontSize.stepDown() # Should change it to 41
prefs.hideVScroll.setChecked(True)
prefs.hideHScroll.setChecked(True)
assert CONFIG.guiLocale != "en_US"
assert CONFIG.guiTheme != "default_dark"
assert CONFIG.guiFont != "TestFont"
assert CONFIG.guiFontSize < 42
assert CONFIG.guiFont.family() != ""
assert CONFIG.hideVScroll is False
assert CONFIG.hideHScroll is False
# Document Style
prefs.guiSyntax.setCurrentIndex(prefs.guiSyntax.findData("default_dark"))
with monkeypatch.context() as mp:
mp.setattr(QFontDialog, "getFont", lambda *a: (MockFont(), True))
mp.setattr(QFontDialog, "getFont", lambda *a: (QFont(), True))
prefs.textFontButton.click()
prefs.textSize.stepDown() # Should change it to 41
prefs.emphLabels.setChecked(False)
prefs.showFullPath.setChecked(False)
prefs.incNotesWCount.setChecked(False)
assert CONFIG.guiSyntax != "default_dark"
assert CONFIG.textFont != "testFont"
assert CONFIG.textSize < 42
assert CONFIG.textFont.family() != ""
assert CONFIG.emphLabels is True
assert CONFIG.showFullPath is True
assert CONFIG.incNotesWCount is True
@@ -341,15 +337,13 @@ def testDlgPreferences_Settings(qtbot, monkeypatch, nwGUI, tstPaths):
# Appearance
assert CONFIG.guiLocale == "en_US"
assert CONFIG.guiTheme == "default_dark"
assert CONFIG.guiFont == "TestFont"
assert CONFIG.guiFontSize == 41
assert CONFIG.guiFont == QFont()
assert CONFIG.hideVScroll is True
assert CONFIG.hideHScroll is True
# Document Style
assert CONFIG.guiSyntax == "default_dark"
assert CONFIG.textFont == "TestFont"
assert CONFIG.textSize == 41
assert CONFIG.textFont == QFont()
assert CONFIG.emphLabels is False
assert CONFIG.showFullPath is False
assert CONFIG.incNotesWCount is False
+3 -3
View File
@@ -23,7 +23,7 @@ from __future__ import annotations
import pytest
from PyQt5.QtCore import QEvent, Qt, QThreadPool
from PyQt5.QtGui import QClipboard, QMouseEvent, QTextBlock, QTextCursor, QTextOption
from PyQt5.QtGui import QClipboard, QFont, QMouseEvent, QTextBlock, QTextCursor, QTextOption
from PyQt5.QtWidgets import QAction, QApplication, QMenu
from novelwriter import CONFIG, SHARED
@@ -84,7 +84,7 @@ def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd):
assert docEditor.docHeader._docOutline == {0: "### New Scene"}
# Check that editor handles settings
CONFIG.textFont = ""
CONFIG.textFont = QFont()
CONFIG.doJustify = True
CONFIG.showTabsNSpaces = True
CONFIG.showLineEndings = True
@@ -96,7 +96,7 @@ def testGuiEditor_Init(qtbot, nwGUI, projPath, ipsumText, mockRnd):
docEditor.initEditor()
qDoc = docEditor.document()
assert CONFIG.textFont == qDoc.defaultFont().family()
assert CONFIG.textFont == qDoc.defaultFont()
assert qDoc.defaultTextOption().alignment() == QtAlignJustify
assert qDoc.defaultTextOption().flags() & QTextOption.ShowTabsAndSpaces
assert qDoc.defaultTextOption().flags() & QTextOption.ShowLineAndParagraphSeparators
-21
View File
@@ -48,27 +48,6 @@ def testGuiTheme_Main(qtbot, nwGUI, tstPaths):
assert mSize > 0
assert mainTheme.getTextWidth("m", mainTheme.guiFont) == mSize
# Init Fonts
# ==========
# The defaults should be set
defaultFont = CONFIG.guiFont
defaultSize = CONFIG.guiFontSize
# CHange them to nonsense values
CONFIG.guiFont = "notafont"
CONFIG.guiFontSize = 99
# Let the theme class set them back to default
mainTheme._setGuiFont()
assert CONFIG.guiFont == defaultFont
assert CONFIG.guiFontSize == defaultSize
# A second call should just restore the defaults again
mainTheme._setGuiFont()
assert CONFIG.guiFont == defaultFont
assert CONFIG.guiFontSize == defaultSize
# Scan for Themes
# ===============
+1 -1
View File
@@ -547,7 +547,7 @@ def testBuildSettings_Format(monkeypatch, qtbot, nwGUI):
"""Test the Format Tab of the GuiBuildSettings dialog."""
build = BuildSettings()
textFont = str(CONFIG.textFont)
textFont = str(CONFIG.textFont.family())
build.setValue("format.buildLang", "en_US")
build.setValue("format.textFont", "") # Will fall back to config value