Fix some typing issues
This commit is contained in:
+50
-58
@@ -29,13 +29,13 @@ import hashlib
|
|||||||
import logging
|
import logging
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any, Literal
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication
|
from PyQt5.QtCore import QCoreApplication
|
||||||
from PyQt5.QtWidgets import qApp
|
from PyQt5.QtWidgets import QWidget, qApp
|
||||||
|
|
||||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
@@ -113,14 +113,14 @@ def checkHandle(value, default, allowNone=False):
|
|||||||
|
|
||||||
|
|
||||||
def checkUuid(value: Any, default: str) -> str:
|
def checkUuid(value: Any, default: str) -> str:
|
||||||
"""Try to process a value as an uuid, or return a default."""
|
"""Try to process a value as an UUID, or return a default."""
|
||||||
try:
|
try:
|
||||||
return str(uuid.UUID(value))
|
return str(uuid.UUID(value))
|
||||||
except Exception:
|
except Exception:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def checkPath(value, default):
|
def checkPath(value: Any, default: Path) -> Path:
|
||||||
"""Check if a value is a valid path. Non-empty strings are accepted.
|
"""Check if a value is a valid path. Non-empty strings are accepted.
|
||||||
"""
|
"""
|
||||||
if isinstance(value, Path):
|
if isinstance(value, Path):
|
||||||
@@ -135,7 +135,7 @@ def checkPath(value, default):
|
|||||||
# Validator Functions
|
# Validator Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def isHandle(value):
|
def isHandle(value: Any) -> bool:
|
||||||
"""Check if a string is a valid novelWriter handle.
|
"""Check if a string is a valid novelWriter handle.
|
||||||
Note: This is case sensitive. Must be lower case!
|
Note: This is case sensitive. Must be lower case!
|
||||||
"""
|
"""
|
||||||
@@ -149,9 +149,8 @@ def isHandle(value):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def isTitleTag(value):
|
def isTitleTag(value: Any) -> bool:
|
||||||
"""Check if a string is a valid title tag string.
|
"""Check if a string is a valid title tag string."""
|
||||||
"""
|
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
return False
|
return False
|
||||||
if len(value) != 5:
|
if len(value) != 5:
|
||||||
@@ -164,27 +163,23 @@ def isTitleTag(value):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def isItemClass(value):
|
def isItemClass(value: str) -> bool:
|
||||||
"""Check if a string is a valid nwItemClass identifier.
|
"""Check if a string is a valid nwItemClass identifier."""
|
||||||
"""
|
|
||||||
return value in nwItemClass.__members__
|
return value in nwItemClass.__members__
|
||||||
|
|
||||||
|
|
||||||
def isItemType(value):
|
def isItemType(value: str) -> bool:
|
||||||
"""Check if a string is a valid nwItemType identifier.
|
"""Check if a string is a valid nwItemType identifier."""
|
||||||
"""
|
|
||||||
return value in nwItemType.__members__
|
return value in nwItemType.__members__
|
||||||
|
|
||||||
|
|
||||||
def isItemLayout(value):
|
def isItemLayout(value: str) -> bool:
|
||||||
"""Check if a string is a valid nwItemLayout identifier.
|
"""Check if a string is a valid nwItemLayout identifier."""
|
||||||
"""
|
|
||||||
return value in nwItemLayout.__members__
|
return value in nwItemLayout.__members__
|
||||||
|
|
||||||
|
|
||||||
def hexToInt(value, default=0):
|
def hexToInt(value: Any, default: int = 0) -> int:
|
||||||
"""Convert a hex string to an integer.
|
"""Convert a hex string to an integer."""
|
||||||
"""
|
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
try:
|
try:
|
||||||
return int(value, 16)
|
return int(value, 16)
|
||||||
@@ -193,13 +188,13 @@ def hexToInt(value, default=0):
|
|||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
def minmax(value, minVal, maxVal):
|
def minmax(value: int, minVal: int, maxVal: int) -> int:
|
||||||
"""Make sure an integer is between min and max value (inclusive).
|
"""Make sure an integer is between min and max value (inclusive).
|
||||||
"""
|
"""
|
||||||
return min(maxVal, max(minVal, value))
|
return min(maxVal, max(minVal, value))
|
||||||
|
|
||||||
|
|
||||||
def checkIntTuple(value, valid, default):
|
def checkIntTuple(value: int, valid: tuple | list | set, default: int) -> int:
|
||||||
"""Check that an int is an element of a tuple. If it isn't, return
|
"""Check that an int is an element of a tuple. If it isn't, return
|
||||||
the default value.
|
the default value.
|
||||||
"""
|
"""
|
||||||
@@ -213,7 +208,7 @@ def checkIntTuple(value, valid, default):
|
|||||||
# Formatting Functions
|
# Formatting Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def formatInt(value):
|
def formatInt(value: int) -> str:
|
||||||
"""Formats an integer with k, M, G etc.
|
"""Formats an integer with k, M, G etc.
|
||||||
"""
|
"""
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
@@ -260,20 +255,19 @@ def formatTime(t: int) -> str:
|
|||||||
# String Functions
|
# String Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def simplified(string):
|
def simplified(text: str) -> str:
|
||||||
"""Take a string an strip leading and trailing whitespaces, and
|
"""Take a string and strip leading and trailing whitespaces, and
|
||||||
replace all occurences of (multiple) whitespaces with a 0x20 space.
|
replace all occurences of (multiple) whitespaces with a 0x20 space.
|
||||||
"""
|
"""
|
||||||
return " ".join(str(string).strip().split())
|
return " ".join(str(text).strip().split())
|
||||||
|
|
||||||
|
|
||||||
def yesNo(value):
|
def yesNo(value: int | bool | None) -> Literal["yes", "no"]:
|
||||||
"""Convert a boolean evaluated variable to a yes or no.
|
"""Convert a boolean evaluated variable to a yes or no."""
|
||||||
"""
|
|
||||||
return "yes" if value else "no"
|
return "yes" if value else "no"
|
||||||
|
|
||||||
|
|
||||||
def transferCase(source, target):
|
def transferCase(source: str, target: str) -> str:
|
||||||
"""Transfers the case of the source word to the target word. This
|
"""Transfers the case of the source word to the target word. This
|
||||||
will consider all upper or lower, and first char capitalisation.
|
will consider all upper or lower, and first char capitalisation.
|
||||||
"""
|
"""
|
||||||
@@ -295,7 +289,7 @@ def transferCase(source, target):
|
|||||||
return theResult
|
return theResult
|
||||||
|
|
||||||
|
|
||||||
def fuzzyTime(seconds):
|
def fuzzyTime(seconds: int) -> str:
|
||||||
"""Converts a time difference in seconds into a fuzzy time string.
|
"""Converts a time difference in seconds into a fuzzy time string.
|
||||||
"""
|
"""
|
||||||
if seconds < 0:
|
if seconds < 0:
|
||||||
@@ -356,7 +350,7 @@ def fuzzyTime(seconds):
|
|||||||
).format(int(round(seconds/31557600)))
|
).format(int(round(seconds/31557600)))
|
||||||
|
|
||||||
|
|
||||||
def numberToRoman(value, toLower=False):
|
def numberToRoman(value: int, toLower: bool = False) -> str:
|
||||||
"""Convert an integer to a Roman number.
|
"""Convert an integer to a Roman number.
|
||||||
"""
|
"""
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
@@ -384,7 +378,7 @@ def numberToRoman(value, toLower=False):
|
|||||||
# Encoder Functions
|
# Encoder Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def jsonEncode(data, n=0, nmax=0):
|
def jsonEncode(data: dict | list | tuple, n: int = 0, nmax: int = 0) -> str:
|
||||||
"""Encode a dictionary, list or tuple as a json object or array, and
|
"""Encode a dictionary, list or tuple as a json object or array, and
|
||||||
indent from level n up to a max level nmax if nmax is larger than 0.
|
indent from level n up to a max level nmax if nmax is larger than 0.
|
||||||
"""
|
"""
|
||||||
@@ -474,7 +468,7 @@ def xmlIndent(tree: ET.Element | ET.ElementTree):
|
|||||||
# File and File System Functions
|
# File and File System Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def readTextFile(path):
|
def readTextFile(path: str | Path) -> str:
|
||||||
"""Read the content of a text file in a robust manner.
|
"""Read the content of a text file in a robust manner.
|
||||||
"""
|
"""
|
||||||
path = Path(path)
|
path = Path(path)
|
||||||
@@ -488,7 +482,7 @@ def readTextFile(path):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def makeFileNameSafe(value):
|
def makeFileNameSafe(value: str) -> str:
|
||||||
"""Returns a filename safe string of the value.
|
"""Returns a filename safe string of the value.
|
||||||
"""
|
"""
|
||||||
clean = ""
|
clean = ""
|
||||||
@@ -498,7 +492,7 @@ def makeFileNameSafe(value):
|
|||||||
return clean
|
return clean
|
||||||
|
|
||||||
|
|
||||||
def sha256sum(path):
|
def sha256sum(path: str | Path) -> str | None:
|
||||||
"""Make a shasum of a file using a buffer.
|
"""Make a shasum of a file using a buffer.
|
||||||
Based on: https://stackoverflow.com/a/44873382/5825851
|
Based on: https://stackoverflow.com/a/44873382/5825851
|
||||||
"""
|
"""
|
||||||
@@ -521,7 +515,7 @@ def sha256sum(path):
|
|||||||
# Other Functions
|
# Other Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
def getGuiItem(objName):
|
def getGuiItem(objName: str) -> QWidget | None:
|
||||||
"""Returns a QtWidget based on its objectName.
|
"""Returns a QtWidget based on its objectName.
|
||||||
"""
|
"""
|
||||||
for qWidget in qApp.topLevelWidgets():
|
for qWidget in qApp.topLevelWidgets():
|
||||||
@@ -535,50 +529,49 @@ def getGuiItem(objName):
|
|||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
class NWConfigParser(ConfigParser):
|
class NWConfigParser(ConfigParser):
|
||||||
|
"""Common: Adapted Config Parser
|
||||||
|
|
||||||
|
This is a subclass of the standard config parser that adds type safe
|
||||||
|
helper functions, and support for lists.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
def rdStr(self, section, option, default):
|
def rdStr(self, section: str, option: str, default: str) -> str:
|
||||||
"""Read string value.
|
"""Read string value."""
|
||||||
"""
|
|
||||||
return self.get(section, option, fallback=default)
|
return self.get(section, option, fallback=default)
|
||||||
|
|
||||||
def rdInt(self, section, option, default):
|
def rdInt(self, section: str, option: str, default: int) -> int:
|
||||||
"""Read integer value.
|
"""Read integer value."""
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
return self.getint(section, option, fallback=default)
|
return self.getint(section, option, fallback=default)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error("Could not read '%s':'%s' from config", section, option)
|
logger.error("Could not read '%s':'%s' from config", section, option)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def rdFlt(self, section, option, default):
|
def rdFlt(self, section: str, option: str, default: float) -> float:
|
||||||
"""Read float value.
|
"""Read float value."""
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
return self.getfloat(section, option, fallback=default)
|
return self.getfloat(section, option, fallback=default)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error("Could not read '%s':'%s' from config", section, option)
|
logger.error("Could not read '%s':'%s' from config", section, option)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def rdBool(self, section, option, default):
|
def rdBool(self, section: str, option: str, default: bool) -> bool:
|
||||||
"""Read boolean value.
|
"""Read boolean value."""
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
return self.getboolean(section, option, fallback=default)
|
return self.getboolean(section, option, fallback=default)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logger.error("Could not read '%s':'%s' from config", section, option)
|
logger.error("Could not read '%s':'%s' from config", section, option)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def rdPath(self, section, option, default):
|
def rdPath(self, section: str, option: str, default: Path) -> Path:
|
||||||
"""Read a path value.
|
"""Read a Path value."""
|
||||||
"""
|
|
||||||
return checkPath(self.get(section, option, fallback=default), default)
|
return checkPath(self.get(section, option, fallback=default), default)
|
||||||
|
|
||||||
def rdStrList(self, section, option, default):
|
def rdStrList(self, section: str, option: str, default: list[str]) -> list[str]:
|
||||||
"""Read string list.
|
"""Read string list."""
|
||||||
"""
|
|
||||||
result = default.copy() if isinstance(default, list) else []
|
result = default.copy() if isinstance(default, list) else []
|
||||||
if self.has_option(section, option):
|
if self.has_option(section, option):
|
||||||
data = self.get(section, option, fallback="").split(",")
|
data = self.get(section, option, fallback="").split(",")
|
||||||
@@ -586,9 +579,8 @@ class NWConfigParser(ConfigParser):
|
|||||||
result[i] = data[i].strip()
|
result[i] = data[i].strip()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def rdIntList(self, section, option, default):
|
def rdIntList(self, section: str, option: str, default: list[int]) -> list[int]:
|
||||||
"""Read integer list.
|
"""Read integer list."""
|
||||||
"""
|
|
||||||
result = default.copy() if isinstance(default, list) else []
|
result = default.copy() if isinstance(default, list) else []
|
||||||
if self.has_option(section, option):
|
if self.has_option(section, option):
|
||||||
data = self.get(section, option, fallback="").split(",")
|
data = self.get(section, option, fallback="").split(",")
|
||||||
|
|||||||
@@ -150,17 +150,17 @@ class BuildSettings:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Return the build name."""
|
"""The build name."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def buildID(self) -> str:
|
def buildID(self) -> str:
|
||||||
"""Return the build ID."""
|
"""The build ID as an UUID."""
|
||||||
return self._uuid
|
return self._uuid
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def changed(self) -> bool:
|
def changed(self) -> bool:
|
||||||
"""Return the changed status of the build."""
|
"""The changed status of the build."""
|
||||||
return self._changed
|
return self._changed
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -190,7 +190,7 @@ class BuildSettings:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def getFloat(self, key: str) -> float:
|
def getFloat(self, key: str) -> float:
|
||||||
"""Type safe value access for float."""
|
"""Type safe value access for floats."""
|
||||||
value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None)[1]))
|
value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None)[1]))
|
||||||
if isinstance(value, float):
|
if isinstance(value, float):
|
||||||
return value
|
return value
|
||||||
|
|||||||
+27
-19
@@ -1,7 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
novelWriter – Project Options Cache
|
novelWriter – Project Options Cache
|
||||||
===================================
|
===================================
|
||||||
Data class for user-defined GUI project options
|
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-10-21 [0.3.1]
|
Created: 2019-10-21 [0.3.1]
|
||||||
@@ -23,17 +22,22 @@ General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.common import checkBool, checkFloat, checkInt, checkString
|
from novelwriter.common import checkBool, checkFloat, checkInt, checkString
|
||||||
from novelwriter.constants import nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
|
|
||||||
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
|
from novelwriter.core.project import NWProject
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
VALID_MAP = {
|
VALID_MAP = {
|
||||||
@@ -63,9 +67,15 @@ VALID_MAP = {
|
|||||||
|
|
||||||
|
|
||||||
class OptionState:
|
class OptionState:
|
||||||
|
"""Core: GUI Options Storage
|
||||||
|
|
||||||
def __init__(self, theProject):
|
A class for storing the state of the GUI. The data is stored per
|
||||||
self.theProject = theProject
|
project. Settings that should be project-independent are stored in
|
||||||
|
the Config instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, project: NWProject):
|
||||||
|
self._project = project
|
||||||
self._theState = {}
|
self._theState = {}
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -73,10 +83,10 @@ class OptionState:
|
|||||||
# Load and Save Cache
|
# Load and Save Cache
|
||||||
##
|
##
|
||||||
|
|
||||||
def loadSettings(self):
|
def loadSettings(self) -> bool:
|
||||||
"""Load the options dictionary from the project settings file.
|
"""Load the options dictionary from the project settings file.
|
||||||
"""
|
"""
|
||||||
stateFile = self.theProject.storage.getMetaFile(nwFiles.OPTS_FILE)
|
stateFile = self._project.storage.getMetaFile(nwFiles.OPTS_FILE)
|
||||||
if not isinstance(stateFile, Path):
|
if not isinstance(stateFile, Path):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -101,10 +111,9 @@ class OptionState:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def saveSettings(self):
|
def saveSettings(self) -> bool:
|
||||||
"""Save the options dictionary to the project settings file.
|
"""Save the options dictionary to the project settings file."""
|
||||||
"""
|
stateFile = self._project.storage.getMetaFile(nwFiles.OPTS_FILE)
|
||||||
stateFile = self.theProject.storage.getMetaFile(nwFiles.OPTS_FILE)
|
|
||||||
if not isinstance(stateFile, Path):
|
if not isinstance(stateFile, Path):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -123,9 +132,8 @@ class OptionState:
|
|||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
|
|
||||||
def setValue(self, group, name, value):
|
def setValue(self, group: str, name: str, value: Any) -> bool:
|
||||||
"""Save a value, with a given group and name.
|
"""Save a value, with a given group and name."""
|
||||||
"""
|
|
||||||
if group not in VALID_MAP:
|
if group not in VALID_MAP:
|
||||||
logger.error("Unknown option group '%s'", group)
|
logger.error("Unknown option group '%s'", group)
|
||||||
return False
|
return False
|
||||||
@@ -148,7 +156,7 @@ class OptionState:
|
|||||||
# Getters
|
# Getters
|
||||||
##
|
##
|
||||||
|
|
||||||
def getValue(self, group, name, default):
|
def getValue(self, group: str, name: str, default: Any) -> Any:
|
||||||
"""Return an arbitrary type value, if it exists. Otherwise,
|
"""Return an arbitrary type value, if it exists. Otherwise,
|
||||||
return the default value.
|
return the default value.
|
||||||
"""
|
"""
|
||||||
@@ -156,7 +164,7 @@ class OptionState:
|
|||||||
return self._theState[group].get(name, default)
|
return self._theState[group].get(name, default)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def getString(self, group, name, default):
|
def getString(self, group: str, name: str, default: str) -> str:
|
||||||
"""Return the value as a string, if it exists. Otherwise, return
|
"""Return the value as a string, if it exists. Otherwise, return
|
||||||
the default value.
|
the default value.
|
||||||
"""
|
"""
|
||||||
@@ -164,7 +172,7 @@ class OptionState:
|
|||||||
return checkString(self._theState[group].get(name, default), default)
|
return checkString(self._theState[group].get(name, default), default)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def getInt(self, group, name, default):
|
def getInt(self, group: str, name: str, default: int) -> int:
|
||||||
"""Return the value as an int, if it exists. Otherwise, return
|
"""Return the value as an int, if it exists. Otherwise, return
|
||||||
the default value.
|
the default value.
|
||||||
"""
|
"""
|
||||||
@@ -172,7 +180,7 @@ class OptionState:
|
|||||||
return checkInt(self._theState[group].get(name, default), default)
|
return checkInt(self._theState[group].get(name, default), default)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def getFloat(self, group, name, default):
|
def getFloat(self, group: str, name: str, default: float) -> float:
|
||||||
"""Return the value as a float, if it exists. Otherwise, return
|
"""Return the value as a float, if it exists. Otherwise, return
|
||||||
the default value.
|
the default value.
|
||||||
"""
|
"""
|
||||||
@@ -180,7 +188,7 @@ class OptionState:
|
|||||||
return checkFloat(self._theState[group].get(name, default), default)
|
return checkFloat(self._theState[group].get(name, default), default)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def getBool(self, group, name, default):
|
def getBool(self, group: str, name: str, default: bool) -> bool:
|
||||||
"""Return the value as a bool, if it exists. Otherwise, return
|
"""Return the value as a bool, if it exists. Otherwise, return
|
||||||
the default value.
|
the default value.
|
||||||
"""
|
"""
|
||||||
@@ -188,9 +196,9 @@ class OptionState:
|
|||||||
return checkBool(self._theState[group].get(name, default), default)
|
return checkBool(self._theState[group].get(name, default), default)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def getEnum(self, group, name, lookup, default):
|
def getEnum(self, group: str, name: str, lookup: type, default: Enum) -> Enum:
|
||||||
"""Return the value mapped to an enum. Otherwise return the
|
"""Return the value mapped to an enum. Otherwise return the
|
||||||
default value
|
default value.
|
||||||
"""
|
"""
|
||||||
if issubclass(lookup, Enum):
|
if issubclass(lookup, Enum):
|
||||||
if group in self._theState:
|
if group in self._theState:
|
||||||
|
|||||||
@@ -285,15 +285,20 @@ class NWProjectData:
|
|||||||
self.theProject.setProjectChanged(True)
|
self.theProject.setProjectChanged(True)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setLastHandle(self, value: dict, component: str | None = None):
|
def setLastHandle(self, value: str | None, component: str):
|
||||||
"""Set a last used handle into the handle registry. If component
|
"""Set a last used handle into the handle registry for a given
|
||||||
is None, the value is assumed to be the whole dictionary of
|
component.
|
||||||
values.
|
|
||||||
"""
|
"""
|
||||||
if isinstance(component, str):
|
if isinstance(component, str):
|
||||||
self._lastHandle[component] = checkStringNone(value, None)
|
self._lastHandle[component] = checkStringNone(value, None)
|
||||||
self.theProject.setProjectChanged(True)
|
self.theProject.setProjectChanged(True)
|
||||||
elif isinstance(value, dict):
|
return
|
||||||
|
|
||||||
|
def setLastHandles(self, value: dict):
|
||||||
|
"""Set the full last handles dictionary to a new set of values.
|
||||||
|
This is intended to be used at project load.
|
||||||
|
"""
|
||||||
|
if isinstance(value, dict):
|
||||||
for key, entry in value.items():
|
for key, entry in value.items():
|
||||||
if key in self._lastHandle:
|
if key in self._lastHandle:
|
||||||
self._lastHandle[key] = str(entry) if isHandle(entry) else None
|
self._lastHandle[key] = str(entry) if isHandle(entry) else None
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ import xml.etree.ElementTree as ET
|
|||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from time import time
|
from time import time
|
||||||
from pathlib import Path
|
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter import __version__, __hexversion__
|
from novelwriter import __version__, __hexversion__
|
||||||
from novelwriter.common import (
|
from novelwriter.common import (
|
||||||
@@ -284,7 +284,7 @@ class ProjectXMLReader:
|
|||||||
elif xItem.tag == "importance":
|
elif xItem.tag == "importance":
|
||||||
self._parseStatusImport(xItem, data.itemImport)
|
self._parseStatusImport(xItem, data.itemImport)
|
||||||
elif xItem.tag == "lastHandle":
|
elif xItem.tag == "lastHandle":
|
||||||
data.setLastHandle(self._parseDictKeyText(xItem))
|
data.setLastHandles(self._parseDictKeyText(xItem))
|
||||||
elif xItem.tag == "autoReplace":
|
elif xItem.tag == "autoReplace":
|
||||||
if self._version >= 0x0102:
|
if self._version >= 0x0102:
|
||||||
data.setAutoReplace(self._parseDictKeyText(xItem))
|
data.setAutoReplace(self._parseDictKeyText(xItem))
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class NWStorage:
|
|||||||
xmlWriter = ProjectXMLWriter(self._runtimePath)
|
xmlWriter = ProjectXMLWriter(self._runtimePath)
|
||||||
return xmlWriter
|
return xmlWriter
|
||||||
|
|
||||||
def getDocument(self, tHandle: str) -> NWDocument:
|
def getDocument(self, tHandle: str | None) -> NWDocument:
|
||||||
"""Return a document wrapper object."""
|
"""Return a document wrapper object."""
|
||||||
if self._runtimePath is not None:
|
if self._runtimePath is not None:
|
||||||
return NWDocument(self._project, tHandle)
|
return NWDocument(self._project, tHandle)
|
||||||
|
|||||||
Reference in New Issue
Block a user