Merge pull request #261 from vkbo/project_updates

Project Class Updates
This commit is contained in:
Veronica K. Berglyd Olsen
2020-05-30 00:23:13 +02:00
committed by GitHub
20 changed files with 384 additions and 209 deletions
+4 -6
View File
@@ -14,12 +14,10 @@ docs/source/_*
__pycache__ __pycache__
# Sample Project # Sample Project
sample/**/cache sample/cache
sample/**/wordlist.txt sample/meta
sample/**/sessionInfo.log sample/*.bak
sample/**/*.bak sample/*.lock
sample/**/*.json
sample/**/*.lock
# PyTest # PyTest
tests/temp tests/temp
+2
View File
@@ -39,6 +39,8 @@ class nwFiles():
PROJ_FILE = "nwProject.nwx" PROJ_FILE = "nwProject.nwx"
PROJ_DICT = "wordlist.txt" PROJ_DICT = "wordlist.txt"
PROJ_LOCK = "nwProject.lock" PROJ_LOCK = "nwProject.lock"
TOC_TXT = "ToC.txt"
TOC_JSON = "ToC.json"
SESS_INFO = "sessionInfo.log" SESS_INFO = "sessionInfo.log"
INDEX_FILE = "tagsIndex.json" INDEX_FILE = "tagsIndex.json"
OPTS_FILE = "guiOptions.json" OPTS_FILE = "guiOptions.json"
-2
View File
@@ -9,7 +9,6 @@ from nw.core.spellcheck import NWSpellSimple
from nw.core.tokenizer import Tokenizer from nw.core.tokenizer import Tokenizer
from nw.core.tohtml import ToHtml from nw.core.tohtml import ToHtml
from nw.core.tools import countWords from nw.core.tools import countWords
from nw.core.tools import projectMaintenance
from nw.core.tools import numberToWord from nw.core.tools import numberToWord
__all__ = [ __all__ = [
@@ -22,6 +21,5 @@ __all__ = [
"Tokenizer", "Tokenizer",
"ToHtml", "ToHtml",
"countWords", "countWords",
"projectMaintenance",
"numberToWord", "numberToWord",
] ]
+19 -22
View File
@@ -91,18 +91,17 @@ class NWDoc():
if self.theItem.parHandle == self.theProject.projTree.trashRoot(): if self.theItem.parHandle == self.theProject.projTree.trashRoot():
self.docEditable = False self.docEditable = False
docDir = "content"
docFile = self.docHandle+".nwd" docFile = self.docHandle+".nwd"
self.fileLoc = path.join(docDir, docFile) logger.debug("Opening document %s" % docFile)
logger.debug("Opening document %s" % self.fileLoc)
dataDir = path.join(self.theProject.projPath, docDir) docPath = path.join(self.theProject.projContent, docFile)
docPath = path.join(dataDir, docFile) self.fileLoc = docPath
theText = "" theText = ""
self.docMeta = "" self.docMeta = ""
if path.isfile(docPath): if path.isfile(docPath):
try: try:
with open(docPath,mode="r",encoding="utf8") as inFile: with open(docPath, mode="r", encoding="utf8") as inFile:
fstLine = inFile.readline() fstLine = inFile.readline()
if fstLine.startswith("%%~ "): if fstLine.startswith("%%~ "):
# This is the meta line # This is the meta line
@@ -112,7 +111,7 @@ class NWDoc():
theText += inFile.read() theText += inFile.read()
except Exception as e: except Exception as e:
self.makeAlert(["Failed to open document file.",str(e)], nwAlert.ERROR) self.makeAlert(["Failed to open document file.", str(e)], nwAlert.ERROR)
# Note: Document must be cleared in case of an io error, # Note: Document must be cleared in case of an io error,
# or else the auto-save or save will try to overwrite it # or else the auto-save or save will try to overwrite it
# with an empty file. Return None to alert the caller. # with an empty file. Return None to alert the caller.
@@ -138,25 +137,23 @@ class NWDoc():
if self.docHandle is None or not self.docEditable: if self.docHandle is None or not self.docEditable:
return False return False
docDir = "content" self.theProject.ensureFolderStructure()
docFile = self.docHandle+".nwd" docFile = self.docHandle+".nwd"
logger.debug("Saving document %s" % path.join(docDir, docFile)) logger.debug("Saving document %s" % docFile)
dataPath = path.join(self.theProject.projPath, docDir)
docPath = path.join(dataPath, docFile) docPath = path.join(self.theProject.projContent, docFile)
if not path.isdir(dataPath): docTemp = path.join(self.theProject.projContent, docFile+"~")
mkdir(dataPath)
logger.debug("Created folder %s" % dataPath)
itemPath = self.theProject.projTree.getItemPath(self.docHandle) itemPath = self.theProject.projTree.getItemPath(self.docHandle)
docMeta = "%%~ "+":".join(itemPath)+":"+self.theItem.itemName+"\n" docMeta = "%%~ "+":".join(itemPath)+":"+self.theItem.itemName+"\n"
docTemp = path.join(dataPath, docFile+"~")
try: try:
with open(docTemp,mode="w",encoding="utf8") as outFile: with open(docTemp, mode="w", encoding="utf8") as outFile:
outFile.write(docMeta) outFile.write(docMeta)
outFile.write(docText) outFile.write(docText)
except Exception as e: except Exception as e:
self.makeAlert(["Could not save document.",str(e)], nwAlert.ERROR) self.makeAlert(["Could not save document.", str(e)], nwAlert.ERROR)
return False return False
# If we're here, the file was successfully saved, so we can # If we're here, the file was successfully saved, so we can
@@ -173,13 +170,12 @@ class NWDoc():
"""Permanently delete a document source file and its backups """Permanently delete a document source file and its backups
from the project data folder. from the project data folder.
""" """
docDir = "content"
docFile = self.docHandle+".nwd" docFile = self.docHandle+".nwd"
dataPath = path.join(self.theProject.projPath, docDir)
chkList = [] chkList = []
chkList.append(path.join(dataPath, docFile)) chkList.append(path.join(self.theProject.projContent, docFile))
chkList.append(path.join(dataPath, docFile+"~")) chkList.append(path.join(self.theProject.projContent, docFile+"~"))
chkList.append(path.join(dataPath, docFile[:-3]+"bak"))
for chkFile in chkList: for chkFile in chkList:
if path.isfile(chkFile): if path.isfile(chkFile):
try: try:
@@ -188,6 +184,7 @@ class NWDoc():
except Exception as e: except Exception as e:
self.makeAlert(["Could not delete document file.",str(e)], nwAlert.ERROR) self.makeAlert(["Could not delete document file.",str(e)], nwAlert.ERROR)
return False return False
return True return True
## ##
+220 -71
View File
@@ -31,6 +31,7 @@
""" """
import logging import logging
import json
import nw import nw
from os import path, mkdir, listdir, unlink, rename, rmdir from os import path, mkdir, listdir, unlink, rename, rmdir
@@ -42,7 +43,6 @@ from shutil import make_archive
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import QMessageBox
from nw.gui.tools import OptionState from nw.gui.tools import OptionState
from nw.core.tools import projectMaintenance
from nw.core.document import NWDoc from nw.core.document import NWDoc
from nw.common import checkString, checkBool, checkInt, formatTimeStamp from nw.common import checkString, checkBool, checkInt, formatTimeStamp
from nw.constants import ( from nw.constants import (
@@ -70,13 +70,15 @@ class NWProject():
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.saveCount = 0 # Meta data: number of saves
self.autoCount = 0 # Meta data: number of automatic 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
self.projMeta = None # The full path to the project's meta data folder self.projMeta = None # The full path to the project's meta data folder
self.projData = None # The full path to the project's data folder self.projCache = None # The full path to the project's cache folder
self.projDict = None # The spell check dictionary self.projContent = None # The full path to the project's content folder
self.projFile = None # The file name of the project main XML file self.projDict = None # The spell check dictionary
self.projFile = None # The file name of the project main XML file
# Project Meta # Project Meta
self.projName = "" # Project name (working title) self.projName = "" # Project name (working title)
@@ -196,7 +198,8 @@ class NWProject():
# Project Settings # Project Settings
self.projPath = None self.projPath = None
self.projMeta = None self.projMeta = None
self.projData = None self.projCache = None
self.projContent = None
self.projDict = None self.projDict = None
self.projFile = nwFiles.PROJ_FILE self.projFile = nwFiles.PROJ_FILE
self.projName = "" self.projName = ""
@@ -205,7 +208,7 @@ class NWProject():
self.autoReplace = {} self.autoReplace = {}
self.titleFormat = { self.titleFormat = {
"title" : r"%title%", "title" : r"%title%",
"chapter" : r"Chapter %num%\\%title%", "chapter" : r"Chapter %ch%: %title%",
"unnumbered" : r"%title%", "unnumbered" : r"%title%",
"scene" : r"* * *", "scene" : r"* * *",
"section" : r"", "section" : r"",
@@ -248,14 +251,30 @@ class NWProject():
self.projPath = path.abspath(path.dirname(fileName)) self.projPath = path.abspath(path.dirname(fileName))
logger.debug("Opening project: %s" % self.projPath) logger.debug("Opening project: %s" % self.projPath)
self.projMeta = path.join(self.projPath,"meta") # Standard Folders and Files
self.projData = path.join(self.projPath,"content") # ==========================
if not self.ensureFolderStructure():
return False
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT) self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
if not self._checkFolder(self.projMeta): # Check for Old Legacy Data
return False # =========================
if not self._checkFolder(self.projData):
return False errList = []
for projItem in listdir(self.projPath):
logger.verbose("Project contains: %s" % projItem)
if projItem.startswith("data_"):
self._legacyDataFolder(projItem)
if errList:
self.makeAlert(errList, nwAlert.ERROR)
self._deprecatedFiles()
# Project Lock
# ============
if overrideLock: if overrideLock:
self._clearLockFile() self._clearLockFile()
@@ -272,10 +291,8 @@ class NWProject():
else: else:
logger.verbose("Project is not locked") logger.verbose("Project is not locked")
try: # Open The Project XML File
projectMaintenance(self) # =========================
except Exception as E:
logger.error(str(E))
try: try:
nwXML = etree.parse(fileName) nwXML = etree.parse(fileName)
@@ -315,12 +332,15 @@ class NWProject():
self.saveCount = checkInt(xRoot.attrib["saveCount"], 0, False) self.saveCount = checkInt(xRoot.attrib["saveCount"], 0, False)
if "autoCount" in xRoot.attrib: if "autoCount" in xRoot.attrib:
self.autoCount = checkInt(xRoot.attrib["autoCount"], 0, False) self.autoCount = checkInt(xRoot.attrib["autoCount"], 0, False)
if "editTime" in xRoot.attrib:
self.editTime = checkInt(xRoot.attrib["editTime"], 0, False)
logger.verbose("XML root is %s" % nwxRoot) logger.verbose("XML root is %s" % nwxRoot)
logger.verbose("File version is %s" % fileVersion) logger.verbose("File version is %s" % fileVersion)
# Check File Type # Check File Type
# =============== # ===============
if not nwxRoot == "novelWriterXML": if not nwxRoot == "novelWriterXML":
self.makeAlert( self.makeAlert(
"Project file does not appear to be a novelWriterXML file.", "Project file does not appear to be a novelWriterXML file.",
@@ -330,14 +350,17 @@ class NWProject():
# Check Project Storage Version # Check Project Storage Version
# ============================= # =============================
if fileVersion == "1.0": if fileVersion == "1.0":
msgBox = QMessageBox() msgBox = QMessageBox()
msgRes = msgBox.question(self.theParent, "Old Project Version", ( msgRes = msgBox.question(self.theParent, "Old Project Version", (
"The project file and data is created by a %s version lower than 0.7. " "The project file and data is created by a %s version lower than 0.7. "
"Do you want to upgrade the project to the most recent format?<br><br>" "Do you want to upgrade the project to the most recent format?<br><br>"
"Note that after the upgrade, you cannot open the project with an older " "Note that after the upgrade, you cannot open the project with an older "
"version of novelWriter any more, so make sure you have a recent backup." "version of %s any more, so make sure you have a recent backup."
) % nw.__package__) ) % (
nw.__package__, nw.__package__
))
if msgRes == QMessageBox.Yes: if msgRes == QMessageBox.Yes:
self._updateStorage() self._updateStorage()
else: else:
@@ -353,6 +376,7 @@ class NWProject():
# Check novelWriter Version # Check novelWriter Version
# ========================= # =========================
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI: if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI:
msgBox = QMessageBox() msgBox = QMessageBox()
msgRes = msgBox.question(self.theParent, "Version Conflict", ( msgRes = msgBox.question(self.theParent, "Version Conflict", (
@@ -367,6 +391,7 @@ class NWProject():
# Start Parsing XML # Start Parsing XML
# ================= # =================
for xChild in xRoot: for xChild in xRoot:
if xChild.tag == "project": if xChild.tag == "project":
logger.debug("Found project meta") logger.debug("Found project meta")
@@ -384,6 +409,7 @@ class NWProject():
self.bookAuthors.append(xItem.text) self.bookAuthors.append(xItem.text)
elif xItem.tag == "backup": elif xItem.tag == "backup":
self.doBackup = checkBool(xItem.text, False) self.doBackup = checkBool(xItem.text, False)
elif xChild.tag == "settings": elif xChild.tag == "settings":
logger.debug("Found project settings") logger.debug("Found project settings")
for xItem in xChild: for xItem in xChild:
@@ -411,6 +437,7 @@ class NWProject():
for xEntry in xItem: for xEntry in xItem:
titleFormat[xEntry.tag] = checkString(xEntry.text, "", False) titleFormat[xEntry.tag] = checkString(xEntry.text, "", False)
self.setTitleFormat(titleFormat) self.setTitleFormat(titleFormat)
elif xChild.tag == "content": elif xChild.tag == "content":
logger.debug("Found project content") logger.debug("Found project content")
self.projTree.unpackXML(xChild) self.projTree.unpackXML(xChild)
@@ -443,15 +470,8 @@ class NWProject():
) )
return False return False
self.projMeta = path.join(self.projPath, "meta")
self.projData = path.join(self.projPath, "content")
saveTime = time() saveTime = time()
if not self.ensureFolderStructure():
if not self._checkFolder(self.projPath):
return False
if not self._checkFolder(self.projMeta):
return False
if not self._checkFolder(self.projData):
return False return False
logger.debug("Saving project: %s" % self.projPath) logger.debug("Saving project: %s" % self.projPath)
@@ -470,6 +490,7 @@ class NWProject():
"saveCount" : str(self.saveCount), "saveCount" : str(self.saveCount),
"autoCount" : str(self.autoCount), "autoCount" : str(self.autoCount),
"timeStamp" : formatTimeStamp(saveTime), "timeStamp" : formatTimeStamp(saveTime),
"editTime" : str(int(self.editTime + saveTime - self.projOpened)),
}) })
# Save Project Meta # Save Project Meta
@@ -519,7 +540,7 @@ class NWProject():
xml_declaration = True xml_declaration = True
)) ))
except Exception as e: except Exception as e:
self.makeAlert(["Failed to save project.",str(e)], nwAlert.ERROR) self.makeAlert(["Failed to save project.", str(e)], nwAlert.ERROR)
return False return False
# If we're here, the file was successfully saved, # If we're here, the file was successfully saved,
@@ -546,12 +567,33 @@ class NWProject():
def closeProject(self): def closeProject(self):
"""Close the current project and clear all meta data. """Close the current project and clear all meta data.
""" """
self.projTree.writeToCFiles()
self._appendSessionStats() self._appendSessionStats()
self._clearLockFile() self._clearLockFile()
self.clearProject() self.clearProject()
self.lockedBy = None self.lockedBy = None
return True return True
def ensureFolderStructure(self):
"""Ensure that all necessary folders exist in the project
folder.
"""
if self.projPath is None or self.projPath == "":
return False
self.projMeta = path.join(self.projPath, "meta")
self.projCache = path.join(self.projPath, "cache")
self.projContent = path.join(self.projPath, "content")
if not self._checkFolder(self.projMeta):
return False
if not self._checkFolder(self.projCache):
return False
if not self._checkFolder(self.projContent):
return False
return True
## ##
# Backup Project # Backup Project
## ##
@@ -978,7 +1020,7 @@ class NWProject():
# Then check the files in the data folder # Then check the files in the data folder
orphanFiles = [] orphanFiles = []
for fileItem in listdir(self.projData): for fileItem in listdir(self.projContent):
if not fileItem.endswith(".nwd"): if not fileItem.endswith(".nwd"):
logger.warning("Skipping file %s" % fileItem) logger.warning("Skipping file %s" % fileItem)
continue continue
@@ -1028,7 +1070,7 @@ class NWProject():
def _appendSessionStats(self): def _appendSessionStats(self):
"""Append session statistics to the sessions log file. """Append session statistics to the sessions log file.
""" """
if self.projMeta is None: if not self.ensureFolderStructure():
return False return False
sessionFile = path.join(self.projMeta, nwFiles.SESS_INFO) sessionFile = path.join(self.projMeta, nwFiles.SESS_INFO)
@@ -1046,52 +1088,113 @@ class NWProject():
return True return True
def _updateStorage(self): ##
"""Updates the project storage folder from 1.0 to 1.1. # Legacy Data Structure Handlers
##
def _legacyDataFolder(self, theFolder):
"""Clean up legacy data folders.
""" """
contDir = path.join(self.projPath, "content")
self._checkFolder(contDir)
errList = [] errList = []
theData = path.join(self.projPath, theFolder)
if not path.isdir(theData):
errList.append("Not a folder: %s" % theData)
return errList
for projItem in listdir(self.projPath): logger.info("Old data folder %s found" % theFolder)
itemPath = path.join(self.projPath, projItem)
if not path.isdir(itemPath) or not projItem.startswith("data_"): # Move Documents to Content
# =========================
for dataItem in listdir(theData):
theFile = path.join(theData, dataItem)
if not path.isfile(theFile):
theErr = self._moveUnknownItem(theData, dataItem)
if theErr:
errList.append(theErr)
continue continue
for dataFile in listdir(itemPath):
dataPath = path.join(itemPath, dataFile)
if dataFile.endswith(".bak"):
try:
unlink(dataPath)
logger.info("Deleted file: %s" % dataPath)
except:
errList.append("Failed to delete: %s" % dataPath)
elif dataFile.endswith(".nwd") and len(dataFile) == 21: if len(dataItem) == 21 and dataItem.endswith("_main.nwd"):
tHandle = projItem[-1]+dataFile[:12] tHandle = theFolder[-1]+dataItem[:12]
newPath = path.join(contDir, tHandle+".nwd") newPath = path.join(self.projContent, tHandle+".nwd")
try: try:
rename(dataPath, newPath) rename(theFile, newPath)
logger.info("Moved file: %s" % dataPath) logger.info("Moved file: %s" % theFile)
logger.info("New location: %s" % newPath) logger.info("New location: %s" % newPath)
except: except Exception as e:
errList.append("Failed to move: %s" % dataPath) logger.error(str(e))
errList.append("Could not move: %s" % theFile)
else: elif len(dataItem) == 21 and dataItem.endswith("_main.bak"):
newPath = path.join(self.projPath, "unknown_"+dataFile) try:
try: unlink(theFile)
rename(dataPath, newPath) logger.info("Deleted file: %s" % theFile)
logger.info("Moved file: %s" % dataPath) except Exception as e:
logger.info("New location: %s" % newPath) logger.error(str(e))
except: errList.append("Could not delete: %s" % theFile)
errList.append("Failed to move: %s" % dataPath)
try:
rmdir(itemPath)
logger.info("Removed folder: %s" % itemPath)
except:
errList.append("Failed to delete: %s" % itemPath)
if errList: else:
self.makeAlert(errList, nwAlert.ERROR) theErr = self._moveUnknownItem(theData, dataItem)
if theErr:
errList.append(theErr)
# Remove Data Folder
# ==================
try:
rmdir(theData)
logger.info("Removed folder: %s" % theFolder)
except:
errList.append("Failed to remove: %s" % theFolder)
return errList
def _moveUnknownItem(self, theDir, theItem):
"""Move an item that doesn't belong in the project folder to
a junk folder.
"""
theJunk = path.join(self.projPath, "junk")
if not self._checkFolder(theJunk):
return "Could not make folder: %s" % theJunk
theSrc = path.join(theDir, theItem)
theDst = path.join(theJunk, theItem)
try:
rename(theSrc, theDst)
logger.info("Moved to junk: %s" % theSrc)
except Exception as e:
logger.error(str(e))
return "Could not move item %s to junk." % theSrc
return ""
def _deprecatedFiles(self):
"""Delete files that are no longer used by novelWriter.
"""
rmList = []
rmList.append(path.join(self.projCache, "nwProject.nwx.0"))
rmList.append(path.join(self.projCache, "nwProject.nwx.1"))
rmList.append(path.join(self.projCache, "nwProject.nwx.2"))
rmList.append(path.join(self.projCache, "nwProject.nwx.3"))
rmList.append(path.join(self.projCache, "nwProject.nwx.4"))
rmList.append(path.join(self.projCache, "nwProject.nwx.5"))
rmList.append(path.join(self.projCache, "nwProject.nwx.6"))
rmList.append(path.join(self.projCache, "nwProject.nwx.7"))
rmList.append(path.join(self.projCache, "nwProject.nwx.8"))
rmList.append(path.join(self.projCache, "nwProject.nwx.9"))
rmList.append(path.join(self.projMeta, "mainOptions.json"))
rmList.append(path.join(self.projMeta, "exportOptions.json"))
rmList.append(path.join(self.projMeta, "outlineOptions.json"))
rmList.append(path.join(self.projMeta, "timelineOptions.json"))
rmList.append(path.join(self.projMeta, "docMergeOptions.json"))
rmList.append(path.join(self.projMeta, "sessionLogOptions.json"))
for rmFile in rmList:
if path.isfile(rmFile):
logger.info("Deleting: %s" % rmFile)
try:
unlink(rmFile)
except Exception as e:
logger.error(str(e))
return return
@@ -1199,6 +1302,51 @@ class NWTree():
return True return True
def writeToCFiles(self):
"""Write the convenience table of contents files in the root of
the project directory. These files are there to assist the user
if they wish to browse the stored files.
"""
tocText = path.join(self.theProject.projPath, nwFiles.TOC_TXT)
tocJson = path.join(self.theProject.projPath, nwFiles.TOC_JSON)
jsonData = []
try:
# Dump the text
with open(tocText, mode="w", encoding="utf8") as outFile:
outFile.write("\n")
outFile.write(" Table of Contents\n")
outFile.write("===================\n")
outFile.write("\n")
outFile.write(" %-25s %-9s %s\n" %("File Name","Class","Document Label"))
outFile.write("-"*80+"\n")
for tHandle in sorted(self._treeOrder):
tItem = self.__getitem__(tHandle)
if tItem is None:
continue
tFile = tHandle+".nwd"
if path.isfile(path.join(self.theProject.projContent, tFile)):
outFile.write(" %-25s %-9s %s\n" %(
path.join("content", tFile),
tItem.itemClass.name,
tItem.itemName,
))
jsonData.append([
path.join("content", tFile),
tItem.itemClass.name,
tItem.itemName,
])
outFile.write("\n")
# Dump the JSON
with open(tocJson, mode="w+", encoding="utf8") as outFile:
outFile.write(json.dumps(jsonData, indent=2))
except Exception as e:
logger.error(str(e))
return
## ##
# Tree Structure Methods # Tree Structure Methods
## ##
@@ -1481,7 +1629,6 @@ class NWItem():
xSub = self._subPack(xPack,"type", text=str(self.itemType.name)) xSub = self._subPack(xPack,"type", text=str(self.itemType.name))
xSub = self._subPack(xPack,"class", text=str(self.itemClass.name)) xSub = self._subPack(xPack,"class", text=str(self.itemClass.name))
xSub = self._subPack(xPack,"status", text=str(self.itemStatus)) xSub = self._subPack(xPack,"status", text=str(self.itemStatus))
xSub = self._subPack(xPack,"expanded", text=str(self.isExpanded))
if self.itemType == nwItemType.FILE: if self.itemType == nwItemType.FILE:
xSub = self._subPack(xPack,"exported", text=str(self.isExported)) xSub = self._subPack(xPack,"exported", text=str(self.isExported))
xSub = self._subPack(xPack,"layout", text=str(self.itemLayout.name)) xSub = self._subPack(xPack,"layout", text=str(self.itemLayout.name))
@@ -1489,6 +1636,8 @@ class NWItem():
xSub = self._subPack(xPack,"wordCount", text=str(self.wordCount), none=False) xSub = self._subPack(xPack,"wordCount", text=str(self.wordCount), none=False)
xSub = self._subPack(xPack,"paraCount", text=str(self.paraCount), none=False) xSub = self._subPack(xPack,"paraCount", text=str(self.paraCount), none=False)
xSub = self._subPack(xPack,"cursorPos", text=str(self.cursorPos), none=False) xSub = self._subPack(xPack,"cursorPos", text=str(self.cursorPos), none=False)
else:
xSub = self._subPack(xPack,"expanded", text=str(self.isExpanded))
return return
def unpackXML(self, xItem): def unpackXML(self, xItem):
-40
View File
@@ -8,7 +8,6 @@
File History: File History:
Created: 2019-04-22 [0.0.1] countWords Created: 2019-04-22 [0.0.1] countWords
Created: 2019-10-13 [0.2.3] numberToWord, _numberToWordEN Created: 2019-10-13 [0.2.3] numberToWord, _numberToWordEN
Created: 2020-02-13 [0.4.3] projectMaintenance
Merged: 2020-05-08 [0.4.5] All of the above into this file Merged: 2020-05-08 [0.4.5] All of the above into this file
This file is a part of novelWriter This file is a part of novelWriter
@@ -81,45 +80,6 @@ def countWords(theText):
return charCount, wordCount, paraCount return charCount, wordCount, paraCount
def projectMaintenance(theProject):
"""Wrapper class for handling various tasks related to managing old
projects with content from older versions of novelWriter.
"""
# Remove no longer used project cache folder
if path.isdir(theProject.projPath):
cacheDir = path.join(theProject.projPath, "cache")
if path.isdir(cacheDir):
logger.info("Deprecated cache folder content found")
rmList = []
for i in range(10):
rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
rmList.append(path.join(cacheDir, "projCount.txt"))
for rmFile in rmList:
if path.isfile(rmFile):
logger.info("Deleting: %s" % rmFile)
try:
unlink(rmFile)
except Exception as e:
logger.error(str(e))
# Remove no longer used meta files
rmList = []
rmList.append(path.join(theProject.projMeta, "mainOptions.json"))
rmList.append(path.join(theProject.projMeta, "exportOptions.json"))
rmList.append(path.join(theProject.projMeta, "outlineOptions.json"))
rmList.append(path.join(theProject.projMeta, "timelineOptions.json"))
rmList.append(path.join(theProject.projMeta, "docMergeOptions.json"))
rmList.append(path.join(theProject.projMeta, "sessionLogOptions.json"))
for rmFile in rmList:
if path.isfile(rmFile):
logger.info("Deleting: %s" % rmFile)
try:
unlink(rmFile)
except Exception as e:
logger.error(str(e))
return
def numberToWord(numVal, theLanguage): def numberToWord(numVal, theLanguage):
"""Wrapper for converting numbers to words for chapter headings. """Wrapper for converting numbers to words for chapter headings.
""" """
+82
View File
@@ -0,0 +1,82 @@
[
[
"content/14298de4d9524.nwd",
"CHARACTER",
"John Smith"
],
[
"content/53b69b83cdafc.nwd",
"NOVEL",
"Title Page"
],
[
"content/5eaea4e8cdee8.nwd",
"WORLD",
"Mars"
],
[
"content/636b6aa9b697b.nwd",
"NOVEL",
"Making a Scene"
],
[
"content/6a2d6d5f4f401.nwd",
"NOVEL",
"Chapter One"
],
[
"content/88706ddc78b1b.nwd",
"NOVEL",
"Chapter Two"
],
[
"content/96b68994dfa3d.nwd",
"NOVEL",
"A Note on Structure"
],
[
"content/974e400180a99.nwd",
"NOVEL",
"Page"
],
[
"content/ae7339df26ded.nwd",
"NOVEL",
"We Found John!"
],
[
"content/b3e74dbc1f584.nwd",
"WORLD",
"Earth"
],
[
"content/b8136a5a774a0.nwd",
"NOVEL",
"Delete Me!"
],
[
"content/ba8a28a246524.nwd",
"NOVEL",
"Interlude"
],
[
"content/bb2c23b3c42cc.nwd",
"CHARACTER",
"Jane Smith"
],
[
"content/bc0cbd2a407f3.nwd",
"NOVEL",
"Another Scene"
],
[
"content/edca4be2fcaf8.nwd",
"NOVEL",
"Part One"
],
[
"content/f1471bef9f2ae.nwd",
"WORLD",
"Space"
]
]
+23
View File
@@ -0,0 +1,23 @@
Table of Contents
===================
File Name Class Document Label
--------------------------------------------------------------------------------
content/14298de4d9524.nwd CHARACTER John Smith
content/53b69b83cdafc.nwd NOVEL Title Page
content/5eaea4e8cdee8.nwd WORLD Mars
content/636b6aa9b697b.nwd NOVEL Making a Scene
content/6a2d6d5f4f401.nwd NOVEL Chapter One
content/88706ddc78b1b.nwd NOVEL Chapter Two
content/96b68994dfa3d.nwd NOVEL A Note on Structure
content/974e400180a99.nwd NOVEL Page
content/ae7339df26ded.nwd NOVEL We Found John!
content/b3e74dbc1f584.nwd WORLD Earth
content/b8136a5a774a0.nwd NOVEL Delete Me!
content/ba8a28a246524.nwd NOVEL Interlude
content/bb2c23b3c42cc.nwd CHARACTER Jane Smith
content/bc0cbd2a407f3.nwd NOVEL Another Scene
content/edca4be2fcaf8.nwd NOVEL Part One
content/f1471bef9f2ae.nwd WORLD Space
+1 -1
View File
@@ -2,6 +2,6 @@
### We Found John! ### We Found John!
@pov: John @pov: John
@location: Mars, OuterSpace @location: Mars
Jane has been searching for a while, and she finally found John on Mars. He was indeed in space! What was he doing on Mars anyway? Well, it turns out, he was farming potatoes. Jane has been searching for a while, and she finally found John on Mars. He was indeed in space! What was he doing on Mars anyway? Well, it turns out, he was farming potatoes.
+1 -1
View File
@@ -1,4 +1,4 @@
%%~ b8136a5a774a0:7031beac91f75:Delete Me! %%~ b8136a5a774a0:98acd8c76c93a:Delete Me!
### Delete Me! ### Delete Me!
This scene is trash. This scene is trash.
+1 -1
View File
@@ -1,4 +1,4 @@
%%~ edca4be2fcaf8:7031beac91f75:Part One %%~ edca4be2fcaf8:7031beac91f75:Part 1
# Part One # Part One
The first part. The first part.
-6
View File
@@ -5,10 +5,4 @@
Space … its an awful lot of nothing, with bits in it here and there. Some of which, people like to call home. Space … its an awful lot of nothing, with bits in it here and there. Some of which, people like to call home.
## Outer Space
@tag: OuterSpace
Now even further into space!
You can have more than one tag in a file, as long as there is only one tag per heading.
+16 -32
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.2" hexVersion="0x000602f0" fileVersion="1.1" saveCount="189" autoCount="30" timeStamp="2020-05-28 20:19:28"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="202" autoCount="29" timeStamp="2020-05-30 00:19:45" editTime="35">
<project> <project>
<name>Sample Project</name> <name>Sample Project</name>
<title>Sample Project</title> <title>Sample Project</title>
@@ -11,8 +11,8 @@
<spellCheck>True</spellCheck> <spellCheck>True</spellCheck>
<autoOutline>True</autoOutline> <autoOutline>True</autoOutline>
<lastEdited>636b6aa9b697b</lastEdited> <lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>bc0cbd2a407f3</lastViewed> <lastViewed>b3e74dbc1f584</lastViewed>
<lastWordCount>941</lastWordCount> <lastWordCount>914</lastWordCount>
<autoReplace> <autoReplace>
<A>B</A> <A>B</A>
<B>E</B> <B>E</B>
@@ -57,7 +57,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>Started</status> <status>Started</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>TITLE</layout> <layout>TITLE</layout>
<charCount>72</charCount> <charCount>72</charCount>
@@ -70,7 +69,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>PAGE</layout> <layout>PAGE</layout>
<charCount>210</charCount> <charCount>210</charCount>
@@ -83,13 +81,12 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>PARTITION</layout> <layout>PARTITION</layout>
<charCount>23</charCount> <charCount>23</charCount>
<wordCount>5</wordCount> <wordCount>5</wordCount>
<paraCount>1</paraCount> <paraCount>1</paraCount>
<cursorPos>27</cursorPos> <cursorPos>0</cursorPos>
</item> </item>
<item handle="e7ded148d6e4a" order="3" parent="7031beac91f75"> <item handle="e7ded148d6e4a" order="3" parent="7031beac91f75">
<name>A Folder</name> <name>A Folder</name>
@@ -103,7 +100,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>Notes</status> <status>Notes</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>CHAPTER</layout> <layout>CHAPTER</layout>
<charCount>12</charCount> <charCount>12</charCount>
@@ -116,72 +112,66 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>1st Draft</status> <status>1st Draft</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>1199</charCount> <charCount>1199</charCount>
<wordCount>216</wordCount> <wordCount>216</wordCount>
<paraCount>7</paraCount> <paraCount>7</paraCount>
<cursorPos>1066</cursorPos> <cursorPos>1266</cursorPos>
</item> </item>
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a"> <item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
<name>Another Scene</name> <name>Another Scene</name>
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>1st Draft</status> <status>1st Draft</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>476</charCount> <charCount>476</charCount>
<wordCount>93</wordCount> <wordCount>93</wordCount>
<paraCount>3</paraCount> <paraCount>3</paraCount>
<cursorPos>428</cursorPos> <cursorPos>551</cursorPos>
</item> </item>
<item handle="ba8a28a246524" order="3" parent="e7ded148d6e4a"> <item handle="ba8a28a246524" order="3" parent="e7ded148d6e4a">
<name>Interlude</name> <name>Interlude</name>
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>Finished</status> <status>Finished</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>UNNUMBERED</layout> <layout>UNNUMBERED</layout>
<charCount>633</charCount> <charCount>633</charCount>
<wordCount>101</wordCount> <wordCount>101</wordCount>
<paraCount>3</paraCount> <paraCount>3</paraCount>
<cursorPos>752</cursorPos> <cursorPos>1238</cursorPos>
</item> </item>
<item handle="96b68994dfa3d" order="4" parent="e7ded148d6e4a"> <item handle="96b68994dfa3d" order="4" parent="e7ded148d6e4a">
<name>A Note on Structure</name> <name>A Note on Structure</name>
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>2nd Draft</status> <status>2nd Draft</status>
<expanded>False</expanded>
<exported>False</exported> <exported>False</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>1692</charCount> <charCount>1692</charCount>
<wordCount>313</wordCount> <wordCount>313</wordCount>
<paraCount>6</paraCount> <paraCount>6</paraCount>
<cursorPos>551</cursorPos> <cursorPos>1721</cursorPos>
</item> </item>
<item handle="88706ddc78b1b" order="5" parent="e7ded148d6e4a"> <item handle="88706ddc78b1b" order="5" parent="e7ded148d6e4a">
<name>Chapter Two</name> <name>Chapter Two</name>
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>1st Draft</status> <status>1st Draft</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>CHAPTER</layout> <layout>CHAPTER</layout>
<charCount>139</charCount> <charCount>139</charCount>
<wordCount>28</wordCount> <wordCount>28</wordCount>
<paraCount>1</paraCount> <paraCount>1</paraCount>
<cursorPos>242</cursorPos> <cursorPos>343</cursorPos>
</item> </item>
<item handle="ae7339df26ded" order="6" parent="e7ded148d6e4a"> <item handle="ae7339df26ded" order="6" parent="e7ded148d6e4a">
<name>We Found John!</name> <name>We Found John!</name>
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>1st Draft</status> <status>1st Draft</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>189</charCount> <charCount>189</charCount>
@@ -208,26 +198,24 @@
<type>FILE</type> <type>FILE</type>
<class>CHARACTER</class> <class>CHARACTER</class>
<status>Minor</status> <status>Minor</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>49</charCount> <charCount>49</charCount>
<wordCount>9</wordCount> <wordCount>9</wordCount>
<paraCount>1</paraCount> <paraCount>1</paraCount>
<cursorPos>65</cursorPos> <cursorPos>24</cursorPos>
</item> </item>
<item handle="bb2c23b3c42cc" order="1" parent="f7e2d9f330615"> <item handle="bb2c23b3c42cc" order="1" parent="f7e2d9f330615">
<name>Jane Smith</name> <name>Jane Smith</name>
<type>FILE</type> <type>FILE</type>
<class>CHARACTER</class> <class>CHARACTER</class>
<status>Major</status> <status>Major</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>55</charCount> <charCount>55</charCount>
<wordCount>9</wordCount> <wordCount>9</wordCount>
<paraCount>1</paraCount> <paraCount>1</paraCount>
<cursorPos>71</cursorPos> <cursorPos>25</cursorPos>
</item> </item>
<item handle="15c4492bd5107" order="2" parent="None"> <item handle="15c4492bd5107" order="2" parent="None">
<name>Locations</name> <name>Locations</name>
@@ -241,33 +229,30 @@
<type>FILE</type> <type>FILE</type>
<class>WORLD</class> <class>WORLD</class>
<status>Main</status> <status>Main</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>76</charCount> <charCount>76</charCount>
<wordCount>15</wordCount> <wordCount>15</wordCount>
<paraCount>1</paraCount> <paraCount>1</paraCount>
<cursorPos>93</cursorPos> <cursorPos>20</cursorPos>
</item> </item>
<item handle="f1471bef9f2ae" order="1" parent="15c4492bd5107"> <item handle="f1471bef9f2ae" order="1" parent="15c4492bd5107">
<name>Space</name> <name>Space</name>
<type>FILE</type> <type>FILE</type>
<class>WORLD</class> <class>WORLD</class>
<status>Minor</status> <status>Minor</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>241</charCount> <charCount>115</charCount>
<wordCount>51</wordCount> <wordCount>24</wordCount>
<paraCount>3</paraCount> <paraCount>1</paraCount>
<cursorPos>135</cursorPos> <cursorPos>133</cursorPos>
</item> </item>
<item handle="5eaea4e8cdee8" order="2" parent="15c4492bd5107"> <item handle="5eaea4e8cdee8" order="2" parent="15c4492bd5107">
<name>Mars</name> <name>Mars</name>
<type>FILE</type> <type>FILE</type>
<class>WORLD</class> <class>WORLD</class>
<status>Major</status> <status>Major</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>28</charCount> <charCount>28</charCount>
@@ -287,7 +272,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
+2 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.0" saveCount="2" autoCount="0" timeStamp="2020-05-27 18:25:48"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="2" autoCount="0" timeStamp="2020-05-29 23:05:28">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title></title> <title></title>
@@ -14,7 +14,7 @@
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -55,7 +55,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
+2 -6
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.0" saveCount="4" autoCount="0" timeStamp="2020-05-27 18:27:20"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="4" autoCount="0" timeStamp="2020-05-29 23:06:02">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title></title> <title></title>
@@ -14,7 +14,7 @@
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -55,7 +55,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>331</charCount> <charCount>331</charCount>
@@ -75,7 +74,6 @@
<type>FILE</type> <type>FILE</type>
<class>CHARACTER</class> <class>CHARACTER</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>34</charCount> <charCount>34</charCount>
@@ -95,7 +93,6 @@
<type>FILE</type> <type>FILE</type>
<class>PLOT</class> <class>PLOT</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>48</charCount> <charCount>48</charCount>
@@ -115,7 +112,6 @@
<type>FILE</type> <type>FILE</type>
<class>WORLD</class> <class>WORLD</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>51</charCount> <charCount>51</charCount>
+2 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.5" fileVersion="1.0" saveCount="2" autoCount="0" timeStamp="2020-05-10 23:19:00"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="2" autoCount="0" timeStamp="2020-05-29 23:07:05">
<project> <project>
<name>Project Name</name> <name>Project Name</name>
<title>Project Title</title> <title>Project Title</title>
@@ -18,7 +18,7 @@
</autoReplace> </autoReplace>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -59,7 +59,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
+2 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.0" saveCount="2" autoCount="0" timeStamp="2020-05-27 18:30:26"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="2" autoCount="0" timeStamp="2020-05-29 23:07:37">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title></title> <title></title>
@@ -14,7 +14,7 @@
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -55,7 +55,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>Note</status> <status>Note</status>
<expanded>False</expanded>
<exported>False</exported> <exported>False</exported>
<layout>PAGE</layout> <layout>PAGE</layout>
<charCount>0</charCount> <charCount>0</charCount>
+2 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.0" saveCount="1" autoCount="0" timeStamp="2020-05-27 18:23:46"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="1" autoCount="0" timeStamp="2020-05-29 23:03:58">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title></title> <title></title>
@@ -14,7 +14,7 @@
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -76,7 +76,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
+2 -3
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.0" saveCount="4" autoCount="0" timeStamp="2020-05-27 18:24:35"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="4" autoCount="0" timeStamp="2020-05-29 23:04:31">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title></title> <title></title>
@@ -14,7 +14,7 @@
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -76,7 +76,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
+2 -5
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="0.6.1" hexVersion="0x000601f0" fileVersion="1.0" saveCount="5" autoCount="0" timeStamp="2020-05-27 18:24:56"> <novelWriterXML appVersion="0.7.0rc1" hexVersion="0x000700c1" fileVersion="1.1" saveCount="5" autoCount="0" timeStamp="2020-05-29 23:04:50">
<project> <project>
<name>New Project</name> <name>New Project</name>
<title></title> <title></title>
@@ -14,7 +14,7 @@
<autoReplace/> <autoReplace/>
<titleFormat> <titleFormat>
<title>%title%</title> <title>%title%</title>
<chapter>Chapter %num%\\%title%</chapter> <chapter>Chapter %ch%: %title%</chapter>
<unnumbered>%title%</unnumbered> <unnumbered>%title%</unnumbered>
<scene>* * *</scene> <scene>* * *</scene>
<section></section> <section></section>
@@ -76,7 +76,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
@@ -117,7 +116,6 @@
<type>FILE</type> <type>FILE</type>
<class>NOVEL</class> <class>NOVEL</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>SCENE</layout> <layout>SCENE</layout>
<charCount>0</charCount> <charCount>0</charCount>
@@ -130,7 +128,6 @@
<type>FILE</type> <type>FILE</type>
<class>CHARACTER</class> <class>CHARACTER</class>
<status>New</status> <status>New</status>
<expanded>False</expanded>
<exported>True</exported> <exported>True</exported>
<layout>NOTE</layout> <layout>NOTE</layout>
<charCount>0</charCount> <charCount>0</charCount>