Files
novelWriter/nw/core/options.py
T
2020-06-24 21:45:41 +02:00

256 lines
7.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- 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 = {
"GuiSessionLog": {
"widthCol0",
"widthCol1",
"sortCol",
"sortOrder",
"hideZeros",
"hideNegative",
},
"GuiDocSplit": {
"spLevel",
},
"GuiBuildNovel": {
"winWidth",
"winHeight",
"addNovel",
"addNotes",
"ignoreFlag",
"justifyText",
"excludeBody",
"textFont",
"textSize",
"noStyling",
"incSynopsis",
"incComments",
"incKeywords",
"incBodyText",
},
"GuiOutline": {
"headerOrder",
"columnWidth",
"columnHidden",
},
"GuiProjectSettings": {
"winWidth",
"winHeight",
"replaceColW",
}
}
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