Merge pull request #261 from vkbo/project_updates
Project Class Updates
This commit is contained in:
+4
-6
@@ -14,12 +14,10 @@ docs/source/_*
|
||||
__pycache__
|
||||
|
||||
# Sample Project
|
||||
sample/**/cache
|
||||
sample/**/wordlist.txt
|
||||
sample/**/sessionInfo.log
|
||||
sample/**/*.bak
|
||||
sample/**/*.json
|
||||
sample/**/*.lock
|
||||
sample/cache
|
||||
sample/meta
|
||||
sample/*.bak
|
||||
sample/*.lock
|
||||
|
||||
# PyTest
|
||||
tests/temp
|
||||
|
||||
@@ -39,6 +39,8 @@ class nwFiles():
|
||||
PROJ_FILE = "nwProject.nwx"
|
||||
PROJ_DICT = "wordlist.txt"
|
||||
PROJ_LOCK = "nwProject.lock"
|
||||
TOC_TXT = "ToC.txt"
|
||||
TOC_JSON = "ToC.json"
|
||||
SESS_INFO = "sessionInfo.log"
|
||||
INDEX_FILE = "tagsIndex.json"
|
||||
OPTS_FILE = "guiOptions.json"
|
||||
|
||||
@@ -9,7 +9,6 @@ from nw.core.spellcheck import NWSpellSimple
|
||||
from nw.core.tokenizer import Tokenizer
|
||||
from nw.core.tohtml import ToHtml
|
||||
from nw.core.tools import countWords
|
||||
from nw.core.tools import projectMaintenance
|
||||
from nw.core.tools import numberToWord
|
||||
|
||||
__all__ = [
|
||||
@@ -22,6 +21,5 @@ __all__ = [
|
||||
"Tokenizer",
|
||||
"ToHtml",
|
||||
"countWords",
|
||||
"projectMaintenance",
|
||||
"numberToWord",
|
||||
]
|
||||
|
||||
+19
-22
@@ -91,18 +91,17 @@ class NWDoc():
|
||||
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
|
||||
self.docEditable = False
|
||||
|
||||
docDir = "content"
|
||||
docFile = self.docHandle+".nwd"
|
||||
self.fileLoc = path.join(docDir, docFile)
|
||||
logger.debug("Opening document %s" % self.fileLoc)
|
||||
dataDir = path.join(self.theProject.projPath, docDir)
|
||||
docPath = path.join(dataDir, docFile)
|
||||
logger.debug("Opening document %s" % docFile)
|
||||
|
||||
docPath = path.join(self.theProject.projContent, docFile)
|
||||
self.fileLoc = docPath
|
||||
|
||||
theText = ""
|
||||
self.docMeta = ""
|
||||
if path.isfile(docPath):
|
||||
try:
|
||||
with open(docPath,mode="r",encoding="utf8") as inFile:
|
||||
with open(docPath, mode="r", encoding="utf8") as inFile:
|
||||
fstLine = inFile.readline()
|
||||
if fstLine.startswith("%%~ "):
|
||||
# This is the meta line
|
||||
@@ -112,7 +111,7 @@ class NWDoc():
|
||||
theText += inFile.read()
|
||||
|
||||
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,
|
||||
# or else the auto-save or save will try to overwrite it
|
||||
# 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:
|
||||
return False
|
||||
|
||||
docDir = "content"
|
||||
self.theProject.ensureFolderStructure()
|
||||
|
||||
docFile = self.docHandle+".nwd"
|
||||
logger.debug("Saving document %s" % path.join(docDir, docFile))
|
||||
dataPath = path.join(self.theProject.projPath, docDir)
|
||||
docPath = path.join(dataPath, docFile)
|
||||
if not path.isdir(dataPath):
|
||||
mkdir(dataPath)
|
||||
logger.debug("Created folder %s" % dataPath)
|
||||
logger.debug("Saving document %s" % docFile)
|
||||
|
||||
docPath = path.join(self.theProject.projContent, docFile)
|
||||
docTemp = path.join(self.theProject.projContent, docFile+"~")
|
||||
|
||||
itemPath = self.theProject.projTree.getItemPath(self.docHandle)
|
||||
docMeta = "%%~ "+":".join(itemPath)+":"+self.theItem.itemName+"\n"
|
||||
|
||||
docTemp = path.join(dataPath, docFile+"~")
|
||||
try:
|
||||
with open(docTemp,mode="w",encoding="utf8") as outFile:
|
||||
with open(docTemp, mode="w", encoding="utf8") as outFile:
|
||||
outFile.write(docMeta)
|
||||
outFile.write(docText)
|
||||
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
|
||||
|
||||
# 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
|
||||
from the project data folder.
|
||||
"""
|
||||
docDir = "content"
|
||||
docFile = self.docHandle+".nwd"
|
||||
dataPath = path.join(self.theProject.projPath, docDir)
|
||||
|
||||
chkList = []
|
||||
chkList.append(path.join(dataPath, docFile))
|
||||
chkList.append(path.join(dataPath, docFile+"~"))
|
||||
chkList.append(path.join(dataPath, docFile[:-3]+"bak"))
|
||||
chkList.append(path.join(self.theProject.projContent, docFile))
|
||||
chkList.append(path.join(self.theProject.projContent, docFile+"~"))
|
||||
|
||||
for chkFile in chkList:
|
||||
if path.isfile(chkFile):
|
||||
try:
|
||||
@@ -188,6 +184,7 @@ class NWDoc():
|
||||
except Exception as e:
|
||||
self.makeAlert(["Could not delete document file.",str(e)], nwAlert.ERROR)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
##
|
||||
|
||||
+221
-72
@@ -31,6 +31,7 @@
|
||||
"""
|
||||
|
||||
import logging
|
||||
import json
|
||||
import nw
|
||||
|
||||
from os import path, mkdir, listdir, unlink, rename, rmdir
|
||||
@@ -42,7 +43,6 @@ from shutil import make_archive
|
||||
from PyQt5.QtWidgets import QMessageBox
|
||||
|
||||
from nw.gui.tools import OptionState
|
||||
from nw.core.tools import projectMaintenance
|
||||
from nw.core.document import NWDoc
|
||||
from nw.common import checkString, checkBool, checkInt, formatTimeStamp
|
||||
from nw.constants import (
|
||||
@@ -70,13 +70,15 @@ class NWProject():
|
||||
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
|
||||
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.projData = None # The full path to the project's data folder
|
||||
self.projDict = None # The spell check dictionary
|
||||
self.projFile = None # The file name of the project main XML file
|
||||
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.projCache = None # The full path to the project's cache folder
|
||||
self.projContent = None # The full path to the project's content folder
|
||||
self.projDict = None # The spell check dictionary
|
||||
self.projFile = None # The file name of the project main XML file
|
||||
|
||||
# Project Meta
|
||||
self.projName = "" # Project name (working title)
|
||||
@@ -196,7 +198,8 @@ class NWProject():
|
||||
# Project Settings
|
||||
self.projPath = None
|
||||
self.projMeta = None
|
||||
self.projData = None
|
||||
self.projCache = None
|
||||
self.projContent = None
|
||||
self.projDict = None
|
||||
self.projFile = nwFiles.PROJ_FILE
|
||||
self.projName = ""
|
||||
@@ -205,7 +208,7 @@ class NWProject():
|
||||
self.autoReplace = {}
|
||||
self.titleFormat = {
|
||||
"title" : r"%title%",
|
||||
"chapter" : r"Chapter %num%\\%title%",
|
||||
"chapter" : r"Chapter %ch%: %title%",
|
||||
"unnumbered" : r"%title%",
|
||||
"scene" : r"* * *",
|
||||
"section" : r"",
|
||||
@@ -248,14 +251,30 @@ class NWProject():
|
||||
self.projPath = path.abspath(path.dirname(fileName))
|
||||
logger.debug("Opening project: %s" % self.projPath)
|
||||
|
||||
self.projMeta = path.join(self.projPath,"meta")
|
||||
self.projData = path.join(self.projPath,"content")
|
||||
# Standard Folders and Files
|
||||
# ==========================
|
||||
|
||||
if not self.ensureFolderStructure():
|
||||
return False
|
||||
|
||||
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
|
||||
|
||||
if not self._checkFolder(self.projMeta):
|
||||
return False
|
||||
if not self._checkFolder(self.projData):
|
||||
return False
|
||||
# Check for Old Legacy Data
|
||||
# =========================
|
||||
|
||||
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:
|
||||
self._clearLockFile()
|
||||
@@ -272,10 +291,8 @@ class NWProject():
|
||||
else:
|
||||
logger.verbose("Project is not locked")
|
||||
|
||||
try:
|
||||
projectMaintenance(self)
|
||||
except Exception as E:
|
||||
logger.error(str(E))
|
||||
# Open The Project XML File
|
||||
# =========================
|
||||
|
||||
try:
|
||||
nwXML = etree.parse(fileName)
|
||||
@@ -315,12 +332,15 @@ class NWProject():
|
||||
self.saveCount = checkInt(xRoot.attrib["saveCount"], 0, False)
|
||||
if "autoCount" in xRoot.attrib:
|
||||
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("File version is %s" % fileVersion)
|
||||
|
||||
# Check File Type
|
||||
# ===============
|
||||
|
||||
if not nwxRoot == "novelWriterXML":
|
||||
self.makeAlert(
|
||||
"Project file does not appear to be a novelWriterXML file.",
|
||||
@@ -330,14 +350,17 @@ class NWProject():
|
||||
|
||||
# Check Project Storage Version
|
||||
# =============================
|
||||
|
||||
if fileVersion == "1.0":
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.question(self.theParent, "Old Project Version", (
|
||||
"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>"
|
||||
"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."
|
||||
) % nw.__package__)
|
||||
"version of %s any more, so make sure you have a recent backup."
|
||||
) % (
|
||||
nw.__package__, nw.__package__
|
||||
))
|
||||
if msgRes == QMessageBox.Yes:
|
||||
self._updateStorage()
|
||||
else:
|
||||
@@ -353,6 +376,7 @@ class NWProject():
|
||||
|
||||
# Check novelWriter Version
|
||||
# =========================
|
||||
|
||||
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI:
|
||||
msgBox = QMessageBox()
|
||||
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
||||
@@ -367,6 +391,7 @@ class NWProject():
|
||||
|
||||
# Start Parsing XML
|
||||
# =================
|
||||
|
||||
for xChild in xRoot:
|
||||
if xChild.tag == "project":
|
||||
logger.debug("Found project meta")
|
||||
@@ -384,6 +409,7 @@ class NWProject():
|
||||
self.bookAuthors.append(xItem.text)
|
||||
elif xItem.tag == "backup":
|
||||
self.doBackup = checkBool(xItem.text, False)
|
||||
|
||||
elif xChild.tag == "settings":
|
||||
logger.debug("Found project settings")
|
||||
for xItem in xChild:
|
||||
@@ -411,6 +437,7 @@ class NWProject():
|
||||
for xEntry in xItem:
|
||||
titleFormat[xEntry.tag] = checkString(xEntry.text, "", False)
|
||||
self.setTitleFormat(titleFormat)
|
||||
|
||||
elif xChild.tag == "content":
|
||||
logger.debug("Found project content")
|
||||
self.projTree.unpackXML(xChild)
|
||||
@@ -443,15 +470,8 @@ class NWProject():
|
||||
)
|
||||
return False
|
||||
|
||||
self.projMeta = path.join(self.projPath, "meta")
|
||||
self.projData = path.join(self.projPath, "content")
|
||||
saveTime = time()
|
||||
|
||||
if not self._checkFolder(self.projPath):
|
||||
return False
|
||||
if not self._checkFolder(self.projMeta):
|
||||
return False
|
||||
if not self._checkFolder(self.projData):
|
||||
if not self.ensureFolderStructure():
|
||||
return False
|
||||
|
||||
logger.debug("Saving project: %s" % self.projPath)
|
||||
@@ -470,6 +490,7 @@ class NWProject():
|
||||
"saveCount" : str(self.saveCount),
|
||||
"autoCount" : str(self.autoCount),
|
||||
"timeStamp" : formatTimeStamp(saveTime),
|
||||
"editTime" : str(int(self.editTime + saveTime - self.projOpened)),
|
||||
})
|
||||
|
||||
# Save Project Meta
|
||||
@@ -519,7 +540,7 @@ class NWProject():
|
||||
xml_declaration = True
|
||||
))
|
||||
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
|
||||
|
||||
# If we're here, the file was successfully saved,
|
||||
@@ -546,12 +567,33 @@ class NWProject():
|
||||
def closeProject(self):
|
||||
"""Close the current project and clear all meta data.
|
||||
"""
|
||||
self.projTree.writeToCFiles()
|
||||
self._appendSessionStats()
|
||||
self._clearLockFile()
|
||||
self.clearProject()
|
||||
self.lockedBy = None
|
||||
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
|
||||
##
|
||||
@@ -978,7 +1020,7 @@ class NWProject():
|
||||
|
||||
# Then check the files in the data folder
|
||||
orphanFiles = []
|
||||
for fileItem in listdir(self.projData):
|
||||
for fileItem in listdir(self.projContent):
|
||||
if not fileItem.endswith(".nwd"):
|
||||
logger.warning("Skipping file %s" % fileItem)
|
||||
continue
|
||||
@@ -1028,7 +1070,7 @@ class NWProject():
|
||||
def _appendSessionStats(self):
|
||||
"""Append session statistics to the sessions log file.
|
||||
"""
|
||||
if self.projMeta is None:
|
||||
if not self.ensureFolderStructure():
|
||||
return False
|
||||
|
||||
sessionFile = path.join(self.projMeta, nwFiles.SESS_INFO)
|
||||
@@ -1046,52 +1088,113 @@ class NWProject():
|
||||
|
||||
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 = []
|
||||
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):
|
||||
itemPath = path.join(self.projPath, projItem)
|
||||
if not path.isdir(itemPath) or not projItem.startswith("data_"):
|
||||
logger.info("Old data folder %s found" % theFolder)
|
||||
|
||||
# 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
|
||||
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:
|
||||
tHandle = projItem[-1]+dataFile[:12]
|
||||
newPath = path.join(contDir, tHandle+".nwd")
|
||||
try:
|
||||
rename(dataPath, newPath)
|
||||
logger.info("Moved file: %s" % dataPath)
|
||||
logger.info("New location: %s" % newPath)
|
||||
except:
|
||||
errList.append("Failed to move: %s" % dataPath)
|
||||
if len(dataItem) == 21 and dataItem.endswith("_main.nwd"):
|
||||
tHandle = theFolder[-1]+dataItem[:12]
|
||||
newPath = path.join(self.projContent, tHandle+".nwd")
|
||||
try:
|
||||
rename(theFile, newPath)
|
||||
logger.info("Moved file: %s" % theFile)
|
||||
logger.info("New location: %s" % newPath)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
errList.append("Could not move: %s" % theFile)
|
||||
|
||||
else:
|
||||
newPath = path.join(self.projPath, "unknown_"+dataFile)
|
||||
try:
|
||||
rename(dataPath, newPath)
|
||||
logger.info("Moved file: %s" % dataPath)
|
||||
logger.info("New location: %s" % newPath)
|
||||
except:
|
||||
errList.append("Failed to move: %s" % dataPath)
|
||||
try:
|
||||
rmdir(itemPath)
|
||||
logger.info("Removed folder: %s" % itemPath)
|
||||
except:
|
||||
errList.append("Failed to delete: %s" % itemPath)
|
||||
elif len(dataItem) == 21 and dataItem.endswith("_main.bak"):
|
||||
try:
|
||||
unlink(theFile)
|
||||
logger.info("Deleted file: %s" % theFile)
|
||||
except Exception as e:
|
||||
logger.error(str(e))
|
||||
errList.append("Could not delete: %s" % theFile)
|
||||
|
||||
if errList:
|
||||
self.makeAlert(errList, nwAlert.ERROR)
|
||||
else:
|
||||
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
|
||||
|
||||
@@ -1181,7 +1284,7 @@ class NWTree():
|
||||
for tHandle in self._treeOrder:
|
||||
tItem = self.__getitem__(tHandle)
|
||||
tItem.packXML(xContent)
|
||||
return
|
||||
return
|
||||
|
||||
def unpackXML(self, xContent):
|
||||
"""Iterate through all items of a content XML object and add
|
||||
@@ -1199,6 +1302,51 @@ class NWTree():
|
||||
|
||||
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
|
||||
##
|
||||
@@ -1481,7 +1629,6 @@ class NWItem():
|
||||
xSub = self._subPack(xPack,"type", text=str(self.itemType.name))
|
||||
xSub = self._subPack(xPack,"class", text=str(self.itemClass.name))
|
||||
xSub = self._subPack(xPack,"status", text=str(self.itemStatus))
|
||||
xSub = self._subPack(xPack,"expanded", text=str(self.isExpanded))
|
||||
if self.itemType == nwItemType.FILE:
|
||||
xSub = self._subPack(xPack,"exported", text=str(self.isExported))
|
||||
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,"paraCount", text=str(self.paraCount), none=False)
|
||||
xSub = self._subPack(xPack,"cursorPos", text=str(self.cursorPos), none=False)
|
||||
else:
|
||||
xSub = self._subPack(xPack,"expanded", text=str(self.isExpanded))
|
||||
return
|
||||
|
||||
def unpackXML(self, xItem):
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
File History:
|
||||
Created: 2019-04-22 [0.0.1] countWords
|
||||
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
|
||||
|
||||
This file is a part of novelWriter
|
||||
@@ -81,45 +80,6 @@ def countWords(theText):
|
||||
|
||||
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):
|
||||
"""Wrapper for converting numbers to words for chapter headings.
|
||||
"""
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
]
|
||||
@@ -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
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
### We Found 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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
%%~ b8136a5a774a0:7031beac91f75:Delete Me!
|
||||
%%~ b8136a5a774a0:98acd8c76c93a:Delete Me!
|
||||
### Delete Me!
|
||||
|
||||
This scene is trash.
|
||||
@@ -1,4 +1,4 @@
|
||||
%%~ edca4be2fcaf8:7031beac91f75:Part One
|
||||
%%~ edca4be2fcaf8:7031beac91f75:Part 1
|
||||
# Part One
|
||||
|
||||
The first part.
|
||||
@@ -5,10 +5,4 @@
|
||||
|
||||
Space … it’s 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
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>Sample Project</name>
|
||||
<title>Sample Project</title>
|
||||
@@ -11,8 +11,8 @@
|
||||
<spellCheck>True</spellCheck>
|
||||
<autoOutline>True</autoOutline>
|
||||
<lastEdited>636b6aa9b697b</lastEdited>
|
||||
<lastViewed>bc0cbd2a407f3</lastViewed>
|
||||
<lastWordCount>941</lastWordCount>
|
||||
<lastViewed>b3e74dbc1f584</lastViewed>
|
||||
<lastWordCount>914</lastWordCount>
|
||||
<autoReplace>
|
||||
<A>B</A>
|
||||
<B>E</B>
|
||||
@@ -57,7 +57,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>Started</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>TITLE</layout>
|
||||
<charCount>72</charCount>
|
||||
@@ -70,7 +69,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>PAGE</layout>
|
||||
<charCount>210</charCount>
|
||||
@@ -83,13 +81,12 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>PARTITION</layout>
|
||||
<charCount>23</charCount>
|
||||
<wordCount>5</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>27</cursorPos>
|
||||
<cursorPos>0</cursorPos>
|
||||
</item>
|
||||
<item handle="e7ded148d6e4a" order="3" parent="7031beac91f75">
|
||||
<name>A Folder</name>
|
||||
@@ -103,7 +100,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>Notes</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>CHAPTER</layout>
|
||||
<charCount>12</charCount>
|
||||
@@ -116,72 +112,66 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>1st Draft</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>1199</charCount>
|
||||
<wordCount>216</wordCount>
|
||||
<paraCount>7</paraCount>
|
||||
<cursorPos>1066</cursorPos>
|
||||
<cursorPos>1266</cursorPos>
|
||||
</item>
|
||||
<item handle="bc0cbd2a407f3" order="2" parent="e7ded148d6e4a">
|
||||
<name>Another Scene</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>1st Draft</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>476</charCount>
|
||||
<wordCount>93</wordCount>
|
||||
<paraCount>3</paraCount>
|
||||
<cursorPos>428</cursorPos>
|
||||
<cursorPos>551</cursorPos>
|
||||
</item>
|
||||
<item handle="ba8a28a246524" order="3" parent="e7ded148d6e4a">
|
||||
<name>Interlude</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>Finished</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>UNNUMBERED</layout>
|
||||
<charCount>633</charCount>
|
||||
<wordCount>101</wordCount>
|
||||
<paraCount>3</paraCount>
|
||||
<cursorPos>752</cursorPos>
|
||||
<cursorPos>1238</cursorPos>
|
||||
</item>
|
||||
<item handle="96b68994dfa3d" order="4" parent="e7ded148d6e4a">
|
||||
<name>A Note on Structure</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>2nd Draft</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>False</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>1692</charCount>
|
||||
<wordCount>313</wordCount>
|
||||
<paraCount>6</paraCount>
|
||||
<cursorPos>551</cursorPos>
|
||||
<cursorPos>1721</cursorPos>
|
||||
</item>
|
||||
<item handle="88706ddc78b1b" order="5" parent="e7ded148d6e4a">
|
||||
<name>Chapter Two</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>1st Draft</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>CHAPTER</layout>
|
||||
<charCount>139</charCount>
|
||||
<wordCount>28</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>242</cursorPos>
|
||||
<cursorPos>343</cursorPos>
|
||||
</item>
|
||||
<item handle="ae7339df26ded" order="6" parent="e7ded148d6e4a">
|
||||
<name>We Found John!</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>1st Draft</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>189</charCount>
|
||||
@@ -208,26 +198,24 @@
|
||||
<type>FILE</type>
|
||||
<class>CHARACTER</class>
|
||||
<status>Minor</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>49</charCount>
|
||||
<wordCount>9</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>65</cursorPos>
|
||||
<cursorPos>24</cursorPos>
|
||||
</item>
|
||||
<item handle="bb2c23b3c42cc" order="1" parent="f7e2d9f330615">
|
||||
<name>Jane Smith</name>
|
||||
<type>FILE</type>
|
||||
<class>CHARACTER</class>
|
||||
<status>Major</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>55</charCount>
|
||||
<wordCount>9</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>71</cursorPos>
|
||||
<cursorPos>25</cursorPos>
|
||||
</item>
|
||||
<item handle="15c4492bd5107" order="2" parent="None">
|
||||
<name>Locations</name>
|
||||
@@ -241,33 +229,30 @@
|
||||
<type>FILE</type>
|
||||
<class>WORLD</class>
|
||||
<status>Main</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>76</charCount>
|
||||
<wordCount>15</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>93</cursorPos>
|
||||
<cursorPos>20</cursorPos>
|
||||
</item>
|
||||
<item handle="f1471bef9f2ae" order="1" parent="15c4492bd5107">
|
||||
<name>Space</name>
|
||||
<type>FILE</type>
|
||||
<class>WORLD</class>
|
||||
<status>Minor</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>241</charCount>
|
||||
<wordCount>51</wordCount>
|
||||
<paraCount>3</paraCount>
|
||||
<cursorPos>135</cursorPos>
|
||||
<charCount>115</charCount>
|
||||
<wordCount>24</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>133</cursorPos>
|
||||
</item>
|
||||
<item handle="5eaea4e8cdee8" order="2" parent="15c4492bd5107">
|
||||
<name>Mars</name>
|
||||
<type>FILE</type>
|
||||
<class>WORLD</class>
|
||||
<status>Major</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>28</charCount>
|
||||
@@ -287,7 +272,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -55,7 +55,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -55,7 +55,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>331</charCount>
|
||||
@@ -75,7 +74,6 @@
|
||||
<type>FILE</type>
|
||||
<class>CHARACTER</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>34</charCount>
|
||||
@@ -95,7 +93,6 @@
|
||||
<type>FILE</type>
|
||||
<class>PLOT</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>48</charCount>
|
||||
@@ -115,7 +112,6 @@
|
||||
<type>FILE</type>
|
||||
<class>WORLD</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>51</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>Project Name</name>
|
||||
<title>Project Title</title>
|
||||
@@ -18,7 +18,7 @@
|
||||
</autoReplace>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -59,7 +59,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -55,7 +55,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>Note</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>False</exported>
|
||||
<layout>PAGE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -76,7 +76,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -76,7 +76,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?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>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
@@ -14,7 +14,7 @@
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %num%\\%title%</chapter>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
@@ -76,7 +76,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
@@ -117,7 +116,6 @@
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>0</charCount>
|
||||
@@ -130,7 +128,6 @@
|
||||
<type>FILE</type>
|
||||
<class>CHARACTER</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
<exported>True</exported>
|
||||
<layout>NOTE</layout>
|
||||
<charCount>0</charCount>
|
||||
|
||||
Reference in New Issue
Block a user