Move the remaining project meta settings to project data class

This commit is contained in:
Veronica Berglyd Olsen
2022-10-31 00:28:10 +01:00
parent 192806a46d
commit aeef8734b8
11 changed files with 115 additions and 118 deletions
+19 -71
View File
@@ -78,9 +78,6 @@ class NWProject:
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
self.saveCount = 0 # Meta data: number of saves
self.autoCount = 0 # Meta data: number of automatic saves
self.editTime = 0 # The accumulated edit time read from the project file
# 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
@@ -92,10 +89,6 @@ class NWProject:
self.projLang = None # The project language, used for builds 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 Meta
self.bookTitle = "" # The final title; should only be used for exports
self.bookAuthors = [] # A list of book authors
# Project Settings # Project Settings
self.autoReplace = {} # Text to auto-replace on exports self.autoReplace = {} # Text to auto-replace on exports
self.titleFormat = {} # The formatting of titles for exports self.titleFormat = {} # The formatting of titles for exports
@@ -253,12 +246,12 @@ class NWProject:
self.projOpened = 0 self.projOpened = 0
self.projChanged = False self.projChanged = False
self.projAltered = False self.projAltered = False
self.saveCount = 0
self.autoCount = 0
# Project Tree # Project Tree
self._projTree.clear() self._projTree.clear()
self._data = NWProjectData()
# Project Settings # Project Settings
self.projPath = None self.projPath = None
self.projMeta = None self.projMeta = None
@@ -268,8 +261,6 @@ class NWProject:
self.projSpell = None self.projSpell = None
self.projLang = None self.projLang = None
self.projFiles = [] self.projFiles = []
self.bookTitle = ""
self.bookAuthors = []
self.autoReplace = {} self.autoReplace = {}
self.titleFormat = { self.titleFormat = {
"title": "%title%", "title": "%title%",
@@ -332,16 +323,18 @@ class NWProject:
if not self.setProjectPath(projPath, newProject=True): if not self.setProjectPath(projPath, newProject=True):
return False return False
self.data.setName(projName) self._data.setName(projName)
self.setBookTitle(projTitle) self._data.setTitle(projTitle)
self.setBookAuthors(projAuthors) self._data.setAuthors(projAuthors)
hNovelRoot = self.newRoot(nwItemClass.NOVEL) hNovelRoot = self.newRoot(nwItemClass.NOVEL)
hTitlePage = self.newFile(self.tr("Title Page"), hNovelRoot) hTitlePage = self.newFile(self.tr("Title Page"), hNovelRoot)
titlePage = "#! %s\n\n" % (self.bookTitle if self.bookTitle else self._data.name) titlePage = "#! %s\n\n" % (self._data.title if self._data.title else self._data.name)
if self.bookAuthors: if self._data.authors:
titlePage = "%s>> %s %s <<\n" % (titlePage, self.tr("By"), self.getAuthors()) titlePage = "%s>> %s %s <<\n" % (
titlePage, self.tr("By"), self._data.getAuthors(self.tr("and"))
)
aDoc = NWDoc(self, hTitlePage) aDoc = NWDoc(self, hTitlePage)
aDoc.writeDocument(titlePage) aDoc.writeDocument(titlePage)
@@ -557,14 +550,8 @@ class NWProject:
# Extract Data # Extract Data
# ============ # ============
self.bookTitle = self._data.title
self.bookAuthors = self._data.autors
self.saveCount = self._data.saveCount
self.autoCount = self._data.autoCount
self.editTime = self._data.editTime
logger.info("Project Name: '%s'", self._data.name) logger.info("Project Name: '%s'", self._data.name)
logger.info("Project Title: '%s'", self.bookTitle) logger.info("Project Title: '%s'", self._data.title)
xmlSettings = xmlData.get("settings", {}) xmlSettings = xmlData.get("settings", {})
@@ -646,9 +633,9 @@ class NWProject:
logger.info("Saving project: %s", self.projPath) logger.info("Saving project: %s", self.projPath)
if autoSave: if autoSave:
self.autoCount += 1 self._data.incAutoCount()
else: else:
self.saveCount += 1 self._data.incSaveCount()
# Root element and project details # Root element and project details
logger.debug("Writing project meta") logger.debug("Writing project meta")
@@ -660,15 +647,15 @@ class NWProject:
}) })
self.updateWordCounts() self.updateWordCounts()
editTime = int(self.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")
self._packProjectValue(xProject, "name", self._data.name) self._packProjectValue(xProject, "name", self._data.name)
self._packProjectValue(xProject, "title", self.bookTitle) self._packProjectValue(xProject, "title", self._data.title)
self._packProjectValue(xProject, "author", self.bookAuthors) self._packProjectValue(xProject, "author", self._data.authors)
self._packProjectValue(xProject, "saveCount", str(self.saveCount)) self._packProjectValue(xProject, "saveCount", str(self._data.saveCount))
self._packProjectValue(xProject, "autoCount", str(self.autoCount)) self._packProjectValue(xProject, "autoCount", str(self._data.autoCount))
self._packProjectValue(xProject, "editTime", str(editTime)) self._packProjectValue(xProject, "editTime", str(editTime))
# Save Project Settings # Save Project Settings
@@ -955,30 +942,6 @@ class NWProject:
return True return True
def setBookTitle(self, bookTitle):
"""Set the book title, that is, the title to include in exports.
"""
self.bookTitle = simplified(bookTitle)
self.setProjectChanged(True)
return True
def setBookAuthors(self, bookAuthors):
"""A line-separated list of authors, parsed into an array.
"""
if not isinstance(bookAuthors, str):
return False
self.bookAuthors = []
for bookAuthor in bookAuthors.splitlines():
bookAuthor = simplified(bookAuthor)
if bookAuthor == "":
continue
self.bookAuthors.append(bookAuthor)
self.setProjectChanged(True)
return True
def setProjBackup(self, doBackup): def setProjBackup(self, doBackup):
"""Set whether projects should be backed up or not. The user """Set whether projects should be backed up or not. The user
will be notified in case required settings are missing. will be notified in case required settings are missing.
@@ -1116,26 +1079,11 @@ class NWProject:
# Getters # Getters
## ##
def getAuthors(self):
"""Return a formatted string of authors.
"""
nAuth = len(self.bookAuthors)
authString = ""
if nAuth == 1:
authString = self.bookAuthors[0]
elif nAuth > 1:
authString = "%s %s %s" % (
", ".join(self.bookAuthors[0:-1]), self.tr("and"), self.bookAuthors[-1]
)
return authString
def getCurrentEditTime(self): def getCurrentEditTime(self):
"""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.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
+49 -3
View File
@@ -60,7 +60,7 @@ class NWProjectData:
return self._title return self._title
@property @property
def autors(self): def authors(self):
return self._authors return self._authors
@property @property
@@ -75,6 +75,44 @@ class NWProjectData:
def editTime(self): def editTime(self):
return self._editTime return self._editTime
##
# Methods
##
def addAuthor(self, value):
self._authors.append(simplified(str(value)))
self._changed = True
return
def incSaveCount(self):
self._saveCount += 1
self._changed = True
return
def incAutoCount(self):
self._autoCount += 1
self._changed = True
return
##
# Getters
##
def getAuthors(self, trAnd="and"):
"""Return a formatted string of authors.
"""
nAuth = len(self._authors)
authors = ""
if nAuth == 1:
authors = self._authors[0]
elif nAuth > 1:
authors = "%s %s %s" % (
", ".join(self._authors[0:-1]), trAnd, self._authors[-1]
)
return authors
## ##
# Setters # Setters
## ##
@@ -89,9 +127,17 @@ class NWProjectData:
self._changed = True self._changed = True
return return
def addAuthor(self, value): def setAuthors(self, value):
self._authors.append(simplified(str(value))) self._authors = []
self._changed = True self._changed = True
if isinstance(value, str):
for author in value.splitlines():
author = simplified(author)
if author:
self.addAuthor(author)
self._changed = True
elif isinstance(value, list):
self._authors = value
return return
def setSaveCount(self, value): def setSaveCount(self, value):
+2 -2
View File
@@ -261,8 +261,8 @@ class ToOdt(Tokenizer):
# =============== # ===============
if self._headerText == "": if self._headerText == "":
theTitle = self.theProject.bookTitle theTitle = self.theProject.data.title
theAuth = self.theProject.getAuthors() theAuth = self.theProject.data.getAuthors(self.tr("and"))
self._headerText = f"{theTitle} / {theAuth} /" self._headerText = f"{theTitle} / {theAuth} /"
# Create Roots # Create Roots
+5 -3
View File
@@ -157,7 +157,7 @@ class GuiProjectDetailsMain(QWidget):
# Header # Header
# ====== # ======
self.bookTitle = QLabel(self.theProject.bookTitle) self.bookTitle = QLabel(self.theProject.data.title)
bookFont = self.bookTitle.font() bookFont = self.bookTitle.font()
bookFont.setPointSizeF(2.2*fPt) bookFont.setPointSizeF(2.2*fPt)
bookFont.setWeight(QFont.Bold) bookFont.setWeight(QFont.Bold)
@@ -175,7 +175,9 @@ class GuiProjectDetailsMain(QWidget):
self.projName.setAlignment(Qt.AlignHCenter) self.projName.setAlignment(Qt.AlignHCenter)
self.projName.setWordWrap(True) self.projName.setWordWrap(True)
self.bookAuthors = QLabel(self.tr("By {0}").format(self.theProject.getAuthors())) self.bookAuthors = QLabel(self.tr("By {0}").format(
self.theProject.data.getAuthors(self.tr("and"))
))
authFont = self.bookAuthors.font() authFont = self.bookAuthors.font()
authFont.setPointSizeF(1.2*fPt) authFont.setPointSizeF(1.2*fPt)
self.bookAuthors.setFont(authFont) self.bookAuthors.setFont(authFont)
@@ -255,7 +257,7 @@ class GuiProjectDetailsMain(QWidget):
self.wordCountVal.setText(f"{nwCount:n}") self.wordCountVal.setText(f"{nwCount:n}")
self.chapCountVal.setText(f"{hCounts[2]:n}") self.chapCountVal.setText(f"{hCounts[2]:n}")
self.sceneCountVal.setText(f"{hCounts[3]:n}") self.sceneCountVal.setText(f"{hCounts[3]:n}")
self.revCountVal.setText(f"{self.theProject.saveCount:n}") self.revCountVal.setText(f"{self.theProject.data.saveCount:n}")
self.editTimeVal.setText(f"{edTime//3600:02d}:{edTime%3600//60:02d}") self.editTimeVal.setText(f"{edTime//3600:02d}:{edTime%3600//60:02d}")
self.projPathVal.setText(self.theProject.projPath) self.projPathVal.setText(self.theProject.projPath)
+4 -4
View File
@@ -115,8 +115,8 @@ class GuiProjectSettings(PagedDialog):
doBackup = not self.tabMain.doBackup.isChecked() doBackup = not self.tabMain.doBackup.isChecked()
self.theProject.data.setName(projName) self.theProject.data.setName(projName)
self.theProject.setBookTitle(bookTitle) self.theProject.data.setTitle(bookTitle)
self.theProject.setBookAuthors(bookAuthors) self.theProject.data.setAuthors(bookAuthors)
self.theProject.setProjBackup(doBackup) self.theProject.setProjBackup(doBackup)
# Remember this as updating spell dictionary can be expensive # Remember this as updating spell dictionary can be expensive
@@ -219,7 +219,7 @@ class GuiProjectEditMain(QWidget):
self.editTitle = QLineEdit() self.editTitle = QLineEdit()
self.editTitle.setMaxLength(200) self.editTitle.setMaxLength(200)
self.editTitle.setMaximumWidth(xW) self.editTitle.setMaximumWidth(xW)
self.editTitle.setText(self.theProject.bookTitle) self.editTitle.setText(self.theProject.data.title)
self.mainForm.addRow( self.mainForm.addRow(
self.tr("Novel title"), self.tr("Novel title"),
self.editTitle, self.editTitle,
@@ -229,7 +229,7 @@ class GuiProjectEditMain(QWidget):
self.editAuthors = QPlainTextEdit() self.editAuthors = QPlainTextEdit()
self.editAuthors.setMaximumHeight(xH) self.editAuthors.setMaximumHeight(xH)
self.editAuthors.setMaximumWidth(xW) self.editAuthors.setMaximumWidth(xW)
self.editAuthors.setPlainText("\n".join(self.theProject.bookAuthors)) self.editAuthors.setPlainText("\n".join(self.theProject.data.authors))
self.mainForm.addRow( self.mainForm.addRow(
self.tr("Author(s)"), self.tr("Author(s)"),
self.editAuthors, self.editAuthors,
+2 -2
View File
@@ -973,8 +973,8 @@ class GuiBuildNovel(QDialog):
jsonData = { jsonData = {
"meta": { "meta": {
"workingTitle": self.theProject.data.name, "workingTitle": self.theProject.data.name,
"novelTitle": self.theProject.bookTitle, "novelTitle": self.theProject.data.title,
"authors": self.theProject.bookAuthors, "authors": self.theProject.data.authors,
"buildTime": self.buildTime, "buildTime": self.buildTime,
} }
} }
+23 -22
View File
@@ -555,22 +555,22 @@ def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir):
assert os.path.isfile(backFile) is False assert os.path.isfile(backFile) is False
# Successful save # Successful save
saveCount = theProject.saveCount saveCount = theProject.data.saveCount
autoCount = theProject.autoCount autoCount = theProject.data.autoCount
assert theProject.saveProject() is True assert theProject.saveProject() is True
assert theProject.saveCount == saveCount + 1 assert theProject.data.saveCount == saveCount + 1
assert theProject.autoCount == autoCount assert theProject.data.autoCount == autoCount
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
# Check that a second save creates a .bak file # Check that a second save creates a .bak file
assert os.path.isfile(backFile) is True assert os.path.isfile(backFile) is True
# Successful autosave # Successful autosave
saveCount = theProject.saveCount saveCount = theProject.data.saveCount
autoCount = theProject.autoCount autoCount = theProject.data.autoCount
assert theProject.saveProject(autoSave=True) is True assert theProject.saveProject(autoSave=True) is True
assert theProject.saveCount == saveCount assert theProject.data.saveCount == saveCount
assert theProject.autoCount == autoCount + 1 assert theProject.data.autoCount == autoCount + 1
assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE)
# Close test project # Close test project
@@ -902,30 +902,31 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd):
assert theProject.data.name == "A Name" assert theProject.data.name == "A Name"
# Project Title # Project Title
theProject.setBookTitle(" A Title ") theProject.data.setTitle(" A Title ")
assert theProject.bookTitle == "A Title" assert theProject.data.title == "A Title"
# Project Authors # Project Authors
# Check that the list is cleaned up and that it can be extracted as # Check that the list is cleaned up and that it can be extracted as
# a properly formatted string, depending on number of names # a properly formatted string, depending on number of names
assert not theProject.setBookAuthors([]) theProject.data.setAuthors([])
assert theProject.setBookAuthors(" Jane Doe \n John Doh \n ") assert theProject.data.authors == []
assert theProject.bookAuthors == ["Jane Doe", "John Doh"] theProject.data.setAuthors(" Jane Doe \n John Doh \n ")
assert theProject.data.authors == ["Jane Doe", "John Doh"]
assert theProject.setBookAuthors("") theProject.data.setAuthors("")
assert theProject.getAuthors() == "" assert theProject.data.getAuthors() == ""
assert theProject.setBookAuthors("Jane Doe") theProject.data.setAuthors("Jane Doe")
assert theProject.getAuthors() == "Jane Doe" assert theProject.data.getAuthors() == "Jane Doe"
assert theProject.setBookAuthors("Jane Doe\nJohn Doh") theProject.data.setAuthors("Jane Doe\nJohn Doh")
assert theProject.getAuthors() == "Jane Doe and John Doh" assert theProject.data.getAuthors() == "Jane Doe and John Doh"
assert theProject.setBookAuthors("Jane Doe\nJohn Doh\nBod Owens") theProject.data.setAuthors("Jane Doe\nJohn Doh\nBod Owens")
assert theProject.getAuthors() == "Jane Doe, John Doh and Bod Owens" assert theProject.data.getAuthors() == "Jane Doe, John Doh and Bod Owens"
# Edit Time # Edit Time
theProject.editTime = 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)
+1 -1
View File
@@ -55,7 +55,7 @@ def testDlgProjDetails_Dialog(qtbot, nwGUI, nwLipsum):
assert projDet.tabMain.wordCountVal.text() == f"{3000:n}" assert projDet.tabMain.wordCountVal.text() == f"{3000:n}"
assert projDet.tabMain.chapCountVal.text() == f"{3:n}" assert projDet.tabMain.chapCountVal.text() == f"{3:n}"
assert projDet.tabMain.sceneCountVal.text() == f"{5:n}" assert projDet.tabMain.sceneCountVal.text() == f"{5:n}"
assert projDet.tabMain.revCountVal.text() == f"{nwGUI.theProject.saveCount:n}" assert projDet.tabMain.revCountVal.text() == f"{nwGUI.theProject.data.saveCount:n}"
assert projDet.tabMain.projPathVal.text() == nwLipsum assert projDet.tabMain.projPathVal.text() == nwLipsum
+3 -3
View File
@@ -96,7 +96,7 @@ 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.setSpellLang("en")
theProject.setBookAuthors("Jane Smith\nJohn Smith") theProject.data.setAuthors("Jane Smith\nJohn Smith")
theProject.setAutoReplace({"A": "B", "C": "D"}) theProject.setAutoReplace({"A": "B", "C": "D"})
# Create Dialog # Create Dialog
@@ -137,8 +137,8 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd
projSettings._doSave() projSettings._doSave()
assert theProject.data.name == "Project Name" assert theProject.data.name == "Project Name"
assert theProject.bookTitle == "Project Title" assert theProject.data.title == "Project Title"
assert theProject.bookAuthors == ["Jane Doe", "John Doh"] assert theProject.data.authors == ["Jane Doe", "John Doh"]
# Clean up # Clean up
projSettings._doClose() projSettings._doClose()
+5 -5
View File
@@ -172,9 +172,9 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.theProject.tree.trashRoot() is None assert nwGUI.theProject.tree.trashRoot() is None
assert nwGUI.theProject.projPath is None assert nwGUI.theProject.projPath is None
assert nwGUI.theProject.projMeta is None assert nwGUI.theProject.projMeta is None
assert nwGUI.theProject.data.name == "New Project" assert nwGUI.theProject.data.name == ""
assert nwGUI.theProject.bookTitle == "" assert nwGUI.theProject.data.title == ""
assert len(nwGUI.theProject.bookAuthors) == 0 assert nwGUI.theProject.data.authors == []
assert not nwGUI.theProject.spellCheck assert not nwGUI.theProject.spellCheck
# Check the files # Check the files
@@ -195,8 +195,8 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock
assert nwGUI.theProject.projPath == fncProj assert nwGUI.theProject.projPath == fncProj
assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta") assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta")
assert nwGUI.theProject.data.name == "New Project" assert nwGUI.theProject.data.name == "New Project"
assert nwGUI.theProject.bookTitle == "New Novel" assert nwGUI.theProject.data.title == "New Novel"
assert len(nwGUI.theProject.bookAuthors) == 1 assert nwGUI.theProject.data.authors == ["Jane Doe"]
assert nwGUI.theProject.spellCheck is False assert nwGUI.theProject.spellCheck is False
# Check that tree items have been created # Check that tree items have been created
+2 -2
View File
@@ -168,8 +168,8 @@ def buildTestProject(theObject, projPath):
theProject.clearProject() theProject.clearProject()
theProject.setProjectPath(projPath, newProject=True) theProject.setProjectPath(projPath, newProject=True)
theProject.data.setName("New Project") theProject.data.setName("New Project")
theProject.setBookTitle("New Novel") theProject.data.setTitle("New Novel")
theProject.setBookAuthors("Jane Doe") theProject.data.setAuthors("Jane Doe")
# Creating a minimal project with a few root folders and a # Creating a minimal project with a few root folders and a
# single chapter folder with a single file. # single chapter folder with a single file.