Annotate config class and extensions

This commit is contained in:
Veronica Berglyd Olsen
2023-08-10 00:49:33 +02:00
parent 71e961ba38
commit ddacfc743e
9 changed files with 244 additions and 280 deletions
+171 -190
View File
@@ -33,12 +33,13 @@ from pathlib import Path
from PyQt5.QtGui import QFontDatabase from PyQt5.QtGui import QFontDatabase
from PyQt5.QtCore import ( from PyQt5.QtCore import (
QT_VERSION, QT_VERSION_STR, PYQT_VERSION, PYQT_VERSION_STR, QStandardPaths, PYQT_VERSION, PYQT_VERSION_STR, QT_VERSION, QT_VERSION_STR, QLibraryInfo,
QSysInfo, QLocale, QLibraryInfo, QTranslator QLocale, QStandardPaths, QSysInfo, QTranslator
) )
from PyQt5.QtWidgets import QApplication
from novelwriter.error import logException, formatException from novelwriter.error import formatException, logException
from novelwriter.common import checkPath, formatTimeStamp, NWConfigParser from novelwriter.common import NWConfigParser, checkInt, checkPath, formatTimeStamp
from novelwriter.constants import nwFiles, nwUnicode from novelwriter.constants import nwFiles, nwUnicode
if TYPE_CHECKING: # pragma: no cover if TYPE_CHECKING: # pragma: no cover
@@ -52,7 +53,7 @@ class Config:
LANG_NW = 1 LANG_NW = 1
LANG_PROJ = 2 LANG_PROJ = 2
def __init__(self): def __init__(self) -> None:
# Initialisation # Initialisation
# ============== # ==============
@@ -236,11 +237,11 @@ class Config:
## ##
@property @property
def hasError(self): def hasError(self) -> bool:
return self._hasError return self._hasError
@property @property
def recentProjects(self): def recentProjects(self) -> RecentProjects:
return self._recentObj return self._recentObj
@property @property
@@ -250,45 +251,45 @@ class Config:
return self._themeObj return self._themeObj
@property @property
def mainWinSize(self): def mainWinSize(self) -> list[int]:
return [int(x*self.guiScale) for x in self._mainWinSize] return [int(x*self.guiScale) for x in self._mainWinSize]
@property @property
def preferencesWinSize(self): def preferencesWinSize(self) -> list[int]:
return [int(x*self.guiScale) for x in self._prefsWinSize] return [int(x*self.guiScale) for x in self._prefsWinSize]
@property @property
def projLoadColWidths(self): def projLoadColWidths(self) -> list[int]:
return [int(x*self.guiScale) for x in self._projLoadCols] return [int(x*self.guiScale) for x in self._projLoadCols]
@property @property
def mainPanePos(self): def mainPanePos(self) -> list[int]:
return [int(x*self.guiScale) for x in self._mainPanePos] return [int(x*self.guiScale) for x in self._mainPanePos]
@property @property
def viewPanePos(self): def viewPanePos(self) -> list[int]:
return [int(x*self.guiScale) for x in self._viewPanePos] return [int(x*self.guiScale) for x in self._viewPanePos]
@property @property
def outlinePanePos(self): def outlinePanePos(self) -> list[int]:
return [int(x*self.guiScale) for x in self._outlnPanePos] return [int(x*self.guiScale) for x in self._outlnPanePos]
## ##
# Getters # Getters
## ##
def getTextWidth(self, focusMode=False): def getTextWidth(self, focusMode: bool = False) -> int:
"""Get the text with for the correct editor mode.""" """Get the text with for the correct editor mode."""
if focusMode: if focusMode:
return self.pxInt(max(self.focusWidth, 200)) return self.pxInt(max(self.focusWidth, 200))
else: else:
return self.pxInt(max(self.textWidth, 200)) return self.pxInt(max(self.textWidth, 200))
def getTextMargin(self): def getTextMargin(self) -> int:
"""Get the scaled text margin.""" """Get the scaled text margin."""
return self.pxInt(max(self.textMargin, 0)) return self.pxInt(max(self.textMargin, 0))
def getTabWidth(self): def getTabWidth(self) -> int:
"""Get the scaled tab width.""" """Get the scaled tab width."""
return self.pxInt(max(self.tabWidth, 0)) return self.pxInt(max(self.tabWidth, 0))
@@ -301,65 +302,65 @@ class Config:
self._themeObj = theme self._themeObj = theme
return return
def setMainWinSize(self, newWidth, newHeight): def setMainWinSize(self, width: int, height: int) -> None:
"""Set the size of the main window, but only if the change is """Set the size of the main window, but only if the change is
larger than 5 pixels. The OS window manager will sometimes larger than 5 pixels. The OS window manager will sometimes
adjust it a bit, and we don't want the main window to shrink or adjust it a bit, and we don't want the main window to shrink or
grow each time the app is opened. grow each time the app is opened.
""" """
newWidth = int(newWidth/self.guiScale) width = int(width/self.guiScale)
newHeight = int(newHeight/self.guiScale) height = int(height/self.guiScale)
if abs(self._mainWinSize[0] - newWidth) > 5: if abs(self._mainWinSize[0] - width) > 5:
self._mainWinSize[0] = newWidth self._mainWinSize[0] = width
if abs(self._mainWinSize[1] - newHeight) > 5: if abs(self._mainWinSize[1] - height) > 5:
self._mainWinSize[1] = newHeight self._mainWinSize[1] = height
return return
def setPreferencesWinSize(self, newWidth, newHeight): def setPreferencesWinSize(self, width: int, height: int) -> None:
"""Set the size of the Preferences dialog window.""" """Set the size of the Preferences dialog window."""
self._prefsWinSize[0] = int(newWidth/self.guiScale) self._prefsWinSize[0] = int(width/self.guiScale)
self._prefsWinSize[1] = int(newHeight/self.guiScale) self._prefsWinSize[1] = int(height/self.guiScale)
return return
def setProjLoadColWidths(self, colWidths): def setProjLoadColWidths(self, widths: list[int]) -> None:
"""Set the column widths of the Load Project dialog.""" """Set the column widths of the Load Project dialog."""
self._projLoadCols = [int(x/self.guiScale) for x in colWidths] self._projLoadCols = [int(x/self.guiScale) for x in widths]
return return
def setMainPanePos(self, panePos): def setMainPanePos(self, pos: list[int]) -> None:
"""Set the position of the main GUI splitter.""" """Set the position of the main GUI splitter."""
self._mainPanePos = [int(x/self.guiScale) for x in panePos] self._mainPanePos = [int(x/self.guiScale) for x in pos]
return return
def setViewPanePos(self, panePos): def setViewPanePos(self, pos: list[int]) -> None:
"""Set the position of the viewer meta data splitter.""" """Set the position of the viewer meta data splitter."""
self._viewPanePos = [int(x/self.guiScale) for x in panePos] self._viewPanePos = [int(x/self.guiScale) for x in pos]
return return
def setOutlinePanePos(self, panePos): def setOutlinePanePos(self, pos: list[int]) -> None:
"""Set the position of the outline details splitter.""" """Set the position of the outline details splitter."""
self._outlnPanePos = [int(x/self.guiScale) for x in panePos] self._outlnPanePos = [int(x/self.guiScale) for x in pos]
return return
def setLastPath(self, lastPath): def setLastPath(self, path: str | Path) -> None:
"""Set the last used path. Only the folder is saved, so if the """Set the last used path. Only the folder is saved, so if the
path is not a folder, the parent of the path is used instead. path is not a folder, the parent of the path is used instead.
""" """
if isinstance(lastPath, (str, Path)): if isinstance(path, (str, Path)):
lastPath = checkPath(lastPath, self._homePath) path = checkPath(path, self._homePath)
if not lastPath.is_dir(): if not path.is_dir():
lastPath = lastPath.parent path = path.parent
if lastPath.is_dir(): if path.is_dir():
self._lastPath = lastPath self._lastPath = path
logger.debug("Last path updated: %s" % self._lastPath) logger.debug("Last path updated: %s" % self._lastPath)
return return
def setBackupPath(self, backupPath: Path | str): def setBackupPath(self, path: Path | str) -> None:
"""Set the current backup path.""" """Set the current backup path."""
self._backupPath = checkPath(backupPath, self._backPath) self._backupPath = checkPath(path, self._backPath)
return return
def setTextFont(self, family: str | None, pointSize: int = 12): def setTextFont(self, family: str | None, pointSize: int = 12) -> None:
"""Set the text font if it exists. If it doesn't, or is None, """Set the text font if it exists. If it doesn't, or is None,
set to default font. set to default font.
""" """
@@ -383,15 +384,11 @@ class Config:
## ##
def pxInt(self, value: int) -> int: def pxInt(self, value: int) -> int:
"""Used to scale fixed gui sizes by the screen scale factor. """Scale fixed gui sizes by the screen scale factor."""
This function returns an int, which is always rounded down.
"""
return int(value*self.guiScale) return int(value*self.guiScale)
def rpxInt(self, value: int) -> int: def rpxInt(self, value: int) -> int:
"""Used to un-scale fixed gui sizes by the screen scale factor. """Un-scale fixed gui sizes by the screen scale factor."""
This function returns an int, which is always rounded down.
"""
return int(value/self.guiScale) return int(value/self.guiScale)
def dataPath(self, target: str | None = None) -> Path: def dataPath(self, target: str | None = None) -> Path:
@@ -461,7 +458,8 @@ class Config:
# Config Actions # Config Actions
## ##
def initConfig(self, confPath: str | Path | None = None, dataPath: str | Path | None = None): def initConfig(self, confPath: str | Path | None = None,
dataPath: str | Path | None = None) -> None:
"""Initialise the config class. The manual setting of confPath """Initialise the config class. The manual setting of confPath
and dataPath is mainly intended for the test suite. and dataPath is mainly intended for the test suite.
""" """
@@ -505,9 +503,8 @@ class Config:
return return
def initLocalisation(self, nwApp): def initLocalisation(self, nwApp: QApplication) -> None:
"""Initialise the localisation of the GUI. """Initialise the localisation of the GUI."""
"""
self._qLocale = QLocale(self.guiLocale) self._qLocale = QLocale(self.guiLocale)
QLocale.setDefault(self._qLocale) QLocale.setDefault(self._qLocale)
self._qtTrans = {} self._qtTrans = {}
@@ -528,16 +525,15 @@ class Config:
return return
def loadConfig(self): def loadConfig(self) -> bool:
"""Load preferences from file and replace default settings. """Load preferences from file and replace default settings."""
"""
logger.debug("Loading config file") logger.debug("Loading config file")
theConf = NWConfigParser() conf = NWConfigParser()
cnfPath = self._confPath / nwFiles.CONF_FILE cnfPath = self._confPath / nwFiles.CONF_FILE
try: try:
with open(cnfPath, mode="r", encoding="utf-8") as inFile: with open(cnfPath, mode="r", encoding="utf-8") as inFile:
theConf.read_file(inFile) conf.read_file(inFile)
except Exception as exc: except Exception as exc:
logger.error("Could not load config file") logger.error("Could not load config file")
logException() logException()
@@ -547,98 +543,98 @@ class Config:
return False return False
# Main # Main
cnfSec = "Main" sec = "Main"
self.guiTheme = theConf.rdStr(cnfSec, "theme", self.guiTheme) self.guiTheme = conf.rdStr(sec, "theme", self.guiTheme)
self.guiSyntax = theConf.rdStr(cnfSec, "syntax", self.guiSyntax) self.guiSyntax = conf.rdStr(sec, "syntax", self.guiSyntax)
self.guiFont = theConf.rdStr(cnfSec, "font", self.guiFont) self.guiFont = conf.rdStr(sec, "font", self.guiFont)
self.guiFontSize = theConf.rdInt(cnfSec, "fontsize", self.guiFontSize) self.guiFontSize = conf.rdInt(sec, "fontsize", self.guiFontSize)
self.guiLocale = theConf.rdStr(cnfSec, "localisation", self.guiLocale) self.guiLocale = conf.rdStr(sec, "localisation", self.guiLocale)
self.hideVScroll = theConf.rdBool(cnfSec, "hidevscroll", self.hideVScroll) self.hideVScroll = conf.rdBool(sec, "hidevscroll", self.hideVScroll)
self.hideHScroll = theConf.rdBool(cnfSec, "hidehscroll", self.hideHScroll) self.hideHScroll = conf.rdBool(sec, "hidehscroll", self.hideHScroll)
self.lastNotes = theConf.rdStr(cnfSec, "lastnotes", self.lastNotes) self.lastNotes = conf.rdStr(sec, "lastnotes", self.lastNotes)
self._lastPath = theConf.rdPath(cnfSec, "lastpath", self._lastPath) self._lastPath = conf.rdPath(sec, "lastpath", self._lastPath)
# Sizes # Sizes
cnfSec = "Sizes" sec = "Sizes"
self._mainWinSize = theConf.rdIntList(cnfSec, "mainwindow", self._mainWinSize) self._mainWinSize = conf.rdIntList(sec, "mainwindow", self._mainWinSize)
self._prefsWinSize = theConf.rdIntList(cnfSec, "preferences", self._prefsWinSize) self._prefsWinSize = conf.rdIntList(sec, "preferences", self._prefsWinSize)
self._projLoadCols = theConf.rdIntList(cnfSec, "projloadcols", self._projLoadCols) self._projLoadCols = conf.rdIntList(sec, "projloadcols", self._projLoadCols)
self._mainPanePos = theConf.rdIntList(cnfSec, "mainpane", self._mainPanePos) self._mainPanePos = conf.rdIntList(sec, "mainpane", self._mainPanePos)
self._viewPanePos = theConf.rdIntList(cnfSec, "viewpane", self._viewPanePos) self._viewPanePos = conf.rdIntList(sec, "viewpane", self._viewPanePos)
self._outlnPanePos = theConf.rdIntList(cnfSec, "outlinepane", self._outlnPanePos) self._outlnPanePos = conf.rdIntList(sec, "outlinepane", self._outlnPanePos)
# Project # Project
cnfSec = "Project" sec = "Project"
self.autoSaveProj = theConf.rdInt(cnfSec, "autosaveproject", self.autoSaveProj) self.autoSaveProj = conf.rdInt(sec, "autosaveproject", self.autoSaveProj)
self.autoSaveDoc = theConf.rdInt(cnfSec, "autosavedoc", self.autoSaveDoc) self.autoSaveDoc = conf.rdInt(sec, "autosavedoc", self.autoSaveDoc)
self.emphLabels = theConf.rdBool(cnfSec, "emphlabels", self.emphLabels) self.emphLabels = conf.rdBool(sec, "emphlabels", self.emphLabels)
self._backupPath = theConf.rdPath(cnfSec, "backuppath", self._backupPath) self._backupPath = conf.rdPath(sec, "backuppath", self._backupPath)
self.backupOnClose = theConf.rdBool(cnfSec, "backuponclose", self.backupOnClose) self.backupOnClose = conf.rdBool(sec, "backuponclose", self.backupOnClose)
self.askBeforeBackup = theConf.rdBool(cnfSec, "askbeforebackup", self.askBeforeBackup) self.askBeforeBackup = conf.rdBool(sec, "askbeforebackup", self.askBeforeBackup)
# Editor # Editor
cnfSec = "Editor" sec = "Editor"
self.textFont = theConf.rdStr(cnfSec, "textfont", self.textFont) self.textFont = conf.rdStr(sec, "textfont", self.textFont)
self.textSize = theConf.rdInt(cnfSec, "textsize", self.textSize) self.textSize = conf.rdInt(sec, "textsize", self.textSize)
self.textWidth = theConf.rdInt(cnfSec, "width", self.textWidth) self.textWidth = conf.rdInt(sec, "width", self.textWidth)
self.textMargin = theConf.rdInt(cnfSec, "margin", self.textMargin) self.textMargin = conf.rdInt(sec, "margin", self.textMargin)
self.tabWidth = theConf.rdInt(cnfSec, "tabwidth", self.tabWidth) self.tabWidth = conf.rdInt(sec, "tabwidth", self.tabWidth)
self.focusWidth = theConf.rdInt(cnfSec, "focuswidth", self.focusWidth) self.focusWidth = conf.rdInt(sec, "focuswidth", self.focusWidth)
self.hideFocusFooter = theConf.rdBool(cnfSec, "hidefocusfooter", self.hideFocusFooter) self.hideFocusFooter = conf.rdBool(sec, "hidefocusfooter", self.hideFocusFooter)
self.doJustify = theConf.rdBool(cnfSec, "justify", self.doJustify) self.doJustify = conf.rdBool(sec, "justify", self.doJustify)
self.autoSelect = theConf.rdBool(cnfSec, "autoselect", self.autoSelect) self.autoSelect = conf.rdBool(sec, "autoselect", self.autoSelect)
self.doReplace = theConf.rdBool(cnfSec, "autoreplace", self.doReplace) self.doReplace = conf.rdBool(sec, "autoreplace", self.doReplace)
self.doReplaceSQuote = theConf.rdBool(cnfSec, "repsquotes", self.doReplaceSQuote) self.doReplaceSQuote = conf.rdBool(sec, "repsquotes", self.doReplaceSQuote)
self.doReplaceDQuote = theConf.rdBool(cnfSec, "repdquotes", self.doReplaceDQuote) self.doReplaceDQuote = conf.rdBool(sec, "repdquotes", self.doReplaceDQuote)
self.doReplaceDash = theConf.rdBool(cnfSec, "repdash", self.doReplaceDash) self.doReplaceDash = conf.rdBool(sec, "repdash", self.doReplaceDash)
self.doReplaceDots = theConf.rdBool(cnfSec, "repdots", self.doReplaceDots) self.doReplaceDots = conf.rdBool(sec, "repdots", self.doReplaceDots)
self.scrollPastEnd = theConf.rdInt(cnfSec, "scrollpastend", self.scrollPastEnd) self.scrollPastEnd = conf.rdInt(sec, "scrollpastend", self.scrollPastEnd)
self.autoScroll = theConf.rdBool(cnfSec, "autoscroll", self.autoScroll) self.autoScroll = conf.rdBool(sec, "autoscroll", self.autoScroll)
self.autoScrollPos = theConf.rdInt(cnfSec, "autoscrollpos", self.autoScrollPos) self.autoScrollPos = conf.rdInt(sec, "autoscrollpos", self.autoScrollPos)
self.fmtSQuoteOpen = theConf.rdStr(cnfSec, "fmtsquoteopen", self.fmtSQuoteOpen) self.fmtSQuoteOpen = conf.rdStr(sec, "fmtsquoteopen", self.fmtSQuoteOpen)
self.fmtSQuoteClose = theConf.rdStr(cnfSec, "fmtsquoteclose", self.fmtSQuoteClose) self.fmtSQuoteClose = conf.rdStr(sec, "fmtsquoteclose", self.fmtSQuoteClose)
self.fmtDQuoteOpen = theConf.rdStr(cnfSec, "fmtdquoteopen", self.fmtDQuoteOpen) self.fmtDQuoteOpen = conf.rdStr(sec, "fmtdquoteopen", self.fmtDQuoteOpen)
self.fmtDQuoteClose = theConf.rdStr(cnfSec, "fmtdquoteclose", self.fmtDQuoteClose) self.fmtDQuoteClose = conf.rdStr(sec, "fmtdquoteclose", self.fmtDQuoteClose)
self.fmtPadBefore = theConf.rdStr(cnfSec, "fmtpadbefore", self.fmtPadBefore) self.fmtPadBefore = conf.rdStr(sec, "fmtpadbefore", self.fmtPadBefore)
self.fmtPadAfter = theConf.rdStr(cnfSec, "fmtpadafter", self.fmtPadAfter) self.fmtPadAfter = conf.rdStr(sec, "fmtpadafter", self.fmtPadAfter)
self.fmtPadThin = theConf.rdBool(cnfSec, "fmtpadthin", self.fmtPadThin) self.fmtPadThin = conf.rdBool(sec, "fmtpadthin", self.fmtPadThin)
self.spellLanguage = theConf.rdStr(cnfSec, "spellcheck", self.spellLanguage) self.spellLanguage = conf.rdStr(sec, "spellcheck", self.spellLanguage)
self.showTabsNSpaces = theConf.rdBool(cnfSec, "showtabsnspaces", self.showTabsNSpaces) self.showTabsNSpaces = conf.rdBool(sec, "showtabsnspaces", self.showTabsNSpaces)
self.showLineEndings = theConf.rdBool(cnfSec, "showlineendings", self.showLineEndings) self.showLineEndings = conf.rdBool(sec, "showlineendings", self.showLineEndings)
self.showMultiSpaces = theConf.rdBool(cnfSec, "showmultispaces", self.showMultiSpaces) self.showMultiSpaces = conf.rdBool(sec, "showmultispaces", self.showMultiSpaces)
self.wordCountTimer = theConf.rdFlt(cnfSec, "wordcounttimer", self.wordCountTimer) self.wordCountTimer = conf.rdFlt(sec, "wordcounttimer", self.wordCountTimer)
self.bigDocLimit = theConf.rdInt(cnfSec, "bigdoclimit", self.bigDocLimit) self.bigDocLimit = conf.rdInt(sec, "bigdoclimit", self.bigDocLimit)
self.incNotesWCount = theConf.rdBool(cnfSec, "incnoteswcount", self.incNotesWCount) self.incNotesWCount = conf.rdBool(sec, "incnoteswcount", self.incNotesWCount)
self.showFullPath = theConf.rdBool(cnfSec, "showfullpath", self.showFullPath) self.showFullPath = conf.rdBool(sec, "showfullpath", self.showFullPath)
self.highlightQuotes = theConf.rdBool(cnfSec, "highlightquotes", self.highlightQuotes) self.highlightQuotes = conf.rdBool(sec, "highlightquotes", self.highlightQuotes)
self.allowOpenSQuote = theConf.rdBool(cnfSec, "allowopensquote", self.allowOpenSQuote) self.allowOpenSQuote = conf.rdBool(sec, "allowopensquote", self.allowOpenSQuote)
self.allowOpenDQuote = theConf.rdBool(cnfSec, "allowopendquote", self.allowOpenDQuote) self.allowOpenDQuote = conf.rdBool(sec, "allowopendquote", self.allowOpenDQuote)
self.highlightEmph = theConf.rdBool(cnfSec, "highlightemph", self.highlightEmph) self.highlightEmph = conf.rdBool(sec, "highlightemph", self.highlightEmph)
self.stopWhenIdle = theConf.rdBool(cnfSec, "stopwhenidle", self.stopWhenIdle) self.stopWhenIdle = conf.rdBool(sec, "stopwhenidle", self.stopWhenIdle)
self.userIdleTime = theConf.rdInt(cnfSec, "useridletime", self.userIdleTime) self.userIdleTime = conf.rdInt(sec, "useridletime", self.userIdleTime)
# State # State
cnfSec = "State" sec = "State"
self.showRefPanel = theConf.rdBool(cnfSec, "showrefpanel", self.showRefPanel) self.showRefPanel = conf.rdBool(sec, "showrefpanel", self.showRefPanel)
self.viewComments = theConf.rdBool(cnfSec, "viewcomments", self.viewComments) self.viewComments = conf.rdBool(sec, "viewcomments", self.viewComments)
self.viewSynopsis = theConf.rdBool(cnfSec, "viewsynopsis", self.viewSynopsis) self.viewSynopsis = conf.rdBool(sec, "viewsynopsis", self.viewSynopsis)
self.searchCase = theConf.rdBool(cnfSec, "searchcase", self.searchCase) self.searchCase = conf.rdBool(sec, "searchcase", self.searchCase)
self.searchWord = theConf.rdBool(cnfSec, "searchword", self.searchWord) self.searchWord = conf.rdBool(sec, "searchword", self.searchWord)
self.searchRegEx = theConf.rdBool(cnfSec, "searchregex", self.searchRegEx) self.searchRegEx = conf.rdBool(sec, "searchregex", self.searchRegEx)
self.searchLoop = theConf.rdBool(cnfSec, "searchloop", self.searchLoop) self.searchLoop = conf.rdBool(sec, "searchloop", self.searchLoop)
self.searchNextFile = theConf.rdBool(cnfSec, "searchnextfile", self.searchNextFile) self.searchNextFile = conf.rdBool(sec, "searchnextfile", self.searchNextFile)
self.searchMatchCap = theConf.rdBool(cnfSec, "searchmatchcap", self.searchMatchCap) self.searchMatchCap = conf.rdBool(sec, "searchmatchcap", self.searchMatchCap)
# Deprecated Settings or Locations as of 2.0 # Deprecated Settings or Locations as of 2.0
# ToDo: These will be loaded for a few minor releases until the users have converted them # ToDo: These will be loaded for a few minor releases until the users have converted them
self.guiFont = theConf.rdStr("Main", "guifont", self.guiFont) self.guiFont = conf.rdStr("Main", "guifont", self.guiFont)
self.guiFontSize = theConf.rdInt("Main", "guifontsize", self.guiFontSize) self.guiFontSize = conf.rdInt("Main", "guifontsize", self.guiFontSize)
self.guiLocale = theConf.rdStr("Main", "guilang", self.guiLocale) self.guiLocale = conf.rdStr("Main", "guilang", self.guiLocale)
self._backupPath = theConf.rdPath("Backup", "backuppath", self._backupPath) self._backupPath = conf.rdPath("Backup", "backuppath", self._backupPath)
self.backupOnClose = theConf.rdBool("Backup", "backuponclose", self.backupOnClose) self.backupOnClose = conf.rdBool("Backup", "backuponclose", self.backupOnClose)
self.askBeforeBackup = theConf.rdBool("Backup", "askbeforebackup", self.askBeforeBackup) self.askBeforeBackup = conf.rdBool("Backup", "askbeforebackup", self.askBeforeBackup)
fmtSingleQuotes = theConf.rdStrList(cnfSec, "fmtsinglequote", []) fmtSingleQuotes = conf.rdStrList(sec, "fmtsinglequote", [])
fmtDoubleQuotes = theConf.rdStrList(cnfSec, "fmtdoublequote", []) fmtDoubleQuotes = conf.rdStrList(sec, "fmtdoublequote", [])
if isinstance(fmtSingleQuotes, list) and len(fmtSingleQuotes) == 2: if isinstance(fmtSingleQuotes, list) and len(fmtSingleQuotes) == 2:
self.fmtSQuoteOpen = fmtSingleQuotes[0] self.fmtSQuoteOpen = fmtSingleQuotes[0]
@@ -661,18 +657,17 @@ class Config:
return True return True
def saveConfig(self): def saveConfig(self) -> bool:
"""Save the current preferences to file. """Save the current preferences to file."""
"""
logger.debug("Saving config file") logger.debug("Saving config file")
theConf = NWConfigParser() conf = NWConfigParser()
theConf["Meta"] = { conf["Meta"] = {
"timestamp": formatTimeStamp(time()), "timestamp": formatTimeStamp(time()),
} }
theConf["Main"] = { conf["Main"] = {
"theme": str(self.guiTheme), "theme": str(self.guiTheme),
"syntax": str(self.guiSyntax), "syntax": str(self.guiSyntax),
"font": str(self.guiFont), "font": str(self.guiFont),
@@ -684,7 +679,7 @@ class Config:
"lastpath": str(self._lastPath), "lastpath": str(self._lastPath),
} }
theConf["Sizes"] = { conf["Sizes"] = {
"mainwindow": self._packList(self._mainWinSize), "mainwindow": self._packList(self._mainWinSize),
"preferences": self._packList(self._prefsWinSize), "preferences": self._packList(self._prefsWinSize),
"projloadcols": self._packList(self._projLoadCols), "projloadcols": self._packList(self._projLoadCols),
@@ -693,7 +688,7 @@ class Config:
"outlinepane": self._packList(self._outlnPanePos), "outlinepane": self._packList(self._outlnPanePos),
} }
theConf["Project"] = { conf["Project"] = {
"autosaveproject": str(self.autoSaveProj), "autosaveproject": str(self.autoSaveProj),
"autosavedoc": str(self.autoSaveDoc), "autosavedoc": str(self.autoSaveDoc),
"emphlabels": str(self.emphLabels), "emphlabels": str(self.emphLabels),
@@ -702,7 +697,7 @@ class Config:
"askbeforebackup": str(self.askBeforeBackup), "askbeforebackup": str(self.askBeforeBackup),
} }
theConf["Editor"] = { conf["Editor"] = {
"textfont": str(self.textFont), "textfont": str(self.textFont),
"textsize": str(self.textSize), "textsize": str(self.textSize),
"width": str(self.textWidth), "width": str(self.textWidth),
@@ -743,7 +738,7 @@ class Config:
"useridletime": str(self.userIdleTime), "useridletime": str(self.userIdleTime),
} }
theConf["State"] = { conf["State"] = {
"showrefpanel": str(self.showRefPanel), "showrefpanel": str(self.showRefPanel),
"viewcomments": str(self.viewComments), "viewcomments": str(self.viewComments),
"viewsynopsis": str(self.viewSynopsis), "viewsynopsis": str(self.viewSynopsis),
@@ -759,7 +754,7 @@ class Config:
cnfPath = self._confPath / nwFiles.CONF_FILE cnfPath = self._confPath / nwFiles.CONF_FILE
try: try:
with open(cnfPath, mode="w", encoding="utf-8") as outFile: with open(cnfPath, mode="w", encoding="utf-8") as outFile:
theConf.write(outFile) conf.write(outFile)
except Exception as exc: except Exception as exc:
logger.error("Could not save config file") logger.error("Could not save config file")
logException() logException()
@@ -774,26 +769,14 @@ class Config:
# Internal Functions # Internal Functions
## ##
def _packList(self, inData): def _packList(self, data: list) -> str:
"""Pack a list of items into a comma-separated string for saving """Pack a list of items into a comma-separated string for saving
to the config file. to the config file.
""" """
return ", ".join([str(inVal) for inVal in inData]) return ", ".join([str(inVal) for inVal in data])
def _checkNone(self, checkVal): def _checkOptionalPackages(self) -> None:
"""Return a NoneType if the value corresponds to None, otherwise """Check optional packages used by some features."""
return the value unchanged.
"""
if checkVal is None:
return None
if isinstance(checkVal, str):
if checkVal.lower() == "none":
return None
return checkVal
def _checkOptionalPackages(self):
"""Check if we have the optional packages used by some features.
"""
try: try:
import enchant # noqa: F401 import enchant # noqa: F401
except ImportError: except ImportError:
@@ -809,14 +792,13 @@ class Config:
class RecentProjects: class RecentProjects:
def __init__(self, config): def __init__(self, config: Config) -> None:
self._conf = config self._conf = config
self._data = {} self._data = {}
return return
def loadCache(self): def loadCache(self) -> bool:
"""Load the cache file for recent projects. """Load the cache file for recent projects."""
"""
self._data = {} self._data = {}
cacheFile = self._conf.dataPath(nwFiles.RECENT_FILE) cacheFile = self._conf.dataPath(nwFiles.RECENT_FILE)
@@ -839,9 +821,8 @@ class RecentProjects:
return True return True
def saveCache(self): def saveCache(self) -> bool:
"""Save the cache dictionary of recent projects. """Save the cache dictionary of recent projects."""
"""
cacheFile = self._conf.dataPath(nwFiles.RECENT_FILE) cacheFile = self._conf.dataPath(nwFiles.RECENT_FILE)
cacheTemp = cacheFile.with_suffix(".tmp") cacheTemp = cacheFile.with_suffix(".tmp")
try: try:
@@ -855,27 +836,27 @@ class RecentProjects:
return True return True
def listEntries(self): def listEntries(self) -> list[tuple[str, str, int, int]]:
"""List all items in the cache. """List all items in the cache."""
""" return [
return [(k, e["title"], e["words"], e["time"]) for k, e in self._data.items()] (str(k), str(e["title"]), checkInt(e["words"], 0), checkInt(e["time"], 0))
for k, e in self._data.items()
]
def update(self, projPath, projTitle, wordCount, saveTime): def update(self, path: str | Path, title: str, words: int, saved: float | int) -> None:
"""Add or update recent cache information on a given project. """Add or update recent cache information on a given project."""
""" self._data[str(path)] = {
self._data[str(projPath)] = { "title": title,
"title": projTitle, "words": int(words),
"words": int(wordCount), "time": int(saved),
"time": int(saveTime),
} }
self.saveCache() self.saveCache()
return return
def remove(self, projPath): def remove(self, path: str | Path) -> None:
"""Try to remove a path from the recent projects cache. """Try to remove a path from the recent projects cache."""
""" if self._data.pop(str(path), None) is not None:
if self._data.pop(str(projPath), None) is not None: logger.debug("Removed recent: %s", path)
logger.debug("Removed recent: %s", projPath)
self.saveCache() self.saveCache()
return return
+4 -4
View File
@@ -100,8 +100,9 @@ class GuiProjectLoad(QDialog):
self.listBox.setIconSize(QSize(iPx, iPx)) self.listBox.setIconSize(QSize(iPx, iPx))
treeHead = self.listBox.headerItem() treeHead = self.listBox.headerItem()
treeHead.setTextAlignment(self.C_COUNT, Qt.AlignRight) if treeHead:
treeHead.setTextAlignment(self.C_TIME, Qt.AlignRight) treeHead.setTextAlignment(self.C_COUNT, Qt.AlignRight)
treeHead.setTextAlignment(self.C_TIME, Qt.AlignRight)
self.lblRecent = QLabel("<b>%s</b>" % self.tr("Recently Opened Projects")) self.lblRecent = QLabel("<b>%s</b>" % self.tr("Recently Opened Projects"))
self.lblPath = QLabel("<b>%s</b>" % self.tr("Path")) self.lblPath = QLabel("<b>%s</b>" % self.tr("Path"))
@@ -281,8 +282,7 @@ class GuiProjectLoad(QDialog):
newItem.setFont(self.C_TIME, CONFIG.theme.guiFontFixed) newItem.setFont(self.C_TIME, CONFIG.theme.guiFontFixed)
self.listBox.addTopLevelItem(newItem) self.listBox.addTopLevelItem(newItem)
if self.listBox.topLevelItemCount() > 0: self.listBox.setCurrentItem(self.listBox.topLevelItem(0))
self.listBox.topLevelItem(0).setSelected(True)
projColWidth = CONFIG.projLoadColWidths projColWidth = CONFIG.projLoadColWidths
if len(projColWidth) == 3: if len(projColWidth) == 3:
+5 -7
View File
@@ -42,7 +42,7 @@ class NProgressCircle(QProgressBar):
"_cPen", "_bPen", "_tColor" "_cPen", "_bPen", "_tColor"
) )
def __init__(self, parent: QWidget, size: int, point: int): def __init__(self, parent: QWidget, size: int, point: int) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self._text = None self._text = None
self._point = point self._point = point
@@ -60,10 +60,8 @@ class NProgressCircle(QProgressBar):
self.setFixedHeight(size) self.setFixedHeight(size)
return return
def setColours( def setColours(self, back: QColor | None = None, track: QColor | None = None,
self, back: QColor | None = None, track: QColor | None = None, bar: QColor | None = None, text: QColor | None = None) -> None:
bar: QColor | None = None, text: QColor | None = None
):
"""Set the colours of the widget.""" """Set the colours of the widget."""
if isinstance(back, QColor): if isinstance(back, QColor):
self._dPen = QPen(back) self._dPen = QPen(back)
@@ -76,13 +74,13 @@ class NProgressCircle(QProgressBar):
self._tColor = text self._tColor = text
return return
def setCentreText(self, text: str | None): def setCentreText(self, text: str | None) -> None:
"""Replace the progress text with a custom string.""" """Replace the progress text with a custom string."""
self._text = text self._text = text
self.setValue(self.value()) # Triggers a redraw self.setValue(self.value()) # Triggers a redraw
return return
def paintEvent(self, event: QPaintEvent): def paintEvent(self, event: QPaintEvent) -> None:
"""Custom painter for the progress bar.""" """Custom painter for the progress bar."""
progress = 100.0*self.value()/self.maximum() progress = 100.0*self.value()/self.maximum()
angle = ceil(16*3.6*progress) angle = ceil(16*3.6*progress)
+13 -13
View File
@@ -37,7 +37,7 @@ FONT_SCALE = 0.9
class NConfigLayout(QGridLayout): class NConfigLayout(QGridLayout):
def __init__(self): def __init__(self) -> None:
super().__init__() super().__init__()
self._nextRow = 0 self._nextRow = 0
@@ -56,7 +56,8 @@ class NConfigLayout(QGridLayout):
# Getters and Setters # Getters and Setters
## ##
def setHelpTextStyle(self, color: QColor | list | tuple, fontScale: float = FONT_SCALE): def setHelpTextStyle(self, color: QColor | list | tuple,
fontScale: float = FONT_SCALE) -> None:
"""Set the text color for the help text.""" """Set the text color for the help text."""
if isinstance(color, QColor): if isinstance(color, QColor):
self._helpCol = color self._helpCol = color
@@ -65,7 +66,7 @@ class NConfigLayout(QGridLayout):
self._fontScale = fontScale self._fontScale = fontScale
return return
def setHelpText(self, row: int, text: str): def setHelpText(self, row: int, text: str) -> None:
"""Set the text for the help label.""" """Set the text for the help label."""
if row in self._itemMap: if row in self._itemMap:
qHelp = self._itemMap[row][1] qHelp = self._itemMap[row][1]
@@ -73,7 +74,7 @@ class NConfigLayout(QGridLayout):
qHelp.setText(text) qHelp.setText(text)
return return
def setLabelText(self, row: int, text: str): def setLabelText(self, row: int, text: str) -> None:
"""Set the text for the main label.""" """Set the text for the main label."""
if row in self._itemMap: if row in self._itemMap:
self._itemMap[row](0).setText(text) self._itemMap[row](0).setText(text)
@@ -83,7 +84,7 @@ class NConfigLayout(QGridLayout):
# Class Methods # Class Methods
## ##
def addGroupLabel(self, label: str): def addGroupLabel(self, label: str) -> None:
"""Add a text label to separate groups of settings.""" """Add a text label to separate groups of settings."""
hM = CONFIG.pxInt(4) hM = CONFIG.pxInt(4)
qLabel = QLabel("<b>%s</b>" % label) qLabel = QLabel("<b>%s</b>" % label)
@@ -94,10 +95,8 @@ class NConfigLayout(QGridLayout):
self._nextRow += 1 self._nextRow += 1
return return
def addRow( def addRow(self, label: str, widget: QWidget, helpText: str | None = None,
self, label: str, widget: QWidget, helpText: str | None = None, unit: str | None = None, button: QWidget | None = None) -> int:
unit: str | None = None, button: QWidget | None = None
) -> int:
"""Add a label and a widget as a new row of the grid.""" """Add a label and a widget as a new row of the grid."""
wSp = CONFIG.pxInt(8) wSp = CONFIG.pxInt(8)
qLabel = QLabel(label) qLabel = QLabel(label)
@@ -155,7 +154,7 @@ class NSimpleLayout(QGridLayout):
column layout. column layout.
""" """
def __init__(self): def __init__(self) -> None:
super().__init__() super().__init__()
self._nextRow = 0 self._nextRow = 0
@@ -170,7 +169,7 @@ class NSimpleLayout(QGridLayout):
# Methods # Methods
## ##
def addGroupLabel(self, label: str): def addGroupLabel(self, label: str) -> None:
"""Add a text label to separate groups of settings.""" """Add a text label to separate groups of settings."""
hM = CONFIG.pxInt(4) hM = CONFIG.pxInt(4)
qLabel = QLabel("<b>%s</b>" % label) qLabel = QLabel("<b>%s</b>" % label)
@@ -181,7 +180,7 @@ class NSimpleLayout(QGridLayout):
self._nextRow += 1 self._nextRow += 1
return return
def addRow(self, label: str, widget: QWidget): def addRow(self, label: str, widget: QWidget) -> None:
"""Add a label and a widget as a new row of the grid.""" """Add a label and a widget as a new row of the grid."""
wSp = CONFIG.pxInt(8) wSp = CONFIG.pxInt(8)
qLabel = QLabel(label) qLabel = QLabel(label)
@@ -208,7 +207,8 @@ class NSimpleLayout(QGridLayout):
class NHelpLabel(QLabel): class NHelpLabel(QLabel):
def __init__(self, text: str, color: QColor | list | tuple, fontSize: float = FONT_SCALE): def __init__(self, text: str, color: QColor | list | tuple,
fontSize: float = FONT_SCALE) -> None:
super().__init__(text) super().__init__(text)
if isinstance(color, QColor): if isinstance(color, QColor):
+14 -17
View File
@@ -23,10 +23,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
from PyQt5.QtCore import QRect, QPoint from PyQt5.QtGui import QPaintEvent
from PyQt5.QtCore import QRect, QPoint, QSize
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QDialog, QHBoxLayout, QStyle, QStyleOptionTab, QStylePainter, QTabBar, QDialog, QHBoxLayout, QStyle, QStyleOptionTab, QStylePainter, QTabBar,
QTabWidget, QVBoxLayout QTabWidget, QVBoxLayout, QWidget
) )
from novelwriter import CONFIG from novelwriter import CONFIG
@@ -34,7 +35,7 @@ from novelwriter import CONFIG
class NPagedDialog(QDialog): class NPagedDialog(QDialog):
def __init__(self, parent=None): def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self._tabBar = NVerticalTabBar(self) self._tabBar = NVerticalTabBar(self)
@@ -67,21 +68,18 @@ class NPagedDialog(QDialog):
return return
def addTab(self, widget, label): def addTab(self, widget: QWidget, label: str) -> None:
"""Forward the adding of tabs to the QTabWidget. """Forward the adding of tabs to the QTabWidget."""
"""
self._tabBox.addTab(widget, label) self._tabBox.addTab(widget, label)
return return
def addControls(self, buttonBar): def addControls(self, buttonBar: QWidget) -> None:
"""Add a button bar to the dialog. """Add a button bar to the dialog."""
"""
self._buttonBox.addWidget(buttonBar) self._buttonBox.addWidget(buttonBar)
return return
def setCurrentWidget(self, widget): def setCurrentWidget(self, widget: QWidget) -> None:
"""Forward the changing of tab to the QTabWidget. """Forward the changing of tab to the QTabWidget."""
"""
self._tabBox.setCurrentWidget(widget) self._tabBox.setCurrentWidget(widget)
return return
@@ -90,20 +88,19 @@ class NPagedDialog(QDialog):
class NVerticalTabBar(QTabBar): class NVerticalTabBar(QTabBar):
def __init__(self, parent=None): def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self._mW = CONFIG.pxInt(150) self._mW = CONFIG.pxInt(150)
return return
def tabSizeHint(self, index): def tabSizeHint(self, index: int) -> QSize:
"""Return a transposed size hint for the rotated bar. """Return a transposed size hint for the rotated bar."""
"""
tSize = super().tabSizeHint(index) tSize = super().tabSizeHint(index)
tSize.transpose() tSize.transpose()
tSize.setWidth(min(tSize.width(), self._mW)) tSize.setWidth(min(tSize.width(), self._mW))
return tSize return tSize
def paintEvent(self, event): def paintEvent(self, event: QPaintEvent) -> None:
"""Custom implementation of the label painter that rotates the """Custom implementation of the label painter that rotates the
label 90 degrees. label 90 degrees.
""" """
+2 -2
View File
@@ -35,11 +35,11 @@ class NProgressSimple(QProgressBar):
A custom widget that paints a plain bar with no other styling. A custom widget that paints a plain bar with no other styling.
""" """
def __init__(self, parent: QWidget): def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
return return
def paintEvent(self, event: QPaintEvent): def paintEvent(self, event: QPaintEvent) -> None:
"""Custom painter for the progress bar.""" """Custom painter for the progress bar."""
if self.value() == 0: if self.value() == 0:
return return
+26 -30
View File
@@ -23,9 +23,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
from PyQt5.QtGui import QPainter from PyQt5.QtGui import QMouseEvent, QPainter, QPaintEvent, QResizeEvent
from PyQt5.QtCore import Qt, QRectF, QPropertyAnimation, pyqtProperty from PyQt5.QtCore import QEvent, QPropertyAnimation, QRectF, Qt, pyqtProperty
from PyQt5.QtWidgets import QSizePolicy, QAbstractButton from PyQt5.QtWidgets import QAbstractButton, QSizePolicy, QWidget
from novelwriter import CONFIG from novelwriter import CONFIG
from novelwriter.constants import nwUnicode from novelwriter.constants import nwUnicode
@@ -33,7 +33,8 @@ from novelwriter.constants import nwUnicode
class NSwitch(QAbstractButton): class NSwitch(QAbstractButton):
def __init__(self, parent=None, width=None, height=None): def __init__(self, parent: QWidget | None = None,
width: int | None = None, height: int | None = None) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
if width is None: if width is None:
@@ -64,12 +65,12 @@ class NSwitch(QAbstractButton):
# Properties # Properties
## ##
@pyqtProperty(int) @pyqtProperty(int) # type: ignore
def offset(self): def offset(self) -> int: # type: ignore
return self._offset return self._offset
@offset.setter @offset.setter # type: ignore
def offset(self, offset): def offset(self, offset: int):
self._offset = offset self._offset = offset
self.update() self.update()
return return
@@ -78,33 +79,30 @@ class NSwitch(QAbstractButton):
# Getters and Setters # Getters and Setters
## ##
def setChecked(self, checked): def setChecked(self, checked: bool) -> None:
"""Overload setChecked to also alter the offset. """Overload setChecked to also alter the offset."""
"""
super().setChecked(checked) super().setChecked(checked)
if checked: if checked:
self.offset = self._xW - self._xR self._offset = self._xW - self._xR
else: else:
self.offset = self._xR self._offset = self._xR
return return
## ##
# Events # Events
## ##
def resizeEvent(self, event): def resizeEvent(self, event: QResizeEvent) -> None:
"""Overload resize to ensure correct offset. """Overload resize to ensure correct offset."""
"""
super().resizeEvent(event) super().resizeEvent(event)
if self.isChecked(): if self.isChecked():
self.offset = self._xW - self._xR self._offset = self._xW - self._xR
else: else:
self.offset = self._xR self._offset = self._xR
return return
def paintEvent(self, event): def paintEvent(self, event: QPaintEvent) -> None:
"""Drawing the switch itself. """Drawing the switch itself."""
"""
qPaint = QPainter(self) qPaint = QPainter(self)
qPaint.setRenderHint(QPainter.Antialiasing, True) qPaint.setRenderHint(QPainter.Antialiasing, True)
qPaint.setPen(Qt.NoPen) qPaint.setPen(Qt.NoPen)
@@ -134,27 +132,26 @@ class NSwitch(QAbstractButton):
qPaint.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR) qPaint.drawRoundedRect(0, 0, self._xW, self._xH, self._xR, self._xR)
qPaint.setBrush(thumbBrush) qPaint.setBrush(thumbBrush)
qPaint.drawEllipse(self.offset - self._rR, self._rB, self._rH, self._rH) qPaint.drawEllipse(self._offset - self._rR, self._rB, self._rH, self._rH)
theFont = qPaint.font() theFont = qPaint.font()
theFont.setPixelSize(self._xT) theFont.setPixelSize(self._xT)
qPaint.setPen(textColor) qPaint.setPen(textColor)
qPaint.setFont(theFont) qPaint.setFont(theFont)
qPaint.drawText( qPaint.drawText(
QRectF(self.offset - self._rR, self._rB, self._rH, self._rH), QRectF(self._offset - self._rR, self._rB, self._rH, self._rH),
Qt.AlignCenter, thumbText Qt.AlignCenter, thumbText
) )
return return
def mouseReleaseEvent(self, event): def mouseReleaseEvent(self, event: QMouseEvent) -> None:
"""Animate the switch on mouse release. """Animate the switch on mouse release."""
"""
super().mouseReleaseEvent(event) super().mouseReleaseEvent(event)
if event.button() == Qt.LeftButton: if event.button() == Qt.LeftButton:
doAnim = QPropertyAnimation(self, b"offset", self) doAnim = QPropertyAnimation(self, b"offset", self)
doAnim.setDuration(120) doAnim.setDuration(120)
doAnim.setStartValue(self.offset) doAnim.setStartValue(self._offset)
if self.isChecked(): if self.isChecked():
doAnim.setEndValue(self._xW - self._xR) doAnim.setEndValue(self._xW - self._xR)
else: else:
@@ -162,9 +159,8 @@ class NSwitch(QAbstractButton):
doAnim.start() doAnim.start()
return return
def enterEvent(self, event): def enterEvent(self, event: QEvent) -> None:
"""Change the cursor when hovering the button. """Change the cursor when hovering the button."""
"""
self.setCursor(Qt.PointingHandCursor) self.setCursor(Qt.PointingHandCursor)
super().enterEvent(event) super().enterEvent(event)
return return
+9 -9
View File
@@ -23,8 +23,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
""" """
from __future__ import annotations from __future__ import annotations
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtWidgets import QGridLayout, QLabel, QScrollArea, QSizePolicy, QWidget from PyQt5.QtWidgets import QGridLayout, QLabel, QScrollArea, QSizePolicy, QWidget
from novelwriter.extensions.switch import NSwitch from novelwriter.extensions.switch import NSwitch
@@ -39,7 +39,7 @@ class NSwitchBox(QScrollArea):
switchToggled = pyqtSignal(str, bool) switchToggled = pyqtSignal(str, bool)
def __init__(self, parent: QWidget, baseSize: int): def __init__(self, parent: QWidget, baseSize: int) -> None:
super().__init__(parent=parent) super().__init__(parent=parent)
self._index = 0 self._index = 0
self._hSwitch = baseSize self._hSwitch = baseSize
@@ -49,7 +49,7 @@ class NSwitchBox(QScrollArea):
self.clear() self.clear()
return return
def clear(self): def clear(self) -> None:
"""Rebuild the content of the core widget.""" """Rebuild the content of the core widget."""
self._index = 0 self._index = 0
self._widgets = [] self._widgets = []
@@ -66,7 +66,7 @@ class NSwitchBox(QScrollArea):
return return
def addLabel(self, text: str): def addLabel(self, text: str) -> None:
"""Add a header label to the content box.""" """Add a header label to the content box."""
label = QLabel(text) label = QLabel(text)
font = label.font() font = label.font()
@@ -77,7 +77,7 @@ class NSwitchBox(QScrollArea):
self._bumpIndex() self._bumpIndex()
return return
def addItem(self, qIcon: QIcon, text: str, identifier: str, default: bool = False): def addItem(self, qIcon: QIcon, text: str, identifier: str, default: bool = False) -> None:
"""Add an item to the content box.""" """Add an item to the content box."""
icon = QLabel("") icon = QLabel("")
icon.setAlignment(Qt.AlignRight | Qt.AlignVCenter) icon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
@@ -97,7 +97,7 @@ class NSwitchBox(QScrollArea):
return return
def addSeparator(self): def addSeparator(self) -> None:
"""Add a blank entry in the content box.""" """Add a blank entry in the content box."""
spacer = QWidget() spacer = QWidget()
spacer.setFixedHeight(int(0.5*self._sIcon)) spacer.setFixedHeight(int(0.5*self._sIcon))
@@ -106,7 +106,7 @@ class NSwitchBox(QScrollArea):
self._bumpIndex() self._bumpIndex()
return return
def setInnerContentsMargins(self, left: int, top: int, right: int, bottom: int): def setInnerContentsMargins(self, left: int, top: int, right: int, bottom: int) -> None:
"""Set the contents margins of the inner layout.""" """Set the contents margins of the inner layout."""
self._content.setContentsMargins(left, top, right, bottom) self._content.setContentsMargins(left, top, right, bottom)
return return
@@ -115,12 +115,12 @@ class NSwitchBox(QScrollArea):
# Internal Functions # Internal Functions
## ##
def _emitSwitchSignal(self, identifier: str, state: bool): def _emitSwitchSignal(self, identifier: str, state: bool) -> None:
"""Emit a signal for a switch toggle.""" """Emit a signal for a switch toggle."""
self.switchToggled.emit(identifier, state) self.switchToggled.emit(identifier, state)
return return
def _bumpIndex(self): def _bumpIndex(self) -> None:
"""Increase the index counter and make sure only the last """Increase the index counter and make sure only the last
columns is stretching. columns is stretching.
""" """
-8
View File
@@ -366,14 +366,6 @@ def testBaseConfig_Internal(monkeypatch, fncPath):
# Function _packList # Function _packList
assert tstConf._packList(["A", 1, 2.0, None, False]) == "A, 1, 2.0, None, False" assert tstConf._packList(["A", 1, 2.0, None, False]) == "A, 1, 2.0, None, False"
# Function _checkNone
assert tstConf._checkNone(None) is None
assert tstConf._checkNone("None") is None
assert tstConf._checkNone("none") is None
assert tstConf._checkNone("NONE") is None
assert tstConf._checkNone("NoNe") is None
assert tstConf._checkNone(123456) == 123456
# Function _checkOptionalPackages # Function _checkOptionalPackages
# (Assumes enchant package exists and is importable) # (Assumes enchant package exists and is importable)
tstConf._checkOptionalPackages() tstConf._checkOptionalPackages()