Complete loading project xml via data class
This commit is contained in:
@@ -38,8 +38,8 @@ from PyQt5.QtCore import QCoreApplication
|
|||||||
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
|
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.common import (
|
from novelwriter.common import (
|
||||||
checkString, checkStringNone, isHandle, formatTimeStamp, makeFileNameSafe,
|
checkStringNone, isHandle, formatTimeStamp, makeFileNameSafe, hexToInt,
|
||||||
hexToInt, minmax, simplified
|
minmax, simplified
|
||||||
)
|
)
|
||||||
from novelwriter.constants import trConst, nwFiles, nwLabels
|
from novelwriter.constants import trConst, nwFiles, nwLabels
|
||||||
from novelwriter.core.tree import NWTree
|
from novelwriter.core.tree import NWTree
|
||||||
@@ -63,8 +63,8 @@ class NWProject:
|
|||||||
self.mainConf = novelwriter.CONFIG
|
self.mainConf = novelwriter.CONFIG
|
||||||
self.mainGui = mainGui
|
self.mainGui = mainGui
|
||||||
|
|
||||||
|
# Project Data
|
||||||
self._data = NWProjectData()
|
self._data = NWProjectData()
|
||||||
self._raw = {}
|
|
||||||
|
|
||||||
# Core Elements
|
# Core Elements
|
||||||
self._optState = OptionState(self) # Project-specific GUI options
|
self._optState = OptionState(self) # Project-specific GUI options
|
||||||
@@ -84,14 +84,8 @@ class NWProject:
|
|||||||
self.projCache = None # The full path to the project's cache folder
|
self.projCache = None # The full path to the project's cache folder
|
||||||
self.projContent = None # The full path to the project's content folder
|
self.projContent = None # The full path to the project's content folder
|
||||||
self.projDict = None # The spell check dictionary
|
self.projDict = None # The spell check dictionary
|
||||||
self.projSpell = None # The spell check language, if different than default
|
|
||||||
self.projFiles = [] # A list of all files in the content folder on load
|
self.projFiles = [] # A list of all files in the content folder on load
|
||||||
|
|
||||||
# Project Settings
|
|
||||||
self.autoReplace = {} # Text to auto-replace on exports
|
|
||||||
self.titleFormat = {} # The formatting of titles for exports
|
|
||||||
self.spellCheck = False # Controls the spellcheck-as-you-type feature
|
|
||||||
|
|
||||||
# Internal Mapping
|
# Internal Mapping
|
||||||
self.tr = partial(QCoreApplication.translate, "NWProject")
|
self.tr = partial(QCoreApplication.translate, "NWProject")
|
||||||
|
|
||||||
@@ -255,17 +249,7 @@ class NWProject:
|
|||||||
self.projCache = None
|
self.projCache = None
|
||||||
self.projContent = None
|
self.projContent = None
|
||||||
self.projDict = None
|
self.projDict = None
|
||||||
self.projSpell = None
|
|
||||||
self.projFiles = []
|
self.projFiles = []
|
||||||
self.autoReplace = {}
|
|
||||||
self.titleFormat = {
|
|
||||||
"title": "%title%",
|
|
||||||
"chapter": "%title%",
|
|
||||||
"unnumbered": "%title%",
|
|
||||||
"scene": "* * *",
|
|
||||||
"section": "",
|
|
||||||
}
|
|
||||||
self.spellCheck = False
|
|
||||||
self._data.itemStatus.write(None, self.tr("New"), (100, 100, 100))
|
self._data.itemStatus.write(None, self.tr("New"), (100, 100, 100))
|
||||||
self._data.itemStatus.write(None, self.tr("Note"), (200, 50, 0))
|
self._data.itemStatus.write(None, self.tr("Note"), (200, 50, 0))
|
||||||
self._data.itemStatus.write(None, self.tr("Draft"), (200, 150, 0))
|
self._data.itemStatus.write(None, self.tr("Draft"), (200, 150, 0))
|
||||||
@@ -466,9 +450,6 @@ class NWProject:
|
|||||||
self._data = NWProjectData()
|
self._data = NWProjectData()
|
||||||
xmlReader = ProjectXMLReader(fileName)
|
xmlReader = ProjectXMLReader(fileName)
|
||||||
xmlParsed = xmlReader.read(self._data)
|
xmlParsed = xmlReader.read(self._data)
|
||||||
xmlData = xmlReader.data
|
|
||||||
|
|
||||||
# print(json.dumps(xmlData, indent=2))
|
|
||||||
|
|
||||||
nwxRoot = xmlReader.xmlRoot
|
nwxRoot = xmlReader.xmlRoot
|
||||||
appVersion = xmlReader.appVersion or self.tr("Unknown")
|
appVersion = xmlReader.appVersion or self.tr("Unknown")
|
||||||
@@ -494,8 +475,6 @@ class NWProject:
|
|||||||
self.clearProject()
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self._raw = xmlData
|
|
||||||
|
|
||||||
logger.debug("XML root is '%s'", nwxRoot)
|
logger.debug("XML root is '%s'", nwxRoot)
|
||||||
logger.debug("File version is '%s'", xmlVersion)
|
logger.debug("File version is '%s'", xmlVersion)
|
||||||
|
|
||||||
@@ -539,15 +518,7 @@ class NWProject:
|
|||||||
logger.info("Project Name: '%s'", self._data.name)
|
logger.info("Project Name: '%s'", self._data.name)
|
||||||
logger.info("Project Title: '%s'", self._data.title)
|
logger.info("Project Title: '%s'", self._data.title)
|
||||||
|
|
||||||
xmlSettings = xmlData.get("settings", {})
|
self._projTree.unpack(xmlReader.content)
|
||||||
|
|
||||||
self.spellCheck = self._data.spellCheck
|
|
||||||
self.projSpell = self._data.spellLang
|
|
||||||
self.autoReplace = xmlSettings.get("autoReplace", {})
|
|
||||||
self.titleFormat.update(xmlSettings.get("titleFormat", {}))
|
|
||||||
|
|
||||||
self._projTree.unpack(xmlData.get("content", []))
|
|
||||||
|
|
||||||
self._optState.loadSettings()
|
self._optState.loadSettings()
|
||||||
|
|
||||||
# Sort out old file locations
|
# Sort out old file locations
|
||||||
@@ -648,10 +619,10 @@ class NWProject:
|
|||||||
self._packProjectValue(xSettings, "lastWordCount", self._data.getCurrCount("total"))
|
self._packProjectValue(xSettings, "lastWordCount", self._data.getCurrCount("total"))
|
||||||
self._packProjectValue(xSettings, "novelWordCount", self._data.getCurrCount("novel"))
|
self._packProjectValue(xSettings, "novelWordCount", self._data.getCurrCount("novel"))
|
||||||
self._packProjectValue(xSettings, "notesWordCount", self._data.getCurrCount("notes"))
|
self._packProjectValue(xSettings, "notesWordCount", self._data.getCurrCount("notes"))
|
||||||
self._packProjectKeyValue(xSettings, "autoReplace", self.autoReplace)
|
self._packProjectKeyValue(xSettings, "autoReplace", self._data.autoReplace)
|
||||||
|
|
||||||
xTitleFmt = etree.SubElement(xSettings, "titleFormat")
|
xTitleFmt = etree.SubElement(xSettings, "titleFormat")
|
||||||
for aKey, aValue in self.titleFormat.items():
|
for aKey, aValue in self._data.titleFormat.items():
|
||||||
if len(aKey) > 0:
|
if len(aKey) > 0:
|
||||||
self._packProjectValue(xTitleFmt, aKey, aValue)
|
self._packProjectValue(xTitleFmt, aKey, aValue)
|
||||||
|
|
||||||
@@ -921,24 +892,6 @@ class NWProject:
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def setSpellCheck(self, theMode):
|
|
||||||
"""Enable/disable spell checking.
|
|
||||||
"""
|
|
||||||
if self.spellCheck != theMode:
|
|
||||||
self.spellCheck = theMode
|
|
||||||
self.setProjectChanged(True)
|
|
||||||
return self.spellCheck
|
|
||||||
|
|
||||||
def setSpellLang(self, theLang):
|
|
||||||
"""Set the project-specific spell check language.
|
|
||||||
"""
|
|
||||||
theLang = checkStringNone(theLang, None)
|
|
||||||
if self.projSpell != theLang:
|
|
||||||
self.projSpell = theLang
|
|
||||||
self.setProjectChanged(True)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def setProjectLang(self, theLang):
|
def setProjectLang(self, theLang):
|
||||||
"""Set the project-specific language.
|
"""Set the project-specific language.
|
||||||
"""
|
"""
|
||||||
@@ -970,25 +923,6 @@ class NWProject:
|
|||||||
"""
|
"""
|
||||||
return self._setStatusImport(newCols, delCols, self._data.itemImport)
|
return self._setStatusImport(newCols, delCols, self._data.itemImport)
|
||||||
|
|
||||||
def setAutoReplace(self, autoReplace):
|
|
||||||
"""Update the auto-replace dictionary.
|
|
||||||
"""
|
|
||||||
self.autoReplace = {}
|
|
||||||
for key, entry in autoReplace.items():
|
|
||||||
self.autoReplace[key] = simplified(entry)
|
|
||||||
self.setProjectChanged(True)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def setTitleFormat(self, titleFormat):
|
|
||||||
"""Set the formatting of titles in the project.
|
|
||||||
"""
|
|
||||||
for valKey, valEntry in titleFormat.items():
|
|
||||||
if valKey in self.titleFormat:
|
|
||||||
self.titleFormat[valKey] = checkString(
|
|
||||||
simplified(valEntry), self.titleFormat[valKey]
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def setProjectChanged(self, bValue):
|
def setProjectChanged(self, bValue):
|
||||||
"""Toggle the project changed flag, and propagate the
|
"""Toggle the project changed flag, and propagate the
|
||||||
information to the GUI statusbar.
|
information to the GUI statusbar.
|
||||||
|
|||||||
@@ -54,6 +54,15 @@ class NWProjectData:
|
|||||||
self._lastCount = {}
|
self._lastCount = {}
|
||||||
self._currCount = {}
|
self._currCount = {}
|
||||||
|
|
||||||
|
self._autoReplace = {}
|
||||||
|
self._titleFormat = {
|
||||||
|
"title": "%title%",
|
||||||
|
"chapter": "%title%",
|
||||||
|
"unnumbered": "%title%",
|
||||||
|
"scene": "* * *",
|
||||||
|
"section": "",
|
||||||
|
}
|
||||||
|
|
||||||
self._status = NWStatus(NWStatus.STATUS)
|
self._status = NWStatus(NWStatus.STATUS)
|
||||||
self._import = NWStatus(NWStatus.IMPORT)
|
self._import = NWStatus(NWStatus.IMPORT)
|
||||||
|
|
||||||
@@ -106,6 +115,14 @@ class NWProjectData:
|
|||||||
def spellLang(self):
|
def spellLang(self):
|
||||||
return self._spellLang
|
return self._spellLang
|
||||||
|
|
||||||
|
@property
|
||||||
|
def autoReplace(self):
|
||||||
|
return self._autoReplace
|
||||||
|
|
||||||
|
@property
|
||||||
|
def titleFormat(self):
|
||||||
|
return self._titleFormat
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def itemStatus(self):
|
def itemStatus(self):
|
||||||
return self._status
|
return self._status
|
||||||
@@ -153,6 +170,9 @@ class NWProjectData:
|
|||||||
def getCurrCount(self, type):
|
def getCurrCount(self, type):
|
||||||
return self._currCount.get(type, 0)
|
return self._currCount.get(type, 0)
|
||||||
|
|
||||||
|
def getTitleFormat(self, kind):
|
||||||
|
return self._titleFormat.get(kind, "%title%")
|
||||||
|
|
||||||
##
|
##
|
||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
@@ -231,4 +251,21 @@ class NWProjectData:
|
|||||||
self._changed = True
|
self._changed = True
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def setAutoReplace(self, value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
self._autoReplace = {}
|
||||||
|
for key, entry in value.items():
|
||||||
|
if isinstance(entry, str):
|
||||||
|
self._autoReplace[key] = simplified(entry)
|
||||||
|
self._changed = True
|
||||||
|
return
|
||||||
|
|
||||||
|
def setTitleFormat(self, value):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
for key, entry in value.items():
|
||||||
|
if key in self._titleFormat and isinstance(entry, str):
|
||||||
|
self._titleFormat[key] = simplified(entry)
|
||||||
|
self._changed = True
|
||||||
|
return
|
||||||
|
|
||||||
# END Class NWProjectData
|
# END Class NWProjectData
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ class ProjectXMLReader:
|
|||||||
self._path = path
|
self._path = path
|
||||||
self._state = XMLReadState.NO_ACTION
|
self._state = XMLReadState.NO_ACTION
|
||||||
|
|
||||||
self._data = {}
|
|
||||||
self._content = []
|
self._content = []
|
||||||
self._statusData = {}
|
self._statusData = {}
|
||||||
self._statusMap = {}
|
self._statusMap = {}
|
||||||
@@ -85,10 +84,6 @@ class ProjectXMLReader:
|
|||||||
# Properties
|
# Properties
|
||||||
##
|
##
|
||||||
|
|
||||||
@property
|
|
||||||
def data(self):
|
|
||||||
return self._data
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def content(self):
|
def content(self):
|
||||||
return self._content
|
return self._content
|
||||||
@@ -124,7 +119,6 @@ class ProjectXMLReader:
|
|||||||
def read(self, projData):
|
def read(self, projData):
|
||||||
"""Read and parse the project XML file.
|
"""Read and parse the project XML file.
|
||||||
"""
|
"""
|
||||||
self._data = {}
|
|
||||||
self._content = []
|
self._content = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -231,6 +225,7 @@ class ProjectXMLReader:
|
|||||||
projData.setEditTime(xItem.text)
|
projData.setEditTime(xItem.text)
|
||||||
else:
|
else:
|
||||||
logger.warning("Ignored <root/project/%s> in xml", xItem.tag)
|
logger.warning("Ignored <root/project/%s> in xml", xItem.tag)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _parseProjectSettings(self, xSection, projData):
|
def _parseProjectSettings(self, xSection, projData):
|
||||||
@@ -238,9 +233,6 @@ class ProjectXMLReader:
|
|||||||
"""
|
"""
|
||||||
logger.debug("Parsing xml <root/settings>")
|
logger.debug("Parsing xml <root/settings>")
|
||||||
|
|
||||||
data = {}
|
|
||||||
autoReplace = {}
|
|
||||||
titleFormat = {}
|
|
||||||
for xItem in xSection:
|
for xItem in xSection:
|
||||||
if xItem.tag == "doBackup":
|
if xItem.tag == "doBackup":
|
||||||
projData.setDoBackup(xItem.text)
|
projData.setDoBackup(xItem.text)
|
||||||
@@ -270,22 +262,14 @@ class ProjectXMLReader:
|
|||||||
self._parseStatusImport(xItem, projData.itemImport)
|
self._parseStatusImport(xItem, projData.itemImport)
|
||||||
elif xItem.tag == "autoReplace":
|
elif xItem.tag == "autoReplace":
|
||||||
if self._version >= 0x0102:
|
if self._version >= 0x0102:
|
||||||
for xEntry in xItem:
|
projData.setAutoReplace(self._parseDictKeyText(xItem))
|
||||||
if xEntry.tag == "entry" and "key" in xEntry.attrib:
|
|
||||||
autoReplace[xEntry.attrib["key"]] = checkString(xEntry.text, "ERROR")
|
|
||||||
else: # Pre 1.2 format
|
else: # Pre 1.2 format
|
||||||
for xEntry in xItem:
|
projData.setAutoReplace(self._parseDictTagText(xItem))
|
||||||
autoReplace[xEntry.tag] = checkString(xEntry.text, "ERROR")
|
|
||||||
elif xItem.tag == "titleFormat":
|
elif xItem.tag == "titleFormat":
|
||||||
for xEntry in xItem:
|
projData.setTitleFormat(self._parseDictTagText(xItem))
|
||||||
titleFormat[xEntry.tag] = checkString(xEntry.text, "")
|
|
||||||
else:
|
else:
|
||||||
logger.warning("Ignored <root/settings/%s> in xml", xItem.tag)
|
logger.warning("Ignored <root/settings/%s> in xml", xItem.tag)
|
||||||
|
|
||||||
data["autoReplace"] = autoReplace
|
|
||||||
data["titleFormat"] = titleFormat
|
|
||||||
self._data["settings"] = data
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _parseProjectContent(self, xSection):
|
def _parseProjectContent(self, xSection):
|
||||||
@@ -293,7 +277,6 @@ class ProjectXMLReader:
|
|||||||
"""
|
"""
|
||||||
logger.debug("Parsing xml <root/content>")
|
logger.debug("Parsing xml <root/content>")
|
||||||
|
|
||||||
data = []
|
|
||||||
for xItem in xSection:
|
for xItem in xSection:
|
||||||
if xItem.tag == "item":
|
if xItem.tag == "item":
|
||||||
item = {}
|
item = {}
|
||||||
@@ -323,21 +306,20 @@ class ProjectXMLReader:
|
|||||||
item["active"] = checkBool(xVal.attrib.get("exported", False), False)
|
item["active"] = checkBool(xVal.attrib.get("exported", False), False)
|
||||||
else:
|
else:
|
||||||
logger.warning("Ignored <root/content/item/%s> in xml", xVal.tag)
|
logger.warning("Ignored <root/content/item/%s> in xml", xVal.tag)
|
||||||
data.append(item)
|
|
||||||
self._content.append(item)
|
self._content.append(item)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warning("Ignored item <root/content/%s> in xml", xItem.tag)
|
logger.warning("Ignored item <root/content/%s> in xml", xItem.tag)
|
||||||
|
|
||||||
self._data["content"] = data
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _parseProjectContentLegacy(self, xSection):
|
def _parseProjectContentLegacy(self, xSection):
|
||||||
"""Parse the content section of the XML file for version before 1.4.
|
"""Parse the content section of the XML file for older version.
|
||||||
"""
|
"""
|
||||||
logger.debug("Parsing xml <root/content> (legacy format)")
|
logger.debug("Parsing xml <root/content> (legacy format)")
|
||||||
depLayout = ("TITLE", "PAGE", "BOOK", "PARTITION", "UNNUMBERED", "CHAPTER", "SCENE")
|
depLayout = ("TITLE", "PAGE", "BOOK", "PARTITION", "UNNUMBERED", "CHAPTER", "SCENE")
|
||||||
data = []
|
|
||||||
for xItem in xSection:
|
for xItem in xSection:
|
||||||
item = {}
|
item = {}
|
||||||
if xItem.tag == "item":
|
if xItem.tag == "item":
|
||||||
@@ -388,13 +370,11 @@ class ProjectXMLReader:
|
|||||||
if item.get("type", "") == "TRASH":
|
if item.get("type", "") == "TRASH":
|
||||||
item["type"] = "ROOT"
|
item["type"] = "ROOT"
|
||||||
|
|
||||||
data.append(item)
|
|
||||||
self._content.append(item)
|
self._content.append(item)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warning("Ignored <root/content/%s> in xml", xItem.tag)
|
logger.warning("Ignored <root/content/%s> in xml", xItem.tag)
|
||||||
|
|
||||||
self._data["content"] = data
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _parseStatusImport(self, xItem, sObject):
|
def _parseStatusImport(self, xItem, sObject):
|
||||||
@@ -417,6 +397,22 @@ class ProjectXMLReader:
|
|||||||
self._importMap = {entry["name"]: key for key, entry in projData.itemImport.items()}
|
self._importMap = {entry["name"]: key for key, entry in projData.itemImport.items()}
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _parseDictKeyText(self, xItem):
|
||||||
|
"""Parse a dictionary stored with key as an attribute and the
|
||||||
|
value as the text porperty.
|
||||||
|
"""
|
||||||
|
result = {}
|
||||||
|
for xEntry in xItem:
|
||||||
|
if xEntry.tag == "entry" and "key" in xEntry.attrib:
|
||||||
|
result[xEntry.attrib["key"]] = checkString(xEntry.text, "")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _parseDictTagText(self, xItem):
|
||||||
|
"""Parse a dictionary stored with key as the tag and the value
|
||||||
|
as the text porperty.
|
||||||
|
"""
|
||||||
|
return {n.tag: checkString(n.text, "") for n in xItem}
|
||||||
|
|
||||||
# END Class ProjectXMLReader
|
# END Class ProjectXMLReader
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -327,9 +327,10 @@ class Tokenizer(ABC):
|
|||||||
"""Run trough the various replace doctionaries.
|
"""Run trough the various replace doctionaries.
|
||||||
"""
|
"""
|
||||||
# Process the user's auto-replace dictionary
|
# Process the user's auto-replace dictionary
|
||||||
if len(self.theProject.autoReplace) > 0:
|
autoReplace = self.theProject.data.autoReplace
|
||||||
|
if len(autoReplace) > 0:
|
||||||
repDict = {}
|
repDict = {}
|
||||||
for aKey, aVal in self.theProject.autoReplace.items():
|
for aKey, aVal in autoReplace.items():
|
||||||
repDict[f"<{aKey}>"] = aVal
|
repDict[f"<{aKey}>"] = aVal
|
||||||
xRep = re.compile("|".join([re.escape(k) for k in repDict.keys()]), flags=re.DOTALL)
|
xRep = re.compile("|".join([re.escape(k) for k in repDict.keys()]), flags=re.DOTALL)
|
||||||
self._theText = xRep.sub(lambda x: repDict[x.group(0)], self._theText)
|
self._theText = xRep.sub(lambda x: repDict[x.group(0)], self._theText)
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
self.theProject.data.setDoBackup(doBackup)
|
self.theProject.data.setDoBackup(doBackup)
|
||||||
|
|
||||||
# Remember this as updating spell dictionary can be expensive
|
# Remember this as updating spell dictionary can be expensive
|
||||||
self._spellChanged = self.theProject.setSpellLang(spellLang)
|
self._spellChanged = self.theProject.data.setSpellLang(spellLang)
|
||||||
|
|
||||||
if self.tabStatus.colChanged:
|
if self.tabStatus.colChanged:
|
||||||
newList, delList = self.tabStatus.getNewList()
|
newList, delList = self.tabStatus.getNewList()
|
||||||
@@ -135,7 +135,7 @@ class GuiProjectSettings(PagedDialog):
|
|||||||
|
|
||||||
if self.tabReplace.arChanged:
|
if self.tabReplace.arChanged:
|
||||||
newList = self.tabReplace.getNewList()
|
newList = self.tabReplace.getNewList()
|
||||||
self.theProject.setAutoReplace(newList)
|
self.theProject.data.setAutoReplace(newList)
|
||||||
|
|
||||||
self._saveGuiSettings()
|
self._saveGuiSettings()
|
||||||
self.accept()
|
self.accept()
|
||||||
@@ -252,8 +252,8 @@ class GuiProjectEditMain(QWidget):
|
|||||||
)
|
)
|
||||||
|
|
||||||
spellIdx = 0
|
spellIdx = 0
|
||||||
if self.theProject.projSpell is not None:
|
if self.theProject.data.spellLang is not None:
|
||||||
spellIdx = self.spellLang.findData(self.theProject.projSpell)
|
spellIdx = self.spellLang.findData(self.theProject.data.spellLang)
|
||||||
if spellIdx != -1:
|
if spellIdx != -1:
|
||||||
self.spellLang.setCurrentIndex(spellIdx)
|
self.spellLang.setCurrentIndex(spellIdx)
|
||||||
|
|
||||||
@@ -578,7 +578,7 @@ class GuiProjectEditReplace(QWidget):
|
|||||||
self.listBox.setColumnWidth(self.COL_KEY, wCol0)
|
self.listBox.setColumnWidth(self.COL_KEY, wCol0)
|
||||||
self.listBox.setIndentation(0)
|
self.listBox.setIndentation(0)
|
||||||
|
|
||||||
for aKey, aVal in self.theProject.autoReplace.items():
|
for aKey, aVal in self.theProject.data.autoReplace.items():
|
||||||
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
|
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
|
||||||
self.listBox.addTopLevelItem(newItem)
|
self.listBox.addTopLevelItem(newItem)
|
||||||
|
|
||||||
|
|||||||
@@ -684,10 +684,10 @@ class GuiDocEditor(QTextEdit):
|
|||||||
"""Set the spell checker dictionary language, and emit the
|
"""Set the spell checker dictionary language, and emit the
|
||||||
dictionary changed signal.
|
dictionary changed signal.
|
||||||
"""
|
"""
|
||||||
if self.theProject.projSpell is None:
|
if self.theProject.data.spellLang is None:
|
||||||
theLang = self.mainConf.spellLanguage
|
theLang = self.mainConf.spellLanguage
|
||||||
else:
|
else:
|
||||||
theLang = self.theProject.projSpell
|
theLang = self.theProject.data.spellLang
|
||||||
|
|
||||||
self.spEnchant.setLanguage(theLang, self.theProject.projDict)
|
self.spEnchant.setLanguage(theLang, self.theProject.projDict)
|
||||||
_, theProvider = self.spEnchant.describeDict()
|
_, theProvider = self.spEnchant.describeDict()
|
||||||
@@ -721,7 +721,7 @@ class GuiDocEditor(QTextEdit):
|
|||||||
|
|
||||||
self._spellCheck = theMode
|
self._spellCheck = theMode
|
||||||
self.mainGui.mainMenu.setSpellCheck(theMode)
|
self.mainGui.mainMenu.setSpellCheck(theMode)
|
||||||
self.theProject.setSpellCheck(theMode)
|
self.theProject.data.setSpellCheck(theMode)
|
||||||
self.highLight.setSpellCheck(theMode)
|
self.highLight.setSpellCheck(theMode)
|
||||||
if not self._bigDoc:
|
if not self._bigDoc:
|
||||||
self.spellCheckDocument()
|
self.spellCheckDocument()
|
||||||
|
|||||||
@@ -794,7 +794,7 @@ class GuiMainMenu(QMenuBar):
|
|||||||
# Tools > Check Spelling
|
# Tools > Check Spelling
|
||||||
self.aSpellCheck = QAction(self.tr("Check Spelling"), self)
|
self.aSpellCheck = QAction(self.tr("Check Spelling"), self)
|
||||||
self.aSpellCheck.setCheckable(True)
|
self.aSpellCheck.setCheckable(True)
|
||||||
self.aSpellCheck.setChecked(self.theProject.spellCheck)
|
self.aSpellCheck.setChecked(self.theProject.data.spellCheck)
|
||||||
self.aSpellCheck.triggered.connect(self._toggleSpellCheck) # triggered, not toggled!
|
self.aSpellCheck.triggered.connect(self._toggleSpellCheck) # triggered, not toggled!
|
||||||
self.aSpellCheck.setShortcut("Ctrl+F7")
|
self.aSpellCheck.setShortcut("Ctrl+F7")
|
||||||
self.toolsMenu.addAction(self.aSpellCheck)
|
self.toolsMenu.addAction(self.aSpellCheck)
|
||||||
|
|||||||
@@ -524,7 +524,7 @@ class GuiMain(QMainWindow):
|
|||||||
self._updateWindowTitle(self.theProject.data.name)
|
self._updateWindowTitle(self.theProject.data.name)
|
||||||
self.rebuildTrees()
|
self.rebuildTrees()
|
||||||
self.docEditor.setDictionaries()
|
self.docEditor.setDictionaries()
|
||||||
self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
|
self.docEditor.toggleSpellCheck(self.theProject.data.spellCheck)
|
||||||
self.mainStatus.setRefTime(self.theProject.projOpened)
|
self.mainStatus.setRefTime(self.theProject.projOpened)
|
||||||
self.projView.openProjectTasks()
|
self.projView.openProjectTasks()
|
||||||
self.novelView.openProjectTasks()
|
self.novelView.openProjectTasks()
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.fmtTitle.setMinimumWidth(xFmt)
|
self.fmtTitle.setMinimumWidth(xFmt)
|
||||||
self.fmtTitle.setToolTip(fmtHelp)
|
self.fmtTitle.setToolTip(fmtHelp)
|
||||||
self.fmtTitle.setText(
|
self.fmtTitle.setText(
|
||||||
self._reFmtCodes(self.theProject.titleFormat["title"])
|
self._reFmtCodes(self.theProject.data.getTitleFormat("title"))
|
||||||
)
|
)
|
||||||
|
|
||||||
self.fmtChapter = QLineEdit()
|
self.fmtChapter = QLineEdit()
|
||||||
@@ -134,7 +134,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.fmtChapter.setMinimumWidth(xFmt)
|
self.fmtChapter.setMinimumWidth(xFmt)
|
||||||
self.fmtChapter.setToolTip(fmtHelp)
|
self.fmtChapter.setToolTip(fmtHelp)
|
||||||
self.fmtChapter.setText(
|
self.fmtChapter.setText(
|
||||||
self._reFmtCodes(self.theProject.titleFormat["chapter"])
|
self._reFmtCodes(self.theProject.data.getTitleFormat("chapter"))
|
||||||
)
|
)
|
||||||
|
|
||||||
self.fmtUnnumbered = QLineEdit()
|
self.fmtUnnumbered = QLineEdit()
|
||||||
@@ -142,7 +142,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.fmtUnnumbered.setMinimumWidth(xFmt)
|
self.fmtUnnumbered.setMinimumWidth(xFmt)
|
||||||
self.fmtUnnumbered.setToolTip(fmtHelp)
|
self.fmtUnnumbered.setToolTip(fmtHelp)
|
||||||
self.fmtUnnumbered.setText(
|
self.fmtUnnumbered.setText(
|
||||||
self._reFmtCodes(self.theProject.titleFormat["unnumbered"])
|
self._reFmtCodes(self.theProject.data.getTitleFormat("unnumbered"))
|
||||||
)
|
)
|
||||||
|
|
||||||
self.fmtScene = QLineEdit()
|
self.fmtScene = QLineEdit()
|
||||||
@@ -150,7 +150,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.fmtScene.setMinimumWidth(xFmt)
|
self.fmtScene.setMinimumWidth(xFmt)
|
||||||
self.fmtScene.setToolTip(fmtHelp + fmtScHelp)
|
self.fmtScene.setToolTip(fmtHelp + fmtScHelp)
|
||||||
self.fmtScene.setText(
|
self.fmtScene.setText(
|
||||||
self._reFmtCodes(self.theProject.titleFormat["scene"])
|
self._reFmtCodes(self.theProject.data.getTitleFormat("scene"))
|
||||||
)
|
)
|
||||||
|
|
||||||
self.fmtSection = QLineEdit()
|
self.fmtSection = QLineEdit()
|
||||||
@@ -158,7 +158,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
self.fmtSection.setMinimumWidth(xFmt)
|
self.fmtSection.setMinimumWidth(xFmt)
|
||||||
self.fmtSection.setToolTip(fmtHelp + fmtScHelp)
|
self.fmtSection.setToolTip(fmtHelp + fmtScHelp)
|
||||||
self.fmtSection.setText(
|
self.fmtSection.setText(
|
||||||
self._reFmtCodes(self.theProject.titleFormat["section"])
|
self._reFmtCodes(self.theProject.data.getTitleFormat("section"))
|
||||||
)
|
)
|
||||||
|
|
||||||
self.buildLang = QComboBox()
|
self.buildLang = QComboBox()
|
||||||
@@ -1159,7 +1159,7 @@ class GuiBuildNovel(QDialog):
|
|||||||
logger.debug("Saving GuiBuildNovel settings")
|
logger.debug("Saving GuiBuildNovel settings")
|
||||||
|
|
||||||
# Formatting
|
# Formatting
|
||||||
self.theProject.setTitleFormat({
|
self.theProject.data.setTitleFormat({
|
||||||
"title": self.fmtTitle.text().strip(),
|
"title": self.fmtTitle.text().strip(),
|
||||||
"chapter": self.fmtChapter.text().strip(),
|
"chapter": self.fmtChapter.text().strip(),
|
||||||
"unnumbered": self.fmtUnnumbered.text().strip(),
|
"unnumbered": self.fmtUnnumbered.text().strip(),
|
||||||
|
|||||||
+22
-22
@@ -1,13 +1,13 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2022-10-25 18:45:45">
|
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2022-10-31 18:11:11">
|
||||||
<project>
|
<project>
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
<author>Jane Smith</author>
|
<author>Jane Smith</author>
|
||||||
<author>Jay Doh</author>
|
<author>Jay Doh</author>
|
||||||
<saveCount>1386</saveCount>
|
<saveCount>1387</saveCount>
|
||||||
<autoCount>236</autoCount>
|
<autoCount>236</autoCount>
|
||||||
<editTime>69352</editTime>
|
<editTime>69358</editTime>
|
||||||
</project>
|
</project>
|
||||||
<settings>
|
<settings>
|
||||||
<doBackup>False</doBackup>
|
<doBackup>False</doBackup>
|
||||||
@@ -55,43 +55,43 @@
|
|||||||
<name status="sc24b8f" import="ia857f0">Novel</name>
|
<name status="sc24b8f" import="ia857f0">Novel</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="53b69b83cdafc" parent="7031beac91f75" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="53b69b83cdafc" parent="7031beac91f75" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="93" wordCount="19" paraCount="2" cursorPos="119"/>
|
<meta expanded="False" heading="H1" charCount="93" wordCount="19" paraCount="2" cursorPos="119"/>
|
||||||
<name status="sc24b8f" import="ia857f0" active="True">Title Page</name>
|
<name status="sc24b8f" import="ia857f0" active="True">Title Page</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="974e400180a99" parent="7031beac91f75" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="974e400180a99" parent="7031beac91f75" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H0" charCount="251" wordCount="50" paraCount="2" cursorPos="277"/>
|
<meta expanded="False" heading="H0" charCount="251" wordCount="50" paraCount="2" cursorPos="277"/>
|
||||||
<name status="sf12341" import="ia857f0" active="True">Page</name>
|
<name status="sf12341" import="ia857f0" active="True">Page</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="26" wordCount="6" paraCount="1" cursorPos="36"/>
|
<meta expanded="False" heading="H1" charCount="26" wordCount="6" paraCount="1" cursorPos="36"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">Part One</name>
|
<name status="s90e6c9" import="ia857f0" active="True">Part One</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="True" mainHeading="H2" charCount="95" wordCount="18" paraCount="1" cursorPos="291"/>
|
<meta expanded="True" heading="H2" charCount="95" wordCount="18" paraCount="1" cursorPos="291"/>
|
||||||
<name status="sf24ce6" import="ia857f0" active="True">Chapter One</name>
|
<name status="sf24ce6" import="ia857f0" active="True">Chapter One</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H3" charCount="2687" wordCount="479" paraCount="14" cursorPos="67"/>
|
<meta expanded="False" heading="H3" charCount="2687" wordCount="479" paraCount="14" cursorPos="67"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">Making a Scene</name>
|
<name status="s90e6c9" import="ia857f0" active="True">Making a Scene</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="465"/>
|
<meta expanded="False" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="465"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">Another Scene</name>
|
<name status="s90e6c9" import="ia857f0" active="True">Another Scene</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H2" charCount="617" wordCount="101" paraCount="3" cursorPos="310"/>
|
<meta expanded="False" heading="H2" charCount="617" wordCount="101" paraCount="3" cursorPos="310"/>
|
||||||
<name status="s78ea90" import="ia857f0" active="True">Interlude</name>
|
<name status="s78ea90" import="ia857f0" active="True">Interlude</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE">
|
<item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="1909" wordCount="346" paraCount="7" cursorPos="0"/>
|
<meta expanded="False" heading="H1" charCount="1909" wordCount="346" paraCount="7" cursorPos="0"/>
|
||||||
<name status="sf24ce6" import="ia857f0" active="False">A Note on Structure</name>
|
<name status="sf24ce6" import="ia857f0" active="False">A Note on Structure</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="True" mainHeading="H2" charCount="139" wordCount="28" paraCount="1" cursorPos="188"/>
|
<meta expanded="True" heading="H2" charCount="139" wordCount="28" paraCount="1" cursorPos="188"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">Chapter Two</name>
|
<name status="s90e6c9" import="ia857f0" active="True">Chapter Two</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="ae7339df26ded" parent="88706ddc78b1b" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="ae7339df26ded" parent="88706ddc78b1b" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H3" charCount="189" wordCount="37" paraCount="1" cursorPos="0"/>
|
<meta expanded="False" heading="H3" charCount="189" wordCount="37" paraCount="1" cursorPos="0"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">We Found John!</name>
|
<name status="s90e6c9" import="ia857f0" active="True">We Found John!</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="e5e47ebf63b1c" parent="None" root="e5e47ebf63b1c" order="1" type="ROOT" class="NOVEL">
|
<item handle="e5e47ebf63b1c" parent="None" root="e5e47ebf63b1c" order="1" type="ROOT" class="NOVEL">
|
||||||
@@ -99,11 +99,11 @@
|
|||||||
<name status="sf12341" import="ia857f0">Sequel</name>
|
<name status="sf12341" import="ia857f0">Sequel</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bacb7059e3083" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="bacb7059e3083" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="27" wordCount="5" paraCount="1" cursorPos="100"/>
|
<meta expanded="False" heading="H1" charCount="27" wordCount="5" paraCount="1" cursorPos="100"/>
|
||||||
<name status="sc24b8f" import="ia857f0" active="True">Title Page</name>
|
<name status="sc24b8f" import="ia857f0" active="True">Title Page</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="a520879ca0b45" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
<item handle="a520879ca0b45" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H2" charCount="299" wordCount="55" paraCount="2" cursorPos="104"/>
|
<meta expanded="False" heading="H2" charCount="299" wordCount="55" paraCount="2" cursorPos="104"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">Chapter One</name>
|
<name status="s90e6c9" import="ia857f0" active="True">Chapter One</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="2" type="ROOT" class="CHARACTER">
|
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="2" type="ROOT" class="CHARACTER">
|
||||||
@@ -115,11 +115,11 @@
|
|||||||
<name status="sf12341" import="ia857f0">Main Characters</name>
|
<name status="sf12341" import="ia857f0">Main Characters</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
|
<meta expanded="False" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
|
||||||
<name status="sf12341" import="icfb3a5" active="True">John Smith</name>
|
<name status="sf12341" import="icfb3a5" active="True">John Smith</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
|
<meta expanded="False" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
|
||||||
<name status="sf12341" import="i2d7a54" active="True">Jane Smith</name>
|
<name status="sf12341" import="i2d7a54" active="True">Jane Smith</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
|
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
|
||||||
@@ -127,15 +127,15 @@
|
|||||||
<name status="sf12341" import="ia857f0">Locations</name>
|
<name status="sf12341" import="ia857f0">Locations</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="15c4492bd5107" order="0" type="FILE" class="WORLD" layout="NOTE">
|
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="15c4492bd5107" order="0" type="FILE" class="WORLD" layout="NOTE">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
|
<meta expanded="False" heading="H1" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
|
||||||
<name status="sf12341" import="i56be10" active="True">Earth</name>
|
<name status="sf12341" import="i56be10" active="True">Earth</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="15c4492bd5107" order="1" type="FILE" class="WORLD" layout="NOTE">
|
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="15c4492bd5107" order="1" type="FILE" class="WORLD" layout="NOTE">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
|
<meta expanded="False" heading="H1" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
|
||||||
<name status="sf12341" import="icfb3a5" active="True">Space</name>
|
<name status="sf12341" import="icfb3a5" active="True">Space</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="15c4492bd5107" order="2" type="FILE" class="WORLD" layout="NOTE">
|
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="15c4492bd5107" order="2" type="FILE" class="WORLD" layout="NOTE">
|
||||||
<meta expanded="False" mainHeading="H1" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
|
<meta expanded="False" heading="H1" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
|
||||||
<name status="sf12341" import="i2d7a54" active="True">Mars</name>
|
<name status="sf12341" import="i2d7a54" active="True">Mars</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="6827118336ac1" parent="None" root="6827118336ac1" order="4" type="ROOT" class="ARCHIVE">
|
<item handle="6827118336ac1" parent="None" root="6827118336ac1" order="4" type="ROOT" class="ARCHIVE">
|
||||||
@@ -147,7 +147,7 @@
|
|||||||
<name status="sf12341" import="ia857f0">Scenes</name>
|
<name status="sf12341" import="ia857f0">Scenes</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="6827118336ac1" order="0" type="FILE" class="ARCHIVE" layout="DOCUMENT">
|
<item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="6827118336ac1" order="0" type="FILE" class="ARCHIVE" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H3" charCount="232" wordCount="42" paraCount="1" cursorPos="239"/>
|
<meta expanded="False" heading="H3" charCount="232" wordCount="42" paraCount="1" cursorPos="239"/>
|
||||||
<name status="s90e6c9" import="ia857f0" active="True">Old File</name>
|
<name status="s90e6c9" import="ia857f0" active="True">Old File</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="5" type="ROOT" class="TRASH">
|
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="5" type="ROOT" class="TRASH">
|
||||||
@@ -155,7 +155,7 @@
|
|||||||
<name status="sf12341" import="ia857f0">Trash</name>
|
<name status="sf12341" import="ia857f0">Trash</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="98acd8c76c93a" order="0" type="FILE" class="TRASH" layout="DOCUMENT">
|
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="98acd8c76c93a" order="0" type="FILE" class="TRASH" layout="DOCUMENT">
|
||||||
<meta expanded="False" mainHeading="H3" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/>
|
<meta expanded="False" heading="H3" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/>
|
||||||
<name status="sf12341" import="ia857f0" active="True">Delete Me!</name>
|
<name status="sf12341" import="ia857f0" active="True">Delete Me!</name>
|
||||||
</item>
|
</item>
|
||||||
</content>
|
</content>
|
||||||
|
|||||||
@@ -941,19 +941,19 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
|
|||||||
|
|
||||||
# Spell check
|
# Spell check
|
||||||
theProject.setProjectChanged(False)
|
theProject.setProjectChanged(False)
|
||||||
assert theProject.setSpellCheck(True)
|
theProject.data.setSpellCheck(True)
|
||||||
assert not theProject.setSpellCheck(False)
|
theProject.data.setSpellCheck(False)
|
||||||
assert theProject.projChanged
|
assert theProject.projChanged
|
||||||
|
|
||||||
# Spell language
|
# Spell language
|
||||||
theProject.setProjectChanged(False)
|
theProject.setProjectChanged(False)
|
||||||
assert theProject.projSpell is None
|
assert theProject.data.spellLang is None
|
||||||
assert theProject.setSpellLang(None) is False
|
theProject.data.setSpellLang(None)
|
||||||
assert theProject.projSpell is None
|
assert theProject.data.spellLang is None
|
||||||
assert theProject.setSpellLang("None") is False # Should be interpreded as None
|
theProject.data.setSpellLang("None") # Should be interpreded as None
|
||||||
assert theProject.projSpell is None
|
assert theProject.data.spellLang is None
|
||||||
assert theProject.setSpellLang("en_GB")
|
theProject.data.setSpellLang("en_GB")
|
||||||
assert theProject.projSpell == "en_GB"
|
assert theProject.data.spellLang == "en_GB"
|
||||||
assert theProject.projChanged
|
assert theProject.projChanged
|
||||||
|
|
||||||
# Project Language
|
# Project Language
|
||||||
@@ -982,8 +982,8 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
|
|||||||
|
|
||||||
# Autoreplace
|
# Autoreplace
|
||||||
theProject.setProjectChanged(False)
|
theProject.setProjectChanged(False)
|
||||||
assert theProject.setAutoReplace({"A": "B", "C": "D"})
|
theProject.data.setAutoReplace({"A": "B", "C": "D"})
|
||||||
assert theProject.autoReplace == {"A": "B", "C": "D"}
|
assert theProject.data.autoReplace == {"A": "B", "C": "D"}
|
||||||
assert theProject.projChanged
|
assert theProject.projChanged
|
||||||
|
|
||||||
# Change project tree order
|
# Change project tree order
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, mockGUI):
|
|||||||
nDoc = NWDoc(theProject, sHandle)
|
nDoc = NWDoc(theProject, sHandle)
|
||||||
assert nDoc.writeDocument(docText)
|
assert nDoc.writeDocument(docText)
|
||||||
|
|
||||||
theProject.setAutoReplace({"A": "this", "B": "that"})
|
theProject.data.setAutoReplace({"A": "this", "B": "that"})
|
||||||
|
|
||||||
assert theProject.saveProject()
|
assert theProject.saveProject()
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
|
|||||||
|
|
||||||
# Pretend we have a project
|
# Pretend we have a project
|
||||||
nwGUI.hasProject = True
|
nwGUI.hasProject = True
|
||||||
nwGUI.theProject.setSpellLang("en")
|
nwGUI.theProject.data.setSpellLang("en")
|
||||||
|
|
||||||
# Get the dialog object
|
# Get the dialog object
|
||||||
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
|
nwGUI.mainMenu.aProjectSettings.activate(QAction.Trigger)
|
||||||
@@ -95,9 +95,9 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd
|
|||||||
|
|
||||||
# Set some values
|
# Set some values
|
||||||
theProject = nwGUI.theProject
|
theProject = nwGUI.theProject
|
||||||
theProject.setSpellLang("en")
|
theProject.data.setSpellLang("en")
|
||||||
theProject.data.setAuthors("Jane Smith\nJohn Smith")
|
theProject.data.setAuthors("Jane Smith\nJohn Smith")
|
||||||
theProject.setAutoReplace({"A": "B", "C": "D"})
|
theProject.data.setAutoReplace({"A": "B", "C": "D"})
|
||||||
|
|
||||||
# Create Dialog
|
# Create Dialog
|
||||||
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_MAIN)
|
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_MAIN)
|
||||||
@@ -365,9 +365,9 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mock
|
|||||||
|
|
||||||
# Set some values
|
# Set some values
|
||||||
theProject = nwGUI.theProject
|
theProject = nwGUI.theProject
|
||||||
theProject.autoReplace = {
|
theProject.data.setAutoReplace({
|
||||||
"A": "B", "C": "D"
|
"A": "B", "C": "D"
|
||||||
}
|
})
|
||||||
|
|
||||||
# Create Dialog
|
# Create Dialog
|
||||||
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_REPLACE)
|
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_REPLACE)
|
||||||
@@ -429,7 +429,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mock
|
|||||||
|
|
||||||
# Check Project
|
# Check Project
|
||||||
projSettings._doSave()
|
projSettings._doSave()
|
||||||
assert theProject.autoReplace == {
|
assert theProject.data.autoReplace == {
|
||||||
"A": "B", "C": "D", "This": "With This Stuff"
|
"A": "B", "C": "D", "This": "With This Stuff"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
|
|||||||
assert nwGUI.theProject.data.name == ""
|
assert nwGUI.theProject.data.name == ""
|
||||||
assert nwGUI.theProject.data.title == ""
|
assert nwGUI.theProject.data.title == ""
|
||||||
assert nwGUI.theProject.data.authors == []
|
assert nwGUI.theProject.data.authors == []
|
||||||
assert not nwGUI.theProject.spellCheck
|
assert nwGUI.theProject.data.spellCheck is False
|
||||||
|
|
||||||
# Check the files
|
# Check the files
|
||||||
projFile = os.path.join(fncProj, "nwProject.nwx")
|
projFile = os.path.join(fncProj, "nwProject.nwx")
|
||||||
@@ -197,7 +197,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
|
|||||||
assert nwGUI.theProject.data.name == "New Project"
|
assert nwGUI.theProject.data.name == "New Project"
|
||||||
assert nwGUI.theProject.data.title == "New Novel"
|
assert nwGUI.theProject.data.title == "New Novel"
|
||||||
assert nwGUI.theProject.data.authors == ["Jane Doe"]
|
assert nwGUI.theProject.data.authors == ["Jane Doe"]
|
||||||
assert nwGUI.theProject.spellCheck is False
|
assert nwGUI.theProject.data.spellCheck is False
|
||||||
|
|
||||||
# Check that tree items have been created
|
# Check that tree items have been created
|
||||||
assert nwGUI.projView.projTree._getTreeItem(C.hNovelRoot) is not None
|
assert nwGUI.projView.projTree._getTreeItem(C.hNovelRoot) is not None
|
||||||
|
|||||||
Reference in New Issue
Block a user