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__
# 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
+2
View File
@@ -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"
-2
View File
@@ -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
View File
@@ -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
View File
@@ -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):
-40
View File
@@ -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.
"""
+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!
@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 -1
View File
@@ -1,4 +1,4 @@
%%~ b8136a5a774a0:7031beac91f75:Delete Me!
%%~ b8136a5a774a0:98acd8c76c93a:Delete Me!
### Delete Me!
This scene is trash.
+1 -1
View File
@@ -1,4 +1,4 @@
%%~ edca4be2fcaf8:7031beac91f75:Part One
%%~ edca4be2fcaf8:7031beac91f75:Part 1
# Part One
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.
## 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'?>
<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>
+2 -3
View File
@@ -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>
+2 -6
View File
@@ -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>
+2 -3
View File
@@ -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>
+2 -3
View File
@@ -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>
+2 -3
View File
@@ -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>
+2 -3
View File
@@ -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>
+2 -5
View File
@@ -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>