Move all remaining trivial project settings to the data class

This commit is contained in:
Veronica Berglyd Olsen
2022-10-31 15:55:33 +01:00
parent aeef8734b8
commit 9d283d2eae
12 changed files with 225 additions and 195 deletions
+58 -118
View File
@@ -74,10 +74,10 @@ class NWProject:
self._langData = {} # Localisation data self._langData = {} # Localisation data
# Project Status # Project Status
self.projOpened = 0 # The time stamp of when the project file was opened self._projOpened = 0 # The time stamp of when the project file was opened
self.projChanged = False # The project has unsaved changes self._projChanged = False # The project has unsaved changes
self.projAltered = False # The project has been altered this session self._projAltered = False # The project has been altered this session
self.lockedBy = None # Data on which computer has the project open self.lockedBy = None # Data on which computer has the project open
# Class Settings # Class Settings
self.projPath = None # The full path to where the currently open project is saved self.projPath = None # The full path to where the currently open project is saved
@@ -86,7 +86,6 @@ class NWProject:
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.projSpell = None # The spell check language, if different than default
self.projLang = None # The project language, used for builds
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 # Project Settings
@@ -95,17 +94,9 @@ class NWProject:
self.spellCheck = False # Controls the spellcheck-as-you-type feature self.spellCheck = False # Controls the spellcheck-as-you-type feature
self.statusItems = None # Novel file progress status values self.statusItems = None # Novel file progress status values
self.importItems = None # Note file importance values self.importItems = None # Note file importance values
self.lastEdited = None # The handle of the last file to be edited
self.lastViewed = None # The handle of the last file to be viewed
self.lastNovel = None # The handle of the last novel root viewed
self.lastOutline = None # The handle of the last outline root viewed
self.lastWCount = 0 # The project word count from last session
self.lastNovelWC = 0 # The novel files word count from last session
self.lastNotesWC = 0 # The note files word count from last session
self.currWCount = 0 # The project word count in current session self.currWCount = 0 # The project word count in current session
self.currNovelWC = 0 # The novel files word count in cutrent session self.currNovelWC = 0 # The novel files word count in cutrent session
self.currNotesWC = 0 # The note files word count in cutrent session self.currNotesWC = 0 # The note files word count in cutrent session
self.doBackup = True # Run project backup on exit
# Internal Mapping # Internal Mapping
self.tr = partial(QCoreApplication.translate, "NWProject") self.tr = partial(QCoreApplication.translate, "NWProject")
@@ -135,6 +126,18 @@ class NWProject:
def options(self): def options(self):
return self._optState return self._optState
@property
def projOpened(self):
return self._projOpened
@property
def projChanged(self):
return self._projChanged or self._data.changed
@property
def projAltered(self):
return self._projAltered
## ##
# Item Methods # Item Methods
## ##
@@ -243,9 +246,9 @@ class NWProject:
default values. default values.
""" """
# Project Status # Project Status
self.projOpened = 0 self._projOpened = 0
self.projChanged = False self._projChanged = False
self.projAltered = False self._projAltered = False
# Project Tree # Project Tree
self._projTree.clear() self._projTree.clear()
@@ -259,7 +262,6 @@ class NWProject:
self.projContent = None self.projContent = None
self.projDict = None self.projDict = None
self.projSpell = None self.projSpell = None
self.projLang = None
self.projFiles = [] self.projFiles = []
self.autoReplace = {} self.autoReplace = {}
self.titleFormat = { self.titleFormat = {
@@ -280,11 +282,6 @@ class NWProject:
self.importItems.write(None, self.tr("Minor"), (200, 50, 0)) self.importItems.write(None, self.tr("Minor"), (200, 50, 0))
self.importItems.write(None, self.tr("Major"), (200, 150, 0)) self.importItems.write(None, self.tr("Major"), (200, 150, 0))
self.importItems.write(None, self.tr("Main"), (50, 200, 0)) self.importItems.write(None, self.tr("Main"), (50, 200, 0))
self.lastEdited = None
self.lastViewed = None
self.lastWCount = 0
self.lastNovelWC = 0
self.lastNotesWC = 0
self.currWCount = 0 self.currWCount = 0
self.currNovelWC = 0 self.currNovelWC = 0
self.currNotesWC = 0 self.currNotesWC = 0
@@ -414,7 +411,7 @@ class NWProject:
# Finalise # Finalise
if popCustom or popMinimal: if popCustom or popMinimal:
self.projOpened = time() self._projOpened = time()
self.setProjectChanged(True) self.setProjectChanged(True)
self.saveProject(autoSave=True) self.saveProject(autoSave=True)
@@ -484,10 +481,10 @@ class NWProject:
# print(json.dumps(xmlData, indent=2)) # print(json.dumps(xmlData, indent=2))
nwxRoot = xmlData.get("xmlRoot", "") nwxRoot = xmlReader.xmlRoot
appVersion = xmlData.get("appVersion", self.tr("Unknown")) appVersion = xmlReader.appVersion or self.tr("Unknown")
hexVersion = xmlData.get("hexVersion", 0x0000) hexVersion = xmlReader.hexVersion or "0x0"
xmlVersion = xmlData.get("xmlVersion", self.tr("Unknown")) xmlVersion = xmlReader.xmlVersion or self.tr("Unknown")
if not xmlParsed: if not xmlParsed:
if xmlReader.state == XMLReadState.NOT_NWX_FILE: if xmlReader.state == XMLReadState.NOT_NWX_FILE:
@@ -555,17 +552,8 @@ class NWProject:
xmlSettings = xmlData.get("settings", {}) xmlSettings = xmlData.get("settings", {})
self.doBackup = xmlSettings.get("doBackup", False) self.spellCheck = self._data.spellCheck
self.projLang = xmlSettings.get("language", None) self.projSpell = self._data.spellLang
self.spellCheck = xmlSettings.get("spellCheck", False)
self.projSpell = xmlSettings.get("spellLang", None)
self.lastEdited = xmlSettings.get("lastEdited", None)
self.lastViewed = xmlSettings.get("lastViewed", None)
self.lastNovel = xmlSettings.get("lastNovel", None)
self.lastOutline = xmlSettings.get("lastOutline", None)
self.lastWCount = xmlSettings.get("lastWordCount", 0)
self.lastNovelWC = xmlSettings.get("novelWordCount", 0)
self.lastNotesWC = xmlSettings.get("notesWordCount", 0)
self.statusItems.unpack(xmlSettings.get("status", {})) self.statusItems.unpack(xmlSettings.get("status", {}))
self.importItems.unpack(xmlSettings.get("import", {})) self.importItems.unpack(xmlSettings.get("import", {}))
self.autoReplace = xmlSettings.get("autoReplace", {}) self.autoReplace = xmlSettings.get("autoReplace", {})
@@ -590,7 +578,9 @@ class NWProject:
self._deprecatedFiles() self._deprecatedFiles()
# Update recent projects # Update recent projects
self.mainConf.updateRecentCache(self.projPath, self._data.name, self.lastWCount, time()) self.mainConf.updateRecentCache(
self.projPath, self._data.name, self._data.getLastCount("total"), time()
)
self.mainConf.saveRecentCache() self.mainConf.saveRecentCache()
# Check the project tree consistency # Check the project tree consistency
@@ -605,8 +595,8 @@ class NWProject:
self._loadProjectLocalisation() self._loadProjectLocalisation()
self.updateWordCounts() self.updateWordCounts()
self.projOpened = time() self._projOpened = time()
self.projAltered = False self._projAltered = False
self._writeLockFile() self._writeLockFile()
self.setProjectChanged(False) self.setProjectChanged(False)
@@ -647,7 +637,7 @@ class NWProject:
}) })
self.updateWordCounts() self.updateWordCounts()
editTime = int(self._data.editTime + saveTime - self.projOpened) editTime = int(self._data.editTime + saveTime - self._projOpened)
# Save Project Meta # Save Project Meta
xProject = etree.SubElement(nwXML, "project") xProject = etree.SubElement(nwXML, "project")
@@ -660,14 +650,14 @@ class NWProject:
# Save Project Settings # Save Project Settings
xSettings = etree.SubElement(nwXML, "settings") xSettings = etree.SubElement(nwXML, "settings")
self._packProjectValue(xSettings, "doBackup", self.doBackup) self._packProjectValue(xSettings, "doBackup", self._data.doBackup)
self._packProjectValue(xSettings, "language", self.projLang) self._packProjectValue(xSettings, "language", self._data.language)
self._packProjectValue(xSettings, "spellCheck", self.spellCheck) self._packProjectValue(xSettings, "spellCheck", self._data.spellCheck)
self._packProjectValue(xSettings, "spellLang", self.projSpell) self._packProjectValue(xSettings, "spellLang", self._data.spellLang)
self._packProjectValue(xSettings, "lastEdited", self.lastEdited) self._packProjectValue(xSettings, "lastEdited", self._data.getLastHandle("editor"))
self._packProjectValue(xSettings, "lastViewed", self.lastViewed) self._packProjectValue(xSettings, "lastViewed", self._data.getLastHandle("viewer"))
self._packProjectValue(xSettings, "lastNovel", self.lastNovel) self._packProjectValue(xSettings, "lastNovel", self._data.getLastHandle("noveltree"))
self._packProjectValue(xSettings, "lastOutline", self.lastOutline) self._packProjectValue(xSettings, "lastOutline", self._data.getLastHandle("outline"))
self._packProjectValue(xSettings, "lastWordCount", self.currWCount) self._packProjectValue(xSettings, "lastWordCount", self.currWCount)
self._packProjectValue(xSettings, "novelWordCount", self.currNovelWC) self._packProjectValue(xSettings, "novelWordCount", self.currNovelWC)
self._packProjectValue(xSettings, "notesWordCount", self.currNotesWC) self._packProjectValue(xSettings, "notesWordCount", self.currNotesWC)
@@ -942,28 +932,6 @@ class NWProject:
return True return True
def setProjBackup(self, doBackup):
"""Set whether projects should be backed up or not. The user
will be notified in case required settings are missing.
"""
self.doBackup = doBackup
if doBackup:
if not os.path.isdir(self.mainConf.backupPath):
self.mainGui.makeAlert(self.tr(
"You must set a valid backup path in Preferences to use "
"the automatic project backup feature."
), nwAlert.WARN)
return False
if self._data.name == "":
self.mainGui.makeAlert(self.tr(
"You must set a valid project name in Project Settings to "
"use the automatic project backup feature."
), nwAlert.WARN)
return False
return True
def setSpellCheck(self, theMode): def setSpellCheck(self, theMode):
"""Enable/disable spell checking. """Enable/disable spell checking.
""" """
@@ -986,8 +954,8 @@ class NWProject:
"""Set the project-specific language. """Set the project-specific language.
""" """
theLang = checkStringNone(theLang, None) theLang = checkStringNone(theLang, None)
if self.projLang != theLang: if self._data.language != theLang:
self.projLang = theLang self._data.setLanguage(theLang)
self._loadProjectLocalisation() self._loadProjectLocalisation()
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
@@ -1003,38 +971,6 @@ class NWProject:
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
def setLastEdited(self, tHandle):
"""Set last edited project item.
"""
if self.lastEdited != tHandle:
self.lastEdited = tHandle
self.setProjectChanged(True)
return True
def setLastViewed(self, tHandle):
"""Set last viewed project item.
"""
if self.lastViewed != tHandle:
self.lastViewed = tHandle
self.setProjectChanged(True)
return True
def setLastNovelViewed(self, tHandle):
"""Set last viewed novel root in the novel tree.
"""
if self.lastNovel != tHandle:
self.lastNovel = tHandle
self.setProjectChanged(True)
return True
def setLastOutlineViewed(self, tHandle):
"""Set last viewed novel root in the outline view.
"""
if self.lastOutline != tHandle:
self.lastOutline = tHandle
self.setProjectChanged(True)
return True
def setStatusColours(self, newCols, delCols): def setStatusColours(self, newCols, delCols):
"""Update the list of novel file status flags. """Update the list of novel file status flags.
""" """
@@ -1068,12 +1004,15 @@ class NWProject:
"""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.
""" """
self.projChanged = bValue self._projChanged = bValue
self.mainGui.mainStatus.doUpdateProjectStatus(bValue) self.mainGui.mainStatus.doUpdateProjectStatus(bValue)
if bValue: if bValue is True:
# If we've changed the project at all, this should be True # If we've changed the project at all, this should be True
self.projAltered = True self._projAltered = True
return self.projChanged else:
# If we're resetting the status, also reset for data class
self._data.resetProjectChanged()
return self._projChanged
## ##
# Getters # Getters
@@ -1083,7 +1022,7 @@ class NWProject:
"""Get the total project edit time, including the time spent in """Get the total project edit time, including the time spent in
the current session. the current session.
""" """
return round(self._data.editTime + time() - self.projOpened) return round(self._data.editTime + time() - self._projOpened)
def getProjectItems(self): def getProjectItems(self):
"""This function ensures that the item tree loaded is sent to """This function ensures that the item tree loaded is sent to
@@ -1193,11 +1132,11 @@ class NWProject:
def _loadProjectLocalisation(self): def _loadProjectLocalisation(self):
"""Load the language data for the current project language. """Load the language data for the current project language.
""" """
if self.projLang is None: if self._data.language is None:
self._langData = {} self._langData = {}
return False return False
langFile = os.path.join(self.mainConf.nwLangPath, "project_%s.json" % self.projLang) langFile = os.path.join(self.mainConf.nwLangPath, "project_%s.json" % self._data.language)
if not os.path.isfile(langFile): if not os.path.isfile(langFile):
langFile = os.path.join(self.mainConf.nwLangPath, "project_en_GB.json") langFile = os.path.join(self.mainConf.nwLangPath, "project_en_GB.json")
@@ -1421,8 +1360,9 @@ class NWProject:
isFile = os.path.isfile(sessionFile) isFile = os.path.isfile(sessionFile)
nowTime = time() nowTime = time()
sessDiff = self.currWCount - self.lastWCount lastCount = self._data.getLastCount("total")
sessTime = nowTime - self.projOpened sessDiff = self.currWCount - lastCount
sessTime = nowTime - self._projOpened
logger.info("The session lasted %d sec and added %d words", int(sessTime), sessDiff) logger.info("The session lasted %d sec and added %d words", int(sessTime), sessDiff)
if sessTime < 300 and sessDiff == 0: if sessTime < 300 and sessDiff == 0:
@@ -1433,14 +1373,14 @@ class NWProject:
with open(sessionFile, mode="a+", encoding="utf-8") as outFile: with open(sessionFile, mode="a+", encoding="utf-8") as outFile:
if not isFile: if not isFile:
# It's a new file, so add a header # It's a new file, so add a header
if self.lastWCount > 0: if lastCount > 0:
outFile.write("# Offset %d\n" % self.lastWCount) outFile.write("# Offset %d\n" % lastCount)
outFile.write("# %-17s %-19s %8s %8s %8s\n" % ( outFile.write("# %-17s %-19s %8s %8s %8s\n" % (
"Start Time", "End Time", "Novel", "Notes", "Idle" "Start Time", "End Time", "Novel", "Notes", "Idle"
)) ))
outFile.write("%-19s %-19s %8d %8d %8d\n" % ( outFile.write("%-19s %-19s %8d %8d %8d\n" % (
formatTimeStamp(self.projOpened), formatTimeStamp(self._projOpened),
formatTimeStamp(nowTime), formatTimeStamp(nowTime),
self.currNovelWC, self.currNovelWC,
self.currNotesWC, self.currNotesWC,
+70 -1
View File
@@ -25,7 +25,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
from novelwriter.common import checkInt, simplified from novelwriter.common import (
checkBool, checkInt, checkStringNone, simplified
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -42,6 +44,14 @@ class NWProjectData:
self._autoCount = 0 self._autoCount = 0
self._editTime = 0 self._editTime = 0
# Project Settings
self._doBackup = True
self._language = None
self._spellCheck = False
self._spellLang = None
self._lastHandle = {}
self._lastCount = {}
# Internal # Internal
self._changed = False self._changed = False
@@ -75,6 +85,26 @@ class NWProjectData:
def editTime(self): def editTime(self):
return self._editTime return self._editTime
@property
def doBackup(self):
return self._doBackup
@property
def language(self):
return self._language
@property
def spellCheck(self):
return self._spellCheck
@property
def spellLang(self):
return self._spellLang
@property
def changed(self):
return self._changed
## ##
# Methods # Methods
## ##
@@ -94,10 +124,19 @@ class NWProjectData:
self._changed = True self._changed = True
return return
def resetProjectChanged(self):
self._changed = False
## ##
# Getters # Getters
## ##
def getLastHandle(self, component):
return self._lastHandle.get(component, None)
def getLastCount(self, type):
return self._lastCount.get(type, 0)
def getAuthors(self, trAnd="and"): def getAuthors(self, trAnd="and"):
"""Return a formatted string of authors. """Return a formatted string of authors.
""" """
@@ -155,4 +194,34 @@ class NWProjectData:
self._changed = True self._changed = True
return return
def setDoBackup(self, value):
self._doBackup = checkBool(value, False)
self._changed = True
return
def setLanguage(self, value):
self._language = checkStringNone(value, None)
self._changed = True
return
def setSpellCheck(self, value):
self._spellCheck = checkBool(value, False)
self._changed = True
return
def setSpellLang(self, value):
self._spellLang = checkStringNone(value, None)
self._changed = True
return
def setLastHandle(self, value, component):
self._lastHandle[component] = checkStringNone(value, None)
self._changed = True
return
def setLastCount(self, value, type):
self._lastCount[type] = checkInt(value, 0)
self._changed = True
return
# END Class NWProjectData # END Class NWProjectData
+52 -20
View File
@@ -69,10 +69,16 @@ class ProjectXMLReader:
self._state = XMLReadState.NO_ACTION self._state = XMLReadState.NO_ACTION
self._data = {} self._data = {}
self._version = 0x0000 self._content = []
self._statusData = {} self._statusData = {}
self._statusMap = {} self._statusMap = {}
self._root = ""
self._version = 0x0000
self._appVersion = ""
self._hexVersion = ""
self._timeStamp = ""
return return
## ##
@@ -83,10 +89,34 @@ class ProjectXMLReader:
def data(self): def data(self):
return self._data return self._data
@property
def content(self):
return self._content
@property @property
def state(self): def state(self):
return self._state return self._state
@property
def xmlRoot(self):
return self._root
@property
def xmlVersion(self):
return self._version
@property
def appVersion(self):
return self._appVersion
@property
def hexVersion(self):
return self._hexVersion
@property
def timeStamp(self):
return self._timeStamp
## ##
# Methods # Methods
## ##
@@ -95,6 +125,7 @@ class ProjectXMLReader:
"""Read and parse the project XML file. """Read and parse the project XML file.
""" """
self._data = {} self._data = {}
self._content = []
try: try:
xml = etree.parse(self._path) xml = etree.parse(self._path)
@@ -119,8 +150,8 @@ class ProjectXMLReader:
return False return False
xRoot = xml.getroot() xRoot = xml.getroot()
self._data["xmlRoot"] = str(xRoot.tag) self._root = str(xRoot.tag)
if xRoot.tag != "novelWriterXML": if self._root != "novelWriterXML":
self._state = XMLReadState.NOT_NWX_FILE self._state = XMLReadState.NOT_NWX_FILE
return False return False
@@ -147,17 +178,16 @@ class ProjectXMLReader:
self._state = XMLReadState.UNKNOWN_VERSION self._state = XMLReadState.UNKNOWN_VERSION
return False return False
self._data["xmlVersion"] = self._version self._appVersion = str(xRoot.attrib.get("appVersion", ""))
self._data["appVersion"] = str(xRoot.attrib.get("appVersion", "")) self._hexVersion = str(xRoot.attrib.get("appVersion", ""))
self._data["hexVersion"] = str(xRoot.attrib.get("appVersion", "")) self._timeStamp = str(xRoot.attrib.get("timeStamp", ""))
self._data["timeStamp"] = str(xRoot.attrib.get("timeStamp", ""))
status = True status = True
for xSection in xRoot: for xSection in xRoot:
if xSection.tag == "project": if xSection.tag == "project":
status &= self._parseProjectMeta(xSection, projData) status &= self._parseProjectMeta(xSection, projData)
elif xSection.tag == "settings": elif xSection.tag == "settings":
status &= self._parseProjectSettings(xSection) status &= self._parseProjectSettings(xSection, projData)
elif xSection.tag == "content": elif xSection.tag == "content":
if self._version >= 0x0104: if self._version >= 0x0104:
status &= self._parseProjectContent(xSection) status &= self._parseProjectContent(xSection)
@@ -202,7 +232,7 @@ class ProjectXMLReader:
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): def _parseProjectSettings(self, xSection, projData):
"""Parse the settings section of the XML file. """Parse the settings section of the XML file.
""" """
logger.debug("Parsing xml <root/settings>") logger.debug("Parsing xml <root/settings>")
@@ -212,27 +242,27 @@ class ProjectXMLReader:
titleFormat = {} titleFormat = {}
for xItem in xSection: for xItem in xSection:
if xItem.tag == "doBackup": if xItem.tag == "doBackup":
data["doBackup"] = checkBool(xItem.text, False) projData.setDoBackup(xItem.text)
elif xItem.tag == "language": elif xItem.tag == "language":
data["language"] = checkStringNone(xItem.text, None) projData.setLanguage(xItem.text)
elif xItem.tag == "spellCheck": elif xItem.tag == "spellCheck":
data["spellCheck"] = checkBool(xItem.text, False) projData.setSpellCheck(xItem.text)
elif xItem.tag == "spellLang": elif xItem.tag == "spellLang":
data["spellLang"] = checkStringNone(xItem.text, None) projData.setSpellLang(xItem.text)
elif xItem.tag == "lastEdited": elif xItem.tag == "lastEdited":
data["lastEdited"] = checkStringNone(xItem.text, None) projData.setLastHandle(xItem.text, "editor")
elif xItem.tag == "lastViewed": elif xItem.tag == "lastViewed":
data["lastViewed"] = checkStringNone(xItem.text, None) projData.setLastHandle(xItem.text, "viewer")
elif xItem.tag == "lastNovel": elif xItem.tag == "lastNovel":
data["lastNovel"] = checkStringNone(xItem.text, None) projData.setLastHandle(xItem.text, "noveltree")
elif xItem.tag == "lastOutline": elif xItem.tag == "lastOutline":
data["lastOutline"] = checkStringNone(xItem.text, None) projData.setLastHandle(xItem.text, "outline")
elif xItem.tag == "lastWordCount": elif xItem.tag == "lastWordCount":
data["lastWordCount"] = checkInt(xItem.text, 0) projData.setLastCount(xItem.text, "total")
elif xItem.tag == "novelWordCount": elif xItem.tag == "novelWordCount":
data["novelWordCount"] = checkInt(xItem.text, 0) projData.setLastCount(xItem.text, "novel")
elif xItem.tag == "notesWordCount": elif xItem.tag == "notesWordCount":
data["notesWordCount"] = checkInt(xItem.text, 0) projData.setLastCount(xItem.text, "notes")
elif xItem.tag == "status": elif xItem.tag == "status":
data["status"] = self._parseStatusImport(xItem, "status") data["status"] = self._parseStatusImport(xItem, "status")
elif xItem.tag in ("import", "importance"): elif xItem.tag in ("import", "importance"):
@@ -293,6 +323,7 @@ class ProjectXMLReader:
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) data.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)
@@ -357,6 +388,7 @@ class ProjectXMLReader:
item["type"] = "ROOT" item["type"] = "ROOT"
data.append(item) data.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)
+2 -2
View File
@@ -117,7 +117,7 @@ class GuiProjectSettings(PagedDialog):
self.theProject.data.setName(projName) self.theProject.data.setName(projName)
self.theProject.data.setTitle(bookTitle) self.theProject.data.setTitle(bookTitle)
self.theProject.data.setAuthors(bookAuthors) self.theProject.data.setAuthors(bookAuthors)
self.theProject.setProjBackup(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.setSpellLang(spellLang)
@@ -258,7 +258,7 @@ class GuiProjectEditMain(QWidget):
self.spellLang.setCurrentIndex(spellIdx) self.spellLang.setCurrentIndex(spellIdx)
self.doBackup = QSwitch(self) self.doBackup = QSwitch(self)
self.doBackup.setChecked(not self.theProject.doBackup) self.doBackup.setChecked(not self.theProject.data.doBackup)
self.mainForm.addRow( self.mainForm.addRow(
self.tr("No backup on close"), self.tr("No backup on close"),
self.doBackup, self.doBackup,
+1 -1
View File
@@ -217,7 +217,7 @@ class GuiDocViewer(QTextBrowser):
self.verticalScrollBar().setValue(sPos) self.verticalScrollBar().setValue(sPos)
self._docHandle = tHandle self._docHandle = tHandle
self.theProject.setLastViewed(tHandle) self.theProject._data.setLastHandle(tHandle, "viewer")
self.docHeader.setTitleFromHandle(self._docHandle) self.docHeader.setTitleFromHandle(self._docHandle)
self.updateDocMargins() self.updateDocMargins()
+6 -5
View File
@@ -109,7 +109,7 @@ class GuiNovelView(QWidget):
def refreshTree(self): def refreshTree(self):
"""Refresh the current tree. """Refresh the current tree.
""" """
self.novelTree.refreshTree(rootHandle=self.theProject.lastNovel) self.novelTree.refreshTree(rootHandle=self.theProject.data.getLastHandle("noveltree"))
return return
def clearProject(self): def clearProject(self):
@@ -122,7 +122,7 @@ class GuiNovelView(QWidget):
def openProjectTasks(self): def openProjectTasks(self):
"""Run open project tasks. """Run open project tasks.
""" """
lastNovel = self.theProject.lastNovel lastNovel = self.theProject.data.getLastHandle("noveltree")
if lastNovel not in self.theProject.tree: if lastNovel not in self.theProject.tree:
lastNovel = self.theProject.tree.findRoot(nwItemClass.NOVEL) lastNovel = self.theProject.tree.findRoot(nwItemClass.NOVEL)
@@ -319,7 +319,7 @@ class GuiNovelToolBar(QWidget):
def _refreshNovelTree(self): def _refreshNovelTree(self):
"""Rebuild the current tree. """Rebuild the current tree.
""" """
rootHandle = self.theProject.lastNovel rootHandle = self.theProject.data.getLastHandle("noveltree")
self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True) self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True)
return return
@@ -485,7 +485,7 @@ class GuiNovelTree(QTreeWidget):
titleKey = selItem[0].data(self.C_TITLE, self.D_KEY) titleKey = selItem[0].data(self.C_TITLE, self.D_KEY)
self._populateTree(rootHandle) self._populateTree(rootHandle)
self.theProject.setLastNovelViewed(rootHandle) self.theProject.data.setLastHandle(rootHandle, "noveltree")
if titleKey is not None and titleKey in self._treeMap: if titleKey is not None and titleKey in self._treeMap:
self._treeMap[titleKey].setSelected(True) self._treeMap[titleKey].setSelected(True)
@@ -523,7 +523,8 @@ class GuiNovelTree(QTreeWidget):
self._lastCol = colType self._lastCol = colType
self.setColumnHidden(self.C_EXTRA, colType == NovelTreeColumn.HIDDEN) self.setColumnHidden(self.C_EXTRA, colType == NovelTreeColumn.HIDDEN)
if doRefresh: if doRefresh:
self.refreshTree(rootHandle=self.theProject.lastNovel, overRide=True) lastNovel = self.theProject.data.getLastHandle("noveltree")
self.refreshTree(rootHandle=lastNovel, overRide=True)
return return
def setActiveHandle(self, tHandle): def setActiveHandle(self, tHandle):
+3 -3
View File
@@ -114,7 +114,7 @@ class GuiOutlineView(QWidget):
def refreshTree(self): def refreshTree(self):
"""Refresh the current tree. """Refresh the current tree.
""" """
self.outlineTree.refreshTree(rootHandle=self.theProject.lastOutline) self.outlineTree.refreshTree(rootHandle=self.theProject.data.getLastHandle("outline"))
return return
def clearProject(self): def clearProject(self):
@@ -126,7 +126,7 @@ class GuiOutlineView(QWidget):
def openProjectTasks(self): def openProjectTasks(self):
"""Run open project tasks. """Run open project tasks.
""" """
lastOutline = self.theProject.lastOutline lastOutline = self.theProject.data.getLastHandle("outline")
if not (lastOutline in self.theProject.tree or lastOutline is None): if not (lastOutline in self.theProject.tree or lastOutline is None):
lastOutline = self.theProject.tree.findRoot(nwItemClass.NOVEL) lastOutline = self.theProject.tree.findRoot(nwItemClass.NOVEL)
@@ -504,7 +504,7 @@ class GuiOutlineTree(QTreeWidget):
return return
self._populateTree(rootHandle) self._populateTree(rootHandle)
self.theProject.setLastOutlineViewed(rootHandle or None) self.theProject.data.setLastHandle(rootHandle or None, "outline")
return return
+13 -11
View File
@@ -417,7 +417,7 @@ class GuiMain(QMainWindow):
if self.theProject.projAltered: if self.theProject.projAltered:
saveOK = self.saveProject() saveOK = self.saveProject()
doBackup = False doBackup = False
if self.theProject.doBackup and self.mainConf.backupOnClose: if self.theProject.data.doBackup and self.mainConf.backupOnClose:
doBackup = True doBackup = True
if self.mainConf.askBeforeBackup: if self.mainConf.askBeforeBackup:
msgYes = self.askQuestion( msgYes = self.askQuestion(
@@ -532,11 +532,13 @@ class GuiMain(QMainWindow):
self._updateStatusWordCount() self._updateStatusWordCount()
# Restore previously open documents, if any # Restore previously open documents, if any
if self.theProject.lastEdited is not None: lastEdited = self.theProject.data.getLastHandle("editor")
self.openDocument(self.theProject.lastEdited, doScroll=True) if lastEdited is not None:
self.openDocument(lastEdited, doScroll=True)
if self.theProject.lastViewed is not None: lastViewed = self.theProject.data.getLastHandle("viewer")
self.viewDocument(self.theProject.lastViewed) if lastViewed is not None:
self.viewDocument(lastViewed)
# Check if we need to rebuild the index # Check if we need to rebuild the index
if self.theProject.index.indexBroken: if self.theProject.index.indexBroken:
@@ -607,7 +609,7 @@ class GuiMain(QMainWindow):
if self.docEditor.loadText(tHandle, tLine): if self.docEditor.loadText(tHandle, tLine):
if changeFocus: if changeFocus:
self.docEditor.setFocus() self.docEditor.setFocus()
self.theProject.setLastEdited(tHandle) self.theProject.data.setLastHandle(tHandle, "editor")
self.projView.setSelectedHandle(tHandle, doScroll=doScroll) self.projView.setSelectedHandle(tHandle, doScroll=doScroll)
self.novelView.setActiveHandle(tHandle) self.novelView.setActiveHandle(tHandle)
else: else:
@@ -676,7 +678,7 @@ class GuiMain(QMainWindow):
tHandle = self.projView.getSelectedHandle() tHandle = self.projView.getSelectedHandle()
if tHandle is None: if tHandle is None:
tHandle = self.theProject.lastViewed tHandle = self.theProject.data.getLastHandle("viewer")
if tHandle is None: if tHandle is None:
logger.debug("No document to view, giving up") logger.debug("No document to view, giving up")
@@ -1223,14 +1225,14 @@ class GuiMain(QMainWindow):
"""Close the document edit panel. This does not hide the editor. """Close the document edit panel. This does not hide the editor.
""" """
self.closeDocument() self.closeDocument()
self.theProject.setLastEdited(None) self.theProject.data.setLastHandle(None, "editor")
return return
def closeDocViewer(self): def closeDocViewer(self):
"""Close the document view panel. """Close the document view panel.
""" """
self.docViewer.clearViewer() self.docViewer.clearViewer()
self.theProject.setLastViewed(None) self.theProject.data.setLastHandle(None, "viewer")
bPos = self.splitMain.sizes() bPos = self.splitMain.sizes()
self.splitView.setVisible(False) self.splitView.setVisible(False)
self.splitDocs.setSizes([bPos[1], 0]) self.splitDocs.setSizes([bPos[1], 0])
@@ -1556,10 +1558,10 @@ class GuiMain(QMainWindow):
self.theProject.updateWordCounts() self.theProject.updateWordCounts()
if self.mainConf.incNotesWCount: if self.mainConf.incNotesWCount:
currWords = self.theProject.currWCount currWords = self.theProject.currWCount
diffWords = currWords - self.theProject.lastWCount diffWords = currWords - self.theProject.data.getLastCount("total")
else: else:
currWords = self.theProject.currNovelWC currWords = self.theProject.currNovelWC
diffWords = currWords - self.theProject.lastNovelWC diffWords = currWords - self.theProject.data.getLastCount("novel")
self.mainStatus.setProjectStats(currWords, diffWords) self.mainStatus.setProjectStats(currWords, diffWords)
+1 -1
View File
@@ -168,7 +168,7 @@ class GuiBuildNovel(QDialog):
for langID, langName in theLangs: for langID, langName in theLangs:
self.buildLang.addItem(langName, langID) self.buildLang.addItem(langName, langID)
langIdx = self.buildLang.findData(self.theProject.projLang) langIdx = self.buildLang.findData(self.theProject.data.language)
if langIdx != -1: if langIdx != -1:
self.buildLang.setCurrentIndex(langIdx) self.buildLang.setCurrentIndex(langIdx)
+16 -30
View File
@@ -927,7 +927,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
# Edit Time # Edit Time
theProject.data.setEditTime(1234) theProject.data.setEditTime(1234)
theProject.projOpened = 1600000000 theProject._projOpened = 1600000000
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("novelwriter.core.project.time", lambda: 1600005600) mp.setattr("novelwriter.core.project.time", lambda: 1600005600)
assert theProject.getCurrentEditTime() == 6834 assert theProject.getCurrentEditTime() == 6834
@@ -939,28 +939,14 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
assert theProject.trashFolder() == hTrash assert theProject.trashFolder() == hTrash
assert theProject.trashFolder() == hTrash assert theProject.trashFolder() == hTrash
# Project backup
assert theProject.doBackup is True
assert theProject.setProjBackup(False)
assert theProject.doBackup is False
assert not theProject.setProjBackup(True)
theProject.mainConf.backupPath = tmpDir
assert theProject.setProjBackup(True)
theProject.data.setName("")
assert not theProject.setProjBackup(True)
theProject.data.setName("A Name")
assert theProject.setProjBackup(True)
# Spell check # Spell check
theProject.projChanged = False theProject.setProjectChanged(False)
assert theProject.setSpellCheck(True) assert theProject.setSpellCheck(True)
assert not theProject.setSpellCheck(False) assert not theProject.setSpellCheck(False)
assert theProject.projChanged assert theProject.projChanged
# Spell language # Spell language
theProject.projChanged = False theProject.setProjectChanged(False)
assert theProject.projSpell is None assert theProject.projSpell is None
assert theProject.setSpellLang(None) is False assert theProject.setSpellLang(None) is False
assert theProject.projSpell is None assert theProject.projSpell is None
@@ -971,31 +957,31 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
assert theProject.projChanged assert theProject.projChanged
# Project Language # Project Language
theProject.projChanged = False theProject.setProjectChanged(False)
theProject.projLang = "en" theProject.data.setLanguage("en")
assert theProject.setProjectLang(None) is True assert theProject.setProjectLang(None) is True
assert theProject.projLang is None assert theProject.data.language is None
assert theProject.setProjectLang("en_GB") is True assert theProject.setProjectLang("en_GB") is True
assert theProject.projLang == "en_GB" assert theProject.data.language == "en_GB"
# Language Lookup # Language Lookup
assert theProject.localLookup(1) == "One" assert theProject.localLookup(1) == "One"
assert theProject.localLookup(10) == "Ten" assert theProject.localLookup(10) == "Ten"
# Last edited # Last edited
theProject.projChanged = False theProject.setProjectChanged(False)
assert theProject.setLastEdited("0123456789abc") theProject._data.setLastHandle("0123456789abc", "editor")
assert theProject.lastEdited == "0123456789abc" assert theProject._data.getLastHandle("editor") == "0123456789abc"
assert theProject.projChanged assert theProject.projChanged
# Last viewed # Last viewed
theProject.projChanged = False theProject.setProjectChanged(False)
assert theProject.setLastViewed("0123456789abc") theProject._data.setLastHandle("0123456789abc", "viewer")
assert theProject.lastViewed == "0123456789abc" assert theProject._data.getLastHandle("viewer") == "0123456789abc"
assert theProject.projChanged assert theProject.projChanged
# Autoreplace # Autoreplace
theProject.projChanged = False theProject.setProjectChanged(False)
assert theProject.setAutoReplace({"A": "B", "C": "D"}) assert theProject.setAutoReplace({"A": "B", "C": "D"})
assert theProject.autoReplace == {"A": "B", "C": "D"} assert theProject.autoReplace == {"A": "B", "C": "D"}
assert theProject.projChanged assert theProject.projChanged
@@ -1019,7 +1005,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
# Session stats # Session stats
theProject.currWCount = 200 theProject.currWCount = 200
theProject.lastWCount = 100 theProject.data.setLastCount(100, "total")
with monkeypatch.context() as mp: with monkeypatch.context() as mp:
mp.setattr("os.path.isdir", lambda *a, **k: False) mp.setattr("os.path.isdir", lambda *a, **k: False)
assert not theProject._appendSessionStats(idleTime=0) assert not theProject._appendSessionStats(idleTime=0)
@@ -1033,7 +1019,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
assert theProject.projMeta == os.path.join(fncDir, "meta") assert theProject.projMeta == os.path.join(fncDir, "meta")
statsFile = os.path.join(theProject.projMeta, nwFiles.SESS_STATS) statsFile = os.path.join(theProject.projMeta, nwFiles.SESS_STATS)
theProject.projOpened = 1600002000 theProject._projOpened = 1600002000
theProject.currNovelWC = 200 theProject.currNovelWC = 200
theProject.currNotesWC = 100 theProject.currNotesWC = 100
+2 -2
View File
@@ -137,7 +137,7 @@ def testCoreToken_TextOps(monkeypatch, nwMinimal, mockGUI):
"""Test handling files and text in the Tokenizer class. """Test handling files and text in the Tokenizer class.
""" """
theProject = NWProject(mockGUI) theProject = NWProject(mockGUI)
theProject.projLang = "en" theProject.data.setLanguage("en")
theProject._loadProjectLocalisation() theProject._loadProjectLocalisation()
theToken = BareTokenizer(theProject) theToken = BareTokenizer(theProject)
@@ -884,7 +884,7 @@ def testCoreToken_ProcessHeaders(mockGUI):
"""Test the header and page parser of the Tokenizer class. """Test the header and page parser of the Tokenizer class.
""" """
theProject = NWProject(mockGUI) theProject = NWProject(mockGUI)
theProject.projLang = "en" theProject.data.setLanguage("en")
theProject._loadProjectLocalisation() theProject._loadProjectLocalisation()
theToken = BareTokenizer(theProject) theToken = BareTokenizer(theProject)
+1 -1
View File
@@ -195,7 +195,7 @@ def buildTestProject(theObject, projPath):
aDoc.writeDocument("### %s\n\n" % theProject.tr("New Scene")) aDoc.writeDocument("### %s\n\n" % theProject.tr("New Scene"))
theProject.index.reIndexHandle(xHandle[8]) theProject.index.reIndexHandle(xHandle[8])
theProject.projOpened = time.time() theProject._projOpened = time.time()
theProject.setProjectChanged(True) theProject.setProjectChanged(True)
theProject.saveProject(autoSave=True) theProject.saveProject(autoSave=True)