Moved OptionState to core/options.py
This commit is contained in:
@@ -0,0 +1,251 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""novelWriter Project Options Cache
|
||||||
|
|
||||||
|
novelWriter – Project Options Cache
|
||||||
|
=====================================
|
||||||
|
Class wrapping the project options state
|
||||||
|
|
||||||
|
File History:
|
||||||
|
Created: 2019-10-21 [0.3.1]
|
||||||
|
Rewritten: 2020-02-19 [0.4.5]
|
||||||
|
|
||||||
|
This file is a part of novelWriter
|
||||||
|
Copyright 2020, Veronica Berglyd Olsen
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import json
|
||||||
|
import nw
|
||||||
|
|
||||||
|
from os import path
|
||||||
|
|
||||||
|
from nw.constants import nwFiles
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
class OptionState():
|
||||||
|
|
||||||
|
def __init__(self, theProject):
|
||||||
|
|
||||||
|
self.mainConf = nw.CONFIG
|
||||||
|
self.theProject = theProject
|
||||||
|
|
||||||
|
self.theState = {}
|
||||||
|
self.validMap = {
|
||||||
|
"GuiSession": set([
|
||||||
|
"widthCol0",
|
||||||
|
"widthCol1",
|
||||||
|
"widthCol2",
|
||||||
|
"sortCol",
|
||||||
|
"sortOrder",
|
||||||
|
"hideZeros",
|
||||||
|
"hideNegative",
|
||||||
|
]),
|
||||||
|
"GuiDocSplit": set([
|
||||||
|
"spLevel",
|
||||||
|
]),
|
||||||
|
"GuiBuildNovel": set([
|
||||||
|
"winWidth",
|
||||||
|
"winHeight",
|
||||||
|
"addNovel",
|
||||||
|
"addNotes",
|
||||||
|
"ignoreFlag",
|
||||||
|
"justifyText",
|
||||||
|
"excludeBody",
|
||||||
|
"textFont",
|
||||||
|
"textSize",
|
||||||
|
"noStyling",
|
||||||
|
"incSynopsis",
|
||||||
|
"incComments",
|
||||||
|
"incKeywords",
|
||||||
|
"incBodyText",
|
||||||
|
]),
|
||||||
|
"GuiOutline": set([
|
||||||
|
"headerOrder",
|
||||||
|
"columnWidth",
|
||||||
|
"columnHidden",
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Load and Save Cache
|
||||||
|
##
|
||||||
|
|
||||||
|
def loadSettings(self):
|
||||||
|
"""Load the options dictionary from the project settings file.
|
||||||
|
"""
|
||||||
|
if self.theProject.projMeta is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
stateFile = path.join(self.theProject.projMeta, nwFiles.OPTS_FILE)
|
||||||
|
theState = {}
|
||||||
|
|
||||||
|
if path.isfile(stateFile):
|
||||||
|
logger.debug("Loading GUI options file")
|
||||||
|
try:
|
||||||
|
with open(stateFile, mode="r", encoding="utf8") as inFile:
|
||||||
|
theJson = inFile.read()
|
||||||
|
theState = json.loads(theJson)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Failed to load GUI options file")
|
||||||
|
logger.error(str(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Filter out unused variables
|
||||||
|
for aGroup in theState:
|
||||||
|
if aGroup in self.validMap:
|
||||||
|
self.theState[aGroup] = {}
|
||||||
|
for anOpt in theState[aGroup]:
|
||||||
|
if anOpt in self.validMap[aGroup]:
|
||||||
|
self.theState[aGroup][anOpt] = theState[aGroup][anOpt]
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def saveSettings(self):
|
||||||
|
"""Save the options dictionary to the project settings file.
|
||||||
|
"""
|
||||||
|
if self.theProject.projMeta is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
stateFile = path.join(self.theProject.projMeta, nwFiles.OPTS_FILE)
|
||||||
|
logger.debug("Saving GUI options file")
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(stateFile, mode="w+", encoding="utf8") as outFile:
|
||||||
|
outFile.write(json.dumps(self.theState, indent=2))
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Failed to save GUI options file")
|
||||||
|
logger.error(str(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Setters
|
||||||
|
##
|
||||||
|
|
||||||
|
def setValue(self, setGroup, setName, setValue):
|
||||||
|
"""Saves a value, with a given group and name.
|
||||||
|
"""
|
||||||
|
if not setGroup in self.validMap:
|
||||||
|
logger.error("Unknown option group '%s'" % setGroup)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not setName in self.validMap[setGroup]:
|
||||||
|
logger.error("Unknown option name '%s'" % setName)
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not setGroup in self.theState:
|
||||||
|
self.theState[setGroup] = {}
|
||||||
|
|
||||||
|
self.theState[setGroup][setName] = setValue
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Getters
|
||||||
|
##
|
||||||
|
|
||||||
|
def getValue(self, getGroup, getName, defaultValue):
|
||||||
|
"""Return an arbitrary type value, if it exists. Otherwise,
|
||||||
|
return the default value.
|
||||||
|
"""
|
||||||
|
if getGroup in self.theState:
|
||||||
|
if getName in self.theState[getGroup]:
|
||||||
|
try:
|
||||||
|
return self.theState[getGroup][getName]
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(str(e))
|
||||||
|
return defaultValue
|
||||||
|
return defaultValue
|
||||||
|
|
||||||
|
def getString(self, getGroup, getName, defaultValue):
|
||||||
|
"""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]:
|
||||||
|
try:
|
||||||
|
return str(self.theState[getGroup][getName])
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(str(e))
|
||||||
|
return defaultValue
|
||||||
|
return defaultValue
|
||||||
|
|
||||||
|
def getInt(self, getGroup, getName, defaultValue):
|
||||||
|
"""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
|
||||||
|
|
||||||
|
def getFloat(self, getGroup, getName, defaultValue):
|
||||||
|
"""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
|
||||||
|
|
||||||
|
def getBool(self, getGroup, getName, defaultValue):
|
||||||
|
"""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]:
|
||||||
|
try:
|
||||||
|
return bool(self.theState[getGroup][getName])
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(str(e))
|
||||||
|
return defaultValue
|
||||||
|
return defaultValue
|
||||||
|
|
||||||
|
##
|
||||||
|
# Validators
|
||||||
|
##
|
||||||
|
|
||||||
|
def validIntRange(self, theValue, intA, intB, intDefault):
|
||||||
|
"""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
|
||||||
|
|
||||||
|
def validIntTuple(self, theValue, theTuple, intDefault):
|
||||||
|
"""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
|
||||||
|
|
||||||
|
# END Class OptionState
|
||||||
+1
-219
@@ -43,6 +43,7 @@ from nw.core.tree import NWTree
|
|||||||
from nw.core.item import NWItem
|
from nw.core.item import NWItem
|
||||||
from nw.core.document import NWDoc
|
from nw.core.document import NWDoc
|
||||||
from nw.core.status import NWStatus
|
from nw.core.status import NWStatus
|
||||||
|
from nw.core.options import OptionState
|
||||||
from nw.common import checkString, checkBool, checkInt, formatTimeStamp
|
from nw.common import checkString, checkBool, checkInt, formatTimeStamp
|
||||||
from nw.constants import (
|
from nw.constants import (
|
||||||
nwFiles, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
nwFiles, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||||
@@ -1222,222 +1223,3 @@ class NWProject():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# END Class NWProject
|
# END Class NWProject
|
||||||
|
|
||||||
# =============================================================================================== #
|
|
||||||
# OptionState
|
|
||||||
# Save the project-wise state of options that don't go into project XML or main config
|
|
||||||
# =============================================================================================== #
|
|
||||||
|
|
||||||
class OptionState():
|
|
||||||
|
|
||||||
def __init__(self, theProject):
|
|
||||||
|
|
||||||
self.mainConf = nw.CONFIG
|
|
||||||
self.theProject = theProject
|
|
||||||
|
|
||||||
self.theState = {}
|
|
||||||
self.validMap = {
|
|
||||||
"GuiSession": set([
|
|
||||||
"widthCol0",
|
|
||||||
"widthCol1",
|
|
||||||
"widthCol2",
|
|
||||||
"sortCol",
|
|
||||||
"sortOrder",
|
|
||||||
"hideZeros",
|
|
||||||
"hideNegative",
|
|
||||||
]),
|
|
||||||
"GuiDocSplit": set([
|
|
||||||
"spLevel",
|
|
||||||
]),
|
|
||||||
"GuiBuildNovel": set([
|
|
||||||
"winWidth",
|
|
||||||
"winHeight",
|
|
||||||
"addNovel",
|
|
||||||
"addNotes",
|
|
||||||
"ignoreFlag",
|
|
||||||
"justifyText",
|
|
||||||
"excludeBody",
|
|
||||||
"textFont",
|
|
||||||
"textSize",
|
|
||||||
"noStyling",
|
|
||||||
"incSynopsis",
|
|
||||||
"incComments",
|
|
||||||
"incKeywords",
|
|
||||||
"incBodyText",
|
|
||||||
]),
|
|
||||||
"GuiOutline": set([
|
|
||||||
"headerOrder",
|
|
||||||
"columnWidth",
|
|
||||||
"columnHidden",
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
##
|
|
||||||
# Load and Save Cache
|
|
||||||
##
|
|
||||||
|
|
||||||
def loadSettings(self):
|
|
||||||
"""Load the options dictionary from the project settings file.
|
|
||||||
"""
|
|
||||||
if self.theProject.projMeta is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
stateFile = path.join(self.theProject.projMeta, nwFiles.OPTS_FILE)
|
|
||||||
theState = {}
|
|
||||||
|
|
||||||
if path.isfile(stateFile):
|
|
||||||
logger.debug("Loading GUI options file")
|
|
||||||
try:
|
|
||||||
with open(stateFile, mode="r", encoding="utf8") as inFile:
|
|
||||||
theJson = inFile.read()
|
|
||||||
theState = json.loads(theJson)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Failed to load GUI options file")
|
|
||||||
logger.error(str(e))
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Filter out unused variables
|
|
||||||
for aGroup in theState:
|
|
||||||
if aGroup in self.validMap:
|
|
||||||
self.theState[aGroup] = {}
|
|
||||||
for anOpt in theState[aGroup]:
|
|
||||||
if anOpt in self.validMap[aGroup]:
|
|
||||||
self.theState[aGroup][anOpt] = theState[aGroup][anOpt]
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def saveSettings(self):
|
|
||||||
"""Save the options dictionary to the project settings file.
|
|
||||||
"""
|
|
||||||
if self.theProject.projMeta is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
stateFile = path.join(self.theProject.projMeta, nwFiles.OPTS_FILE)
|
|
||||||
logger.debug("Saving GUI options file")
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(stateFile, mode="w+", encoding="utf8") as outFile:
|
|
||||||
outFile.write(json.dumps(self.theState, indent=2))
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Failed to save GUI options file")
|
|
||||||
logger.error(str(e))
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
##
|
|
||||||
# Setters
|
|
||||||
##
|
|
||||||
|
|
||||||
def setValue(self, setGroup, setName, setValue):
|
|
||||||
"""Saves a value, with a given group and name.
|
|
||||||
"""
|
|
||||||
if not setGroup in self.validMap:
|
|
||||||
logger.error("Unknown option group '%s'" % setGroup)
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not setName in self.validMap[setGroup]:
|
|
||||||
logger.error("Unknown option name '%s'" % setName)
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not setGroup in self.theState:
|
|
||||||
self.theState[setGroup] = {}
|
|
||||||
|
|
||||||
self.theState[setGroup][setName] = setValue
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
##
|
|
||||||
# Getters
|
|
||||||
##
|
|
||||||
|
|
||||||
def getValue(self, getGroup, getName, defaultValue):
|
|
||||||
"""Return an arbitrary type value, if it exists. Otherwise,
|
|
||||||
return the default value.
|
|
||||||
"""
|
|
||||||
if getGroup in self.theState:
|
|
||||||
if getName in self.theState[getGroup]:
|
|
||||||
try:
|
|
||||||
return self.theState[getGroup][getName]
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(str(e))
|
|
||||||
return defaultValue
|
|
||||||
return defaultValue
|
|
||||||
|
|
||||||
def getString(self, getGroup, getName, defaultValue):
|
|
||||||
"""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]:
|
|
||||||
try:
|
|
||||||
return str(self.theState[getGroup][getName])
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(str(e))
|
|
||||||
return defaultValue
|
|
||||||
return defaultValue
|
|
||||||
|
|
||||||
def getInt(self, getGroup, getName, defaultValue):
|
|
||||||
"""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
|
|
||||||
|
|
||||||
def getFloat(self, getGroup, getName, defaultValue):
|
|
||||||
"""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
|
|
||||||
|
|
||||||
def getBool(self, getGroup, getName, defaultValue):
|
|
||||||
"""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]:
|
|
||||||
try:
|
|
||||||
return bool(self.theState[getGroup][getName])
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(str(e))
|
|
||||||
return defaultValue
|
|
||||||
return defaultValue
|
|
||||||
|
|
||||||
##
|
|
||||||
# Validators
|
|
||||||
##
|
|
||||||
|
|
||||||
def validIntRange(self, theValue, intA, intB, intDefault):
|
|
||||||
"""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
|
|
||||||
|
|
||||||
def validIntTuple(self, theValue, theTuple, intDefault):
|
|
||||||
"""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
|
|
||||||
|
|
||||||
# END Class OptionState
|
|
||||||
|
|||||||
Reference in New Issue
Block a user