Fix and optimise code (#904)

* Fix bug in early error reporting in main init
* Update docstrings and optimise code in GuiMain
* Update docstrings and optimise code in Config
* Update docstrings and optimise code in common module
* Update docstrings and optimise code in main project classes
* Update the OptionState class
* Update the spell checker class
* Update the file converter classes and extend tests
* Update the about, merge, split and item editor classes and extend tests
* Update item editor test
* Update about dialog tests
* Some minor test cleanup
* Fix typo and add clarification in contributing guide
This commit is contained in:
Veronica Berglyd Olsen
2021-10-14 20:35:42 +01:00
committed by GitHub
parent 2a06db0a2b
commit 1c45331b0a
31 changed files with 1042 additions and 666 deletions
+70 -130
View File
@@ -30,88 +30,40 @@ import logging
import novelwriter
from novelwriter.constants import nwFiles
from novelwriter.common import checkBool, checkFloat, checkInt, checkString
logger = logging.getLogger(__name__)
VALID_MAP = {
"GuiWritingStats": {
"winWidth", "winHeight", "widthCol0", "widthCol1", "widthCol2",
"widthCol3", "sortCol", "sortOrder", "incNovel", "incNotes",
"hideZeros", "hideNegative", "groupByDay", "showIdleTime", "histMax"
},
"GuiDocSplit": {"spLevel"},
"GuiBuildNovel": {
"winWidth", "winHeight", "boxWidth", "docWidth", "addNovel",
"addNotes", "ignoreFlag", "justifyText", "excludeBody", "textFont",
"textSize", "lineHeight", "noStyling", "incSynopsis", "incComments",
"incKeywords", "incBodyText", "replaceTabs", "replaceUCode"
},
"GuiOutline": {"headerOrder", "columnWidth", "columnHidden"},
"GuiProjectSettings": {
"winWidth", "winHeight", "replaceColW", "statusColW", "importColW"
},
"GuiProjectDetails": {
"winWidth", "winHeight", "widthCol0", "widthCol1", "widthCol2",
"widthCol3", "widthCol4", "wordsPerPage", "countFrom", "clearDouble"
},
"GuiWordList": {"winWidth", "winHeight"}
}
class OptionState():
def __init__(self, theProject):
self.theProject = theProject
self.theState = {}
self.validMap = {
"GuiWritingStats": {
"winWidth",
"winHeight",
"widthCol0",
"widthCol1",
"widthCol2",
"widthCol3",
"sortCol",
"sortOrder",
"incNovel",
"incNotes",
"hideZeros",
"hideNegative",
"groupByDay",
"showIdleTime",
"histMax",
},
"GuiDocSplit": {
"spLevel",
},
"GuiBuildNovel": {
"winWidth",
"winHeight",
"boxWidth",
"docWidth",
"addNovel",
"addNotes",
"ignoreFlag",
"justifyText",
"excludeBody",
"textFont",
"textSize",
"lineHeight",
"noStyling",
"incSynopsis",
"incComments",
"incKeywords",
"incBodyText",
"replaceTabs",
"replaceUCode",
},
"GuiOutline": {
"headerOrder",
"columnWidth",
"columnHidden",
},
"GuiProjectSettings": {
"winWidth",
"winHeight",
"replaceColW",
"statusColW",
"importColW",
},
"GuiProjectDetails": {
"winWidth",
"winHeight",
"widthCol0",
"widthCol1",
"widthCol2",
"widthCol3",
"widthCol4",
"wordsPerPage",
"countFrom",
"clearDouble",
},
"GuiWordList": {
"winWidth",
"winHeight",
}
}
self._theState = {}
return
##
@@ -139,11 +91,11 @@ class OptionState():
# Filter out unused variables
for aGroup in theState:
if aGroup in self.validMap:
self.theState[aGroup] = {}
if aGroup in VALID_MAP:
self._theState[aGroup] = {}
for anOpt in theState[aGroup]:
if anOpt in self.validMap[aGroup]:
self.theState[aGroup][anOpt] = theState[aGroup][anOpt]
if anOpt in VALID_MAP[aGroup]:
self._theState[aGroup][anOpt] = theState[aGroup][anOpt]
return True
@@ -158,7 +110,7 @@ class OptionState():
try:
with open(stateFile, mode="w+", encoding="utf-8") as outFile:
json.dump(self.theState, outFile, indent=2)
json.dump(self._theState, outFile, indent=2)
except Exception:
logger.error("Failed to save GUI options file")
novelwriter.logException()
@@ -170,21 +122,21 @@ class OptionState():
# Setters
##
def setValue(self, setGroup, setName, setValue):
def setValue(self, group, name, value):
"""Saves a value, with a given group and name.
"""
if setGroup not in self.validMap:
logger.error("Unknown option group '%s'", setGroup)
if group not in VALID_MAP:
logger.error("Unknown option group '%s'", group)
return False
if setName not in self.validMap[setGroup]:
logger.error("Unknown option name '%s'", setName)
if name not in VALID_MAP[group]:
logger.error("Unknown option name '%s'", name)
return False
if setGroup not in self.theState:
self.theState[setGroup] = {}
if group not in self._theState:
self._theState[group] = {}
self.theState[setGroup][setName] = setValue
self._theState[group][name] = value
return True
@@ -192,79 +144,67 @@ class OptionState():
# Getters
##
def getValue(self, getGroup, getName, defaultValue):
def getValue(self, group, name, default):
"""Return an arbitrary type value, if it exists. Otherwise,
return the default value.
"""
if getGroup in self.theState:
if getName in self.theState[getGroup]:
return self.theState[getGroup][getName]
return defaultValue
if group in self._theState:
return self._theState[group].get(name, default)
return default
def getString(self, getGroup, getName, defaultValue):
def getString(self, group, name, default):
"""Return the value as a string, if it exists. Otherwise, return
the default value.
"""
if getGroup in self.theState:
if getName in self.theState[getGroup]:
return str(self.theState[getGroup][getName])
return defaultValue
if group in self._theState:
return checkString(self._theState[group].get(name, default), default)
return default
def getInt(self, getGroup, getName, defaultValue):
def getInt(self, group, name, default):
"""Return the value as an int, if it exists. Otherwise, return
the default value.
"""
if getGroup in self.theState:
if getName in self.theState[getGroup]:
try:
return int(self.theState[getGroup][getName])
except Exception as e:
logger.warning(str(e))
return defaultValue
return defaultValue
if group in self._theState:
return checkInt(self._theState[group].get(name, default), default)
return default
def getFloat(self, getGroup, getName, defaultValue):
def getFloat(self, group, name, default):
"""Return the value as a float, if it exists. Otherwise, return
the default value.
"""
if getGroup in self.theState:
if getName in self.theState[getGroup]:
try:
return float(self.theState[getGroup][getName])
except Exception as e:
logger.warning(str(e))
return defaultValue
return defaultValue
if group in self._theState:
return checkFloat(self._theState[group].get(name, default), default)
return default
def getBool(self, getGroup, getName, defaultValue):
def getBool(self, group, name, default):
"""Return the value as a bool, if it exists. Otherwise, return
the default value.
"""
if getGroup in self.theState:
if getName in self.theState[getGroup]:
return bool(self.theState[getGroup][getName])
return defaultValue
if group in self._theState:
if name in self._theState[group]:
return checkBool(self._theState[group].get(name, default), default)
return default
##
# Validators
##
def validIntRange(self, theValue, intA, intB, intDefault):
def validIntRange(self, value, first, last, default):
"""Check that an int is in a given range. If it isn't, return
the default value.
"""
if isinstance(theValue, int):
if theValue >= intA and theValue <= intB:
return theValue
return intDefault
if isinstance(value, int):
if value >= first and value <= last:
return value
return default
def validIntTuple(self, theValue, theTuple, intDefault):
def validIntTuple(self, value, valid, default):
"""Check that an int is an element of a tuple. If it isn't,
return the default value.
"""
if isinstance(theValue, int):
if theValue in theTuple:
return theValue
return intDefault
if isinstance(value, int):
if value in valid:
return value
return default
# END Class OptionState