Add test coverage of the project xml class

This commit is contained in:
Veronica Berglyd Olsen
2022-11-01 17:14:57 +01:00
parent f41db97860
commit 5b7f2b2b55
17 changed files with 3584 additions and 33 deletions
+2
View File
@@ -1576,8 +1576,10 @@ class NWProjectData:
"""
if novel is not None:
self._initCounts[0] = checkInt(novel, 0)
self._currCounts[0] = checkInt(novel, 0)
if notes is not None:
self._initCounts[1] = checkInt(notes, 0)
self._currCounts[1] = checkInt(notes, 0)
return
def setCurrCounts(self, novel=None, notes=None):
+12 -17
View File
@@ -58,9 +58,8 @@ class XMLReadState(Enum):
CANNOT_PARSE = 3
NOT_NWX_FILE = 4
UNKNOWN_VERSION = 5
PARSING_ERROR = 6
PARSED_OK = 7
WAS_LEGACY = 8
PARSED_OK = 6
WAS_LEGACY = 7
# END Class XMLReadState
@@ -173,6 +172,7 @@ class ProjectXMLReader:
self._state = XMLReadState.CANNOT_PARSE
return False
else:
self._state = XMLReadState.CANNOT_PARSE
return False
xRoot = xml.getroot()
@@ -191,27 +191,22 @@ class ProjectXMLReader:
logger.debug("XML is '%s' version '%s'", self._root, fileVersion)
self._appVersion = str(xRoot.attrib.get("appVersion", ""))
self._hexVersion = str(xRoot.attrib.get("appVersion", ""))
self._hexVersion = str(xRoot.attrib.get("hexVersion", ""))
self._timeStamp = str(xRoot.attrib.get("timeStamp", ""))
status = True
for xSection in xRoot:
if xSection.tag == "project":
status &= self._parseProjectMeta(xSection, projData)
self._parseProjectMeta(xSection, projData)
elif xSection.tag == "settings":
status &= self._parseProjectSettings(xSection, projData)
self._parseProjectSettings(xSection, projData)
elif xSection.tag == "content":
if self._version >= 0x0104:
status &= self._parseProjectContent(xSection, projContent)
self._parseProjectContent(xSection, projContent)
else:
status &= self._parseProjectContentLegacy(xSection, projContent, projData)
self._parseProjectContentLegacy(xSection, projContent, projData)
else:
logger.warning("Ignored <root/%s> in xml", xSection.tag)
if not status:
self._state = XMLReadState.PARSING_ERROR
return False
if self._version == 0x0104:
self._state = XMLReadState.PARSED_OK
else:
@@ -245,7 +240,7 @@ class ProjectXMLReader:
else:
logger.warning("Ignored <root/project/%s> in xml", xItem.tag)
return True
return
def _parseProjectSettings(self, xSection, projData):
"""Parse the settings section of the XML file.
@@ -284,7 +279,7 @@ class ProjectXMLReader:
else:
logger.warning("Ignored <root/settings/%s> in xml", xItem.tag)
return True
return
def _parseProjectContent(self, xSection, projContent):
"""Parse the content section of the XML file.
@@ -326,7 +321,7 @@ class ProjectXMLReader:
else:
logger.warning("Ignored item <root/content/%s> in xml", xItem.tag)
return True
return
def _parseProjectContentLegacy(self, xSection, projContent, projData):
"""Parse the content section of the XML file for older versions.
@@ -394,7 +389,7 @@ class ProjectXMLReader:
else:
logger.warning("Ignored <root/content/%s> in xml", xItem.tag)
return True
return
def _parseStatusImport(self, xItem, sObject):
"""Parse a status or importance entry.
+1 -1
View File
@@ -11,7 +11,7 @@
<spellCheck>True</spellCheck>
<autoOutline>True</autoOutline>
<lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>ba8a28a246524</lastViewed>
<lastViewed>636b6aa9b697b</lastViewed>
<lastWordCount>914</lastWordCount>
<autoReplace>
<A>B</A>
+4 -4
View File
@@ -5,12 +5,12 @@
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>408</saveCount>
<autoCount>71</autoCount>
<editTime>15120</editTime>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>False</doBackup>
<doBackup>True</doBackup>
<spellCheck>True</spellCheck>
<autoOutline>True</autoOutline>
<lastEdited>636b6aa9b697b</lastEdited>
+6 -6
View File
@@ -5,15 +5,15 @@
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>1122</saveCount>
<autoCount>191</autoCount>
<editTime>53749</editTime>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>False</doBackup>
<language>en</language>
<doBackup>True</doBackup>
<language>en_GB</language>
<spellCheck>True</spellCheck>
<spellLang>None</spellLang>
<spellLang>en_GB</spellLang>
<autoOutline>True</autoOutline>
<lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>636b6aa9b697b</lastViewed>
+5 -5
View File
@@ -5,15 +5,15 @@
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>1312</saveCount>
<autoCount>199</autoCount>
<editTime>65207</editTime>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>False</doBackup>
<doBackup>True</doBackup>
<language>en_GB</language>
<spellCheck>True</spellCheck>
<spellLang>None</spellLang>
<spellLang>en_GB</spellLang>
<autoOutline>True</autoOutline>
<lastEdited>636b6aa9b697b</lastEdited>
<lastViewed>636b6aa9b697b</lastViewed>
+163
View File
@@ -0,0 +1,163 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2022-11-01 12:20:53">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>True</doBackup>
<language>en_GB</language>
<spellCheck>True</spellCheck>
<spellLang>en_GB</spellLang>
<novelWordCount>954</novelWordCount>
<notesWordCount>409</notesWordCount>
<lastHandle>
<entry key="editor">636b6aa9b697b</entry>
<entry key="viewer">636b6aa9b697b</entry>
<entry key="novelTree">7031beac91f75</entry>
<entry key="outline">7031beac91f75</entry>
</lastHandle>
<autoReplace>
<entry key="A">B</entry>
<entry key="B">E</entry>
<entry key="C">D</entry>
</autoReplace>
<titleFormat>
<entry key="title">%title%</entry>
<entry key="chapter">Chapter %chw%: %title%</entry>
<entry key="unnumbered">%title%</entry>
<entry key="scene">Scene %ch%.%sc%: %title%</entry>
<entry key="section"></entry>
</titleFormat>
<status>
<entry key="sf12341" count="4" red="100" green="100" blue="100">New</entry>
<entry key="sf24ce6" count="2" red="200" green="50" blue="0">Notes</entry>
<entry key="sc24b8f" count="3" red="182" green="60" blue="0">Started</entry>
<entry key="s90e6c9" count="7" red="193" green="129" blue="0">1st Draft</entry>
<entry key="sd51c5b" count="0" red="193" green="129" blue="0">2nd Draft</entry>
<entry key="s8ae72a" count="0" red="193" green="129" blue="0">3rd Draft</entry>
<entry key="s78ea90" count="1" red="58" green="180" blue="58">Finished</entry>
</status>
<importance>
<entry key="ia857f0" count="5" red="100" green="100" blue="100">None</entry>
<entry key="icfb3a5" count="2" red="0" green="122" blue="188">Minor</entry>
<entry key="i2d7a54" count="2" red="21" green="0" blue="180">Major</entry>
<entry key="i56be10" count="1" red="117" green="0" blue="175">Main</entry>
</importance>
</settings>
<content count="27">
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
<meta expanded="True"/>
<name status="sc24b8f" import="ia857f0">Novel</name>
</item>
<item handle="53b69b83cdafc" parent="7031beac91f75" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H1" charCount="93" wordCount="19" paraCount="2" cursorPos="119"/>
<name status="sc24b8f" import="ia857f0" active="True">Title Page</name>
</item>
<item handle="974e400180a99" parent="7031beac91f75" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="251" wordCount="50" paraCount="2" cursorPos="277"/>
<name status="sf12341" import="ia857f0" active="True">Page</name>
</item>
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="7031beac91f75" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H1" charCount="26" wordCount="6" paraCount="1" cursorPos="36"/>
<name status="s90e6c9" import="ia857f0" active="True">Part One</name>
</item>
<item handle="6a2d6d5f4f401" parent="7031beac91f75" root="7031beac91f75" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="True" heading="H2" charCount="95" wordCount="18" paraCount="1" cursorPos="291"/>
<name status="sf24ce6" import="ia857f0" active="True">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H3" charCount="2687" wordCount="479" paraCount="14" cursorPos="67"/>
<name status="s90e6c9" import="ia857f0" active="True">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="465"/>
<name status="s90e6c9" import="ia857f0" active="True">Another Scene</name>
</item>
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H2" charCount="617" wordCount="101" paraCount="3" cursorPos="310"/>
<name status="s78ea90" import="ia857f0" active="True">Interlude</name>
</item>
<item handle="96b68994dfa3d" parent="7031beac91f75" root="7031beac91f75" order="5" type="FILE" class="NOVEL" layout="NOTE">
<meta expanded="False" heading="H1" charCount="1909" wordCount="346" paraCount="7" cursorPos="0"/>
<name status="sf24ce6" import="ia857f0" active="False">A Note on Structure</name>
</item>
<item handle="88706ddc78b1b" parent="7031beac91f75" root="7031beac91f75" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="True" heading="H2" charCount="139" wordCount="28" paraCount="1" cursorPos="188"/>
<name status="s90e6c9" import="ia857f0" active="True">Chapter Two</name>
</item>
<item handle="ae7339df26ded" parent="88706ddc78b1b" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H3" charCount="189" wordCount="37" paraCount="1" cursorPos="0"/>
<name status="s90e6c9" import="ia857f0" active="True">We Found John!</name>
</item>
<item handle="e5e47ebf63b1c" parent="None" root="e5e47ebf63b1c" order="1" type="ROOT" class="NOVEL">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Sequel</name>
</item>
<item handle="bacb7059e3083" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H1" charCount="27" wordCount="5" paraCount="1" cursorPos="100"/>
<name status="sc24b8f" import="ia857f0" active="True">Title Page</name>
</item>
<item handle="a520879ca0b45" parent="e5e47ebf63b1c" root="e5e47ebf63b1c" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H2" charCount="299" wordCount="55" paraCount="2" cursorPos="104"/>
<name status="s90e6c9" import="ia857f0" active="True">Chapter One</name>
</item>
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="2" type="ROOT" class="CHARACTER">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Characters</name>
</item>
<item handle="f7e2d9f330615" parent="f6622b4617424" root="f6622b4617424" order="0" type="FOLDER" class="CHARACTER">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Main Characters</name>
</item>
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
<name status="sf12341" import="icfb3a5" active="True">John Smith</name>
</item>
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
<name status="sf12341" import="i2d7a54" active="True">Jane Smith</name>
</item>
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Locations</name>
</item>
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="15c4492bd5107" order="0" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H1" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
<name status="sf12341" import="i56be10" active="True">Earth</name>
</item>
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="15c4492bd5107" order="1" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H1" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
<name status="sf12341" import="icfb3a5" active="True">Space</name>
</item>
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="15c4492bd5107" order="2" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H1" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
<name status="sf12341" import="i2d7a54" active="True">Mars</name>
</item>
<item handle="6827118336ac1" parent="None" root="6827118336ac1" order="4" type="ROOT" class="ARCHIVE">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Archive</name>
</item>
<item handle="ae9bf3c3ea159" parent="6827118336ac1" root="6827118336ac1" order="0" type="FOLDER" class="ARCHIVE">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Scenes</name>
</item>
<item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="6827118336ac1" order="0" type="FILE" class="ARCHIVE" layout="DOCUMENT">
<meta expanded="False" heading="H3" charCount="232" wordCount="42" paraCount="1" cursorPos="239"/>
<name status="s90e6c9" import="ia857f0" active="True">Old File</name>
</item>
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="5" type="ROOT" class="TRASH">
<meta expanded="True"/>
<name status="sf12341" import="ia857f0">Trash</name>
</item>
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="98acd8c76c93a" order="0" type="FILE" class="TRASH" layout="DOCUMENT">
<meta expanded="False" heading="H3" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/>
<name status="sf12341" import="ia857f0" active="True">Delete Me!</name>
</item>
</content>
</novelWriterXML>
+515
View File
@@ -0,0 +1,515 @@
[
{
"handle": "7031beac91f75",
"parent": null,
"root": "7031beac91f75",
"order": 0,
"type": "ROOT",
"class": "NOVEL",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Novel",
"status": "sc24b8f",
"import": "ia857f0",
"active": false
},
{
"handle": "53b69b83cdafc",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 0,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H1",
"charCount": 93,
"wordCount": 19,
"paraCount": 2,
"cursorPos": 119,
"label": "Title Page",
"status": "sc24b8f",
"import": "ia857f0",
"active": true
},
{
"handle": "974e400180a99",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 1,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H0",
"charCount": 251,
"wordCount": 50,
"paraCount": 2,
"cursorPos": 277,
"label": "Page",
"status": "sf12341",
"import": "ia857f0",
"active": true
},
{
"handle": "edca4be2fcaf8",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 2,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H1",
"charCount": 26,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 36,
"label": "Part One",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "6a2d6d5f4f401",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 3,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": true,
"heading": "H2",
"charCount": 95,
"wordCount": 18,
"paraCount": 1,
"cursorPos": 291,
"label": "Chapter One",
"status": "sf24ce6",
"import": "ia857f0",
"active": true
},
{
"handle": "636b6aa9b697b",
"parent": "6a2d6d5f4f401",
"root": "7031beac91f75",
"order": 0,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H3",
"charCount": 2687,
"wordCount": 479,
"paraCount": 14,
"cursorPos": 67,
"label": "Making a Scene",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "bc0cbd2a407f3",
"parent": "6a2d6d5f4f401",
"root": "7031beac91f75",
"order": 1,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H3",
"charCount": 548,
"wordCount": 108,
"paraCount": 3,
"cursorPos": 465,
"label": "Another Scene",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "ba8a28a246524",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 4,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H2",
"charCount": 617,
"wordCount": 101,
"paraCount": 3,
"cursorPos": 310,
"label": "Interlude",
"status": "s78ea90",
"import": "ia857f0",
"active": true
},
{
"handle": "96b68994dfa3d",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 5,
"type": "FILE",
"class": "NOVEL",
"layout": "NOTE",
"expanded": false,
"heading": "H1",
"charCount": 1909,
"wordCount": 346,
"paraCount": 7,
"cursorPos": 0,
"label": "A Note on Structure",
"status": "sf24ce6",
"import": "ia857f0",
"active": false
},
{
"handle": "88706ddc78b1b",
"parent": "7031beac91f75",
"root": "7031beac91f75",
"order": 6,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": true,
"heading": "H2",
"charCount": 139,
"wordCount": 28,
"paraCount": 1,
"cursorPos": 188,
"label": "Chapter Two",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "ae7339df26ded",
"parent": "88706ddc78b1b",
"root": "7031beac91f75",
"order": 0,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H3",
"charCount": 189,
"wordCount": 37,
"paraCount": 1,
"cursorPos": 0,
"label": "We Found John!",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "e5e47ebf63b1c",
"parent": null,
"root": "e5e47ebf63b1c",
"order": 1,
"type": "ROOT",
"class": "NOVEL",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Sequel",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "bacb7059e3083",
"parent": "e5e47ebf63b1c",
"root": "e5e47ebf63b1c",
"order": 0,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H1",
"charCount": 27,
"wordCount": 5,
"paraCount": 1,
"cursorPos": 100,
"label": "Title Page",
"status": "sc24b8f",
"import": "ia857f0",
"active": true
},
{
"handle": "a520879ca0b45",
"parent": "e5e47ebf63b1c",
"root": "e5e47ebf63b1c",
"order": 1,
"type": "FILE",
"class": "NOVEL",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H2",
"charCount": 299,
"wordCount": 55,
"paraCount": 2,
"cursorPos": 104,
"label": "Chapter One",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "f6622b4617424",
"parent": null,
"root": "f6622b4617424",
"order": 2,
"type": "ROOT",
"class": "CHARACTER",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Characters",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "f7e2d9f330615",
"parent": "f6622b4617424",
"root": "f6622b4617424",
"order": 0,
"type": "FOLDER",
"class": "CHARACTER",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Main Characters",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "14298de4d9524",
"parent": "f7e2d9f330615",
"root": "f6622b4617424",
"order": 0,
"type": "FILE",
"class": "CHARACTER",
"layout": "NOTE",
"expanded": false,
"heading": "H1",
"charCount": 49,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 24,
"label": "John Smith",
"status": "sf12341",
"import": "icfb3a5",
"active": true
},
{
"handle": "bb2c23b3c42cc",
"parent": "f7e2d9f330615",
"root": "f6622b4617424",
"order": 1,
"type": "FILE",
"class": "CHARACTER",
"layout": "NOTE",
"expanded": false,
"heading": "H1",
"charCount": 55,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 25,
"label": "Jane Smith",
"status": "sf12341",
"import": "i2d7a54",
"active": true
},
{
"handle": "15c4492bd5107",
"parent": null,
"root": "15c4492bd5107",
"order": 3,
"type": "ROOT",
"class": "WORLD",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Locations",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "b3e74dbc1f584",
"parent": "15c4492bd5107",
"root": "15c4492bd5107",
"order": 0,
"type": "FILE",
"class": "WORLD",
"layout": "NOTE",
"expanded": false,
"heading": "H1",
"charCount": 76,
"wordCount": 15,
"paraCount": 1,
"cursorPos": 20,
"label": "Earth",
"status": "sf12341",
"import": "i56be10",
"active": true
},
{
"handle": "f1471bef9f2ae",
"parent": "15c4492bd5107",
"root": "15c4492bd5107",
"order": 1,
"type": "FILE",
"class": "WORLD",
"layout": "NOTE",
"expanded": false,
"heading": "H1",
"charCount": 115,
"wordCount": 24,
"paraCount": 1,
"cursorPos": 133,
"label": "Space",
"status": "sf12341",
"import": "icfb3a5",
"active": true
},
{
"handle": "5eaea4e8cdee8",
"parent": "15c4492bd5107",
"root": "15c4492bd5107",
"order": 2,
"type": "FILE",
"class": "WORLD",
"layout": "NOTE",
"expanded": false,
"heading": "H1",
"charCount": 28,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 45,
"label": "Mars",
"status": "sf12341",
"import": "i2d7a54",
"active": true
},
{
"handle": "6827118336ac1",
"parent": null,
"root": "6827118336ac1",
"order": 4,
"type": "ROOT",
"class": "ARCHIVE",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Archive",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "ae9bf3c3ea159",
"parent": "6827118336ac1",
"root": "6827118336ac1",
"order": 0,
"type": "FOLDER",
"class": "ARCHIVE",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Scenes",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "8a5deb88c0e97",
"parent": "ae9bf3c3ea159",
"root": "6827118336ac1",
"order": 0,
"type": "FILE",
"class": "ARCHIVE",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H3",
"charCount": 232,
"wordCount": 42,
"paraCount": 1,
"cursorPos": 239,
"label": "Old File",
"status": "s90e6c9",
"import": "ia857f0",
"active": true
},
{
"handle": "98acd8c76c93a",
"parent": null,
"root": "98acd8c76c93a",
"order": 5,
"type": "ROOT",
"class": "TRASH",
"layout": "NO_LAYOUT",
"expanded": true,
"heading": "H0",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 0,
"label": "Trash",
"status": "sf12341",
"import": "ia857f0",
"active": false
},
{
"handle": "b8136a5a774a0",
"parent": "98acd8c76c93a",
"root": "98acd8c76c93a",
"order": 0,
"type": "FILE",
"class": "TRASH",
"layout": "DOCUMENT",
"expanded": false,
"heading": "H3",
"charCount": 30,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 36,
"label": "Delete Me!",
"status": "sf12341",
"import": "ia857f0",
"active": true
}
]
@@ -0,0 +1,362 @@
[
{
"handle": "7031beac91f75",
"parent": null,
"root": null,
"order": 0,
"heading": "H0",
"label": "Novel",
"type": "ROOT",
"class": "NOVEL",
"expanded": true,
"status": "s000002"
},
{
"handle": "53b69b83cdafc",
"parent": "7031beac91f75",
"root": null,
"order": 0,
"heading": "H0",
"label": "Title Page",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 72,
"wordCount": 15,
"paraCount": 2,
"cursorPos": 78,
"status": "s000002"
},
{
"handle": "974e400180a99",
"parent": "7031beac91f75",
"root": null,
"order": 1,
"heading": "H0",
"label": "Page",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 208,
"wordCount": 40,
"paraCount": 2,
"cursorPos": 213,
"status": "s000000"
},
{
"handle": "edca4be2fcaf8",
"parent": "7031beac91f75",
"root": null,
"order": 2,
"heading": "H0",
"label": "Part One",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 23,
"wordCount": 5,
"paraCount": 1,
"cursorPos": 0,
"status": "s000000"
},
{
"handle": "e7ded148d6e4a",
"parent": "7031beac91f75",
"root": null,
"order": 3,
"heading": "H0",
"label": "A Folder",
"type": "FOLDER",
"class": "NOVEL",
"expanded": true,
"status": "s000003"
},
{
"handle": "6a2d6d5f4f401",
"parent": "e7ded148d6e4a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Chapter One",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 12,
"wordCount": 3,
"paraCount": 0,
"cursorPos": 215,
"status": "s000001"
},
{
"handle": "636b6aa9b697b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 1,
"heading": "H0",
"label": "Making a Scene",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 1199,
"wordCount": 216,
"paraCount": 7,
"cursorPos": 527,
"status": "s000003"
},
{
"handle": "bc0cbd2a407f3",
"parent": "e7ded148d6e4a",
"root": null,
"order": 2,
"heading": "H0",
"label": "Another Scene",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 476,
"wordCount": 93,
"paraCount": 3,
"cursorPos": 551,
"status": "s000003"
},
{
"handle": "ba8a28a246524",
"parent": "e7ded148d6e4a",
"root": null,
"order": 3,
"heading": "H0",
"label": "Interlude",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 633,
"wordCount": 101,
"paraCount": 3,
"cursorPos": 1238,
"status": "s000006"
},
{
"handle": "96b68994dfa3d",
"parent": "e7ded148d6e4a",
"root": null,
"order": 4,
"heading": "H0",
"label": "A Note on Structure",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": false,
"layout": "NOTE",
"charCount": 1692,
"wordCount": 313,
"paraCount": 6,
"cursorPos": 1721,
"status": "s000004"
},
{
"handle": "88706ddc78b1b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 5,
"heading": "H0",
"label": "Chapter Two",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 139,
"wordCount": 28,
"paraCount": 1,
"cursorPos": 343,
"status": "s000003"
},
{
"handle": "ae7339df26ded",
"parent": "e7ded148d6e4a",
"root": null,
"order": 6,
"heading": "H0",
"label": "We Found John!",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 189,
"wordCount": 37,
"paraCount": 1,
"cursorPos": 224,
"status": "s000003"
},
{
"handle": "f6622b4617424",
"parent": null,
"root": null,
"order": 1,
"heading": "H0",
"label": "Characters",
"type": "ROOT",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "f7e2d9f330615",
"parent": "f6622b4617424",
"root": null,
"order": 0,
"heading": "H0",
"label": "Main Characters",
"type": "FOLDER",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "14298de4d9524",
"parent": "f7e2d9f330615",
"root": null,
"order": 0,
"heading": "H0",
"label": "John Smith",
"type": "FILE",
"class": "CHARACTER",
"expanded": false,
"active": true,
"layout": "NOTE",
"charCount": 49,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 24,
"import": "i000008"
},
{
"handle": "bb2c23b3c42cc",
"parent": "f7e2d9f330615",
"root": null,
"order": 1,
"heading": "H0",
"label": "Jane Smith",
"type": "FILE",
"class": "CHARACTER",
"expanded": false,
"active": true,
"layout": "NOTE",
"charCount": 55,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 25,
"import": "i000009"
},
{
"handle": "15c4492bd5107",
"parent": null,
"root": null,
"order": 2,
"heading": "H0",
"label": "Locations",
"type": "ROOT",
"class": "WORLD",
"expanded": true,
"import": null
},
{
"handle": "b3e74dbc1f584",
"parent": "15c4492bd5107",
"root": null,
"order": 0,
"heading": "H0",
"label": "Earth",
"type": "FILE",
"class": "WORLD",
"expanded": false,
"active": true,
"layout": "NOTE",
"charCount": 76,
"wordCount": 15,
"paraCount": 1,
"cursorPos": 20,
"import": "i00000a"
},
{
"handle": "f1471bef9f2ae",
"parent": "15c4492bd5107",
"root": null,
"order": 1,
"heading": "H0",
"label": "Space",
"type": "FILE",
"class": "WORLD",
"expanded": false,
"active": true,
"layout": "NOTE",
"charCount": 115,
"wordCount": 24,
"paraCount": 1,
"cursorPos": 133,
"import": "i000008"
},
{
"handle": "5eaea4e8cdee8",
"parent": "15c4492bd5107",
"root": null,
"order": 2,
"heading": "H0",
"label": "Mars",
"type": "FILE",
"class": "WORLD",
"expanded": false,
"active": true,
"layout": "NOTE",
"charCount": 28,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 45,
"import": "i000009"
},
{
"handle": "98acd8c76c93a",
"parent": null,
"root": null,
"order": 3,
"heading": "H0",
"label": "Trash",
"type": "ROOT",
"class": "TRASH",
"expanded": true,
"import": null
},
{
"handle": "b8136a5a774a0",
"parent": "98acd8c76c93a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Delete Me!",
"type": "FILE",
"class": "NOVEL",
"expanded": false,
"active": true,
"layout": "DOCUMENT",
"charCount": 0,
"wordCount": 0,
"paraCount": 0,
"cursorPos": 36,
"status": "s000000"
}
]
+143
View File
@@ -0,0 +1,143 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2020-05-28 09:59:15">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>0</saveCount>
<autoCount>0</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>True</doBackup>
<language>None</language>
<spellCheck>True</spellCheck>
<spellLang>None</spellLang>
<novelWordCount>0</novelWordCount>
<notesWordCount>0</notesWordCount>
<lastHandle>
<entry key="editor">None</entry>
<entry key="viewer">None</entry>
<entry key="novelTree">None</entry>
<entry key="outline">None</entry>
</lastHandle>
<autoReplace>
<entry key="A">B</entry>
<entry key="B">E</entry>
<entry key="C">D</entry>
</autoReplace>
<titleFormat>
<entry key="title">%title%</entry>
<entry key="chapter">Chapter %ch%: %title%</entry>
<entry key="unnumbered">%title%</entry>
<entry key="scene">Scene %ch%.%sc%: %title%</entry>
<entry key="section"></entry>
</titleFormat>
<status>
<entry key="s000000" count="0" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58">Finished</entry>
</status>
<importance>
<entry key="i000007" count="0" red="100" green="100" blue="100">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175">Main</entry>
</importance>
</settings>
<content count="22">
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
<meta expanded="True"/>
<name status="s000002" import="i000007">Novel</name>
</item>
<item handle="53b69b83cdafc" parent="7031beac91f75" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="72" wordCount="15" paraCount="2" cursorPos="78"/>
<name status="s000002" import="i000007" active="True">Title Page</name>
</item>
<item handle="974e400180a99" parent="7031beac91f75" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="208" wordCount="40" paraCount="2" cursorPos="213"/>
<name status="s000000" import="i000007" active="True">Page</name>
</item>
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="23" wordCount="5" paraCount="1" cursorPos="0"/>
<name status="s000000" import="i000007" active="True">Part One</name>
</item>
<item handle="e7ded148d6e4a" parent="7031beac91f75" root="None" order="3" type="FOLDER" class="NOVEL">
<meta expanded="True"/>
<name status="s000003" import="i000007">A Folder</name>
</item>
<item handle="6a2d6d5f4f401" parent="e7ded148d6e4a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="12" wordCount="3" paraCount="0" cursorPos="215"/>
<name status="s000001" import="i000007" active="True">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="e7ded148d6e4a" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="1199" wordCount="216" paraCount="7" cursorPos="527"/>
<name status="s000003" import="i000007" active="True">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="e7ded148d6e4a" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="476" wordCount="93" paraCount="3" cursorPos="551"/>
<name status="s000003" import="i000007" active="True">Another Scene</name>
</item>
<item handle="ba8a28a246524" parent="e7ded148d6e4a" root="None" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="633" wordCount="101" paraCount="3" cursorPos="1238"/>
<name status="s000006" import="i000007" active="True">Interlude</name>
</item>
<item handle="96b68994dfa3d" parent="e7ded148d6e4a" root="None" order="4" type="FILE" class="NOVEL" layout="NOTE">
<meta expanded="False" heading="H0" charCount="1692" wordCount="313" paraCount="6" cursorPos="1721"/>
<name status="s000004" import="i000007" active="False">A Note on Structure</name>
</item>
<item handle="88706ddc78b1b" parent="e7ded148d6e4a" root="None" order="5" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="139" wordCount="28" paraCount="1" cursorPos="343"/>
<name status="s000003" import="i000007" active="True">Chapter Two</name>
</item>
<item handle="ae7339df26ded" parent="e7ded148d6e4a" root="None" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="189" wordCount="37" paraCount="1" cursorPos="224"/>
<name status="s000003" import="i000007" active="True">We Found John!</name>
</item>
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="1" type="ROOT" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Characters</name>
</item>
<item handle="f7e2d9f330615" parent="f6622b4617424" root="None" order="0" type="FOLDER" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Main Characters</name>
</item>
<item handle="14298de4d9524" parent="f7e2d9f330615" root="None" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
<name status="s000000" import="i000008" active="True">John Smith</name>
</item>
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="None" order="1" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
<name status="s000000" import="i000009" active="True">Jane Smith</name>
</item>
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="2" type="ROOT" class="WORLD">
<meta expanded="True"/>
<name status="s000000" import="i000007">Locations</name>
</item>
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="None" order="0" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
<name status="s000000" import="i00000a" active="True">Earth</name>
</item>
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="None" order="1" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
<name status="s000000" import="i000008" active="True">Space</name>
</item>
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="None" order="2" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
<name status="s000000" import="i000009" active="True">Mars</name>
</item>
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="3" type="ROOT" class="TRASH">
<meta expanded="True"/>
<name status="s000000" import="i000007">Trash</name>
</item>
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="0" wordCount="0" paraCount="0" cursorPos="36"/>
<name status="s000000" import="i000007" active="True">Delete Me!</name>
</item>
</content>
</novelWriterXML>
@@ -0,0 +1,346 @@
[
{
"handle": "7031beac91f75",
"parent": null,
"root": null,
"order": 0,
"heading": "H0",
"label": "Novel",
"type": "ROOT",
"class": "NOVEL",
"expanded": true,
"status": "s000002"
},
{
"handle": "53b69b83cdafc",
"parent": "7031beac91f75",
"root": null,
"order": 0,
"heading": "H0",
"label": "Title Page",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 72,
"wordCount": 15,
"paraCount": 2,
"cursorPos": 78,
"status": "s000002"
},
{
"handle": "974e400180a99",
"parent": "7031beac91f75",
"root": null,
"order": 1,
"heading": "H0",
"label": "Page",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 210,
"wordCount": 40,
"paraCount": 2,
"cursorPos": 213,
"status": "s000000"
},
{
"handle": "edca4be2fcaf8",
"parent": "7031beac91f75",
"root": null,
"order": 2,
"heading": "H0",
"label": "Part One",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 23,
"wordCount": 5,
"paraCount": 1,
"cursorPos": 0,
"status": "s000000"
},
{
"handle": "e7ded148d6e4a",
"parent": "7031beac91f75",
"root": null,
"order": 3,
"heading": "H0",
"label": "A Folder",
"type": "FOLDER",
"class": "NOVEL",
"expanded": true,
"status": "s000003"
},
{
"handle": "6a2d6d5f4f401",
"parent": "e7ded148d6e4a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Chapter One",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 12,
"wordCount": 3,
"paraCount": 0,
"cursorPos": 215,
"status": "s000001"
},
{
"handle": "636b6aa9b697b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 1,
"heading": "H0",
"label": "Making a Scene",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 1483,
"wordCount": 263,
"paraCount": 8,
"cursorPos": 1086,
"status": "s000003"
},
{
"handle": "bc0cbd2a407f3",
"parent": "e7ded148d6e4a",
"root": null,
"order": 2,
"heading": "H0",
"label": "Another Scene",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 476,
"wordCount": 93,
"paraCount": 3,
"cursorPos": 428,
"status": "s000003"
},
{
"handle": "ba8a28a246524",
"parent": "e7ded148d6e4a",
"root": null,
"order": 3,
"heading": "H0",
"label": "Interlude",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 633,
"wordCount": 101,
"paraCount": 3,
"cursorPos": 1238,
"status": "s000006"
},
{
"handle": "96b68994dfa3d",
"parent": "e7ded148d6e4a",
"root": null,
"order": 4,
"heading": "H0",
"label": "A Note on Structure",
"type": "FILE",
"class": "NOVEL",
"active": false,
"layout": "NOTE",
"charCount": 1692,
"wordCount": 313,
"paraCount": 6,
"cursorPos": 1721,
"status": "s000004"
},
{
"handle": "88706ddc78b1b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 5,
"heading": "H0",
"label": "Chapter Two",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 139,
"wordCount": 28,
"paraCount": 1,
"cursorPos": 343,
"status": "s000003"
},
{
"handle": "ae7339df26ded",
"parent": "e7ded148d6e4a",
"root": null,
"order": 6,
"heading": "H0",
"label": "We Found John!",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 189,
"wordCount": 37,
"paraCount": 1,
"cursorPos": 224,
"status": "s000003"
},
{
"handle": "f6622b4617424",
"parent": null,
"root": null,
"order": 1,
"heading": "H0",
"label": "Characters",
"type": "ROOT",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "f7e2d9f330615",
"parent": "f6622b4617424",
"root": null,
"order": 0,
"heading": "H0",
"label": "Main Characters",
"type": "FOLDER",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "14298de4d9524",
"parent": "f7e2d9f330615",
"root": null,
"order": 0,
"heading": "H0",
"label": "John Smith",
"type": "FILE",
"class": "CHARACTER",
"active": true,
"layout": "NOTE",
"charCount": 49,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 24,
"import": "i000008"
},
{
"handle": "bb2c23b3c42cc",
"parent": "f7e2d9f330615",
"root": null,
"order": 1,
"heading": "H0",
"label": "Jane Smith",
"type": "FILE",
"class": "CHARACTER",
"active": true,
"layout": "NOTE",
"charCount": 55,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 25,
"import": "i000009"
},
{
"handle": "15c4492bd5107",
"parent": null,
"root": null,
"order": 2,
"heading": "H0",
"label": "Locations",
"type": "ROOT",
"class": "WORLD",
"expanded": true,
"import": null
},
{
"handle": "b3e74dbc1f584",
"parent": "15c4492bd5107",
"root": null,
"order": 0,
"heading": "H0",
"label": "Earth",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 76,
"wordCount": 15,
"paraCount": 1,
"cursorPos": 20,
"import": "i00000a"
},
{
"handle": "f1471bef9f2ae",
"parent": "15c4492bd5107",
"root": null,
"order": 1,
"heading": "H0",
"label": "Space",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 115,
"wordCount": 24,
"paraCount": 1,
"cursorPos": 133,
"import": "i000008"
},
{
"handle": "5eaea4e8cdee8",
"parent": "15c4492bd5107",
"root": null,
"order": 2,
"heading": "H0",
"label": "Mars",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 28,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 45,
"import": "i000009"
},
{
"handle": "98acd8c76c93a",
"parent": null,
"root": null,
"order": 3,
"heading": "H0",
"label": "Trash",
"type": "ROOT",
"class": "TRASH",
"expanded": true,
"import": null
},
{
"handle": "b8136a5a774a0",
"parent": "98acd8c76c93a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Delete Me!",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 30,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 36,
"status": "s000000"
}
]
+143
View File
@@ -0,0 +1,143 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2020-06-26 21:20:24">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>True</doBackup>
<language>None</language>
<spellCheck>True</spellCheck>
<spellLang>None</spellLang>
<novelWordCount>0</novelWordCount>
<notesWordCount>0</notesWordCount>
<lastHandle>
<entry key="editor">None</entry>
<entry key="viewer">None</entry>
<entry key="novelTree">None</entry>
<entry key="outline">None</entry>
</lastHandle>
<autoReplace>
<entry key="A">B</entry>
<entry key="B">E</entry>
<entry key="C">D</entry>
</autoReplace>
<titleFormat>
<entry key="title">%title%</entry>
<entry key="chapter">Chapter %ch%: %title%</entry>
<entry key="unnumbered">%title%</entry>
<entry key="scene">Scene %ch%.%sc%: %title%</entry>
<entry key="section"></entry>
</titleFormat>
<status>
<entry key="s000000" count="0" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58">Finished</entry>
</status>
<importance>
<entry key="i000007" count="0" red="100" green="100" blue="100">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175">Main</entry>
</importance>
</settings>
<content count="22">
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
<meta expanded="True"/>
<name status="s000002" import="i000007">Novel</name>
</item>
<item handle="53b69b83cdafc" parent="7031beac91f75" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="72" wordCount="15" paraCount="2" cursorPos="78"/>
<name status="s000002" import="i000007" active="True">Title Page</name>
</item>
<item handle="974e400180a99" parent="7031beac91f75" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="210" wordCount="40" paraCount="2" cursorPos="213"/>
<name status="s000000" import="i000007" active="True">Page</name>
</item>
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="23" wordCount="5" paraCount="1" cursorPos="0"/>
<name status="s000000" import="i000007" active="True">Part One</name>
</item>
<item handle="e7ded148d6e4a" parent="7031beac91f75" root="None" order="3" type="FOLDER" class="NOVEL">
<meta expanded="True"/>
<name status="s000003" import="i000007">A Folder</name>
</item>
<item handle="6a2d6d5f4f401" parent="e7ded148d6e4a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="12" wordCount="3" paraCount="0" cursorPos="215"/>
<name status="s000001" import="i000007" active="True">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="e7ded148d6e4a" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="1483" wordCount="263" paraCount="8" cursorPos="1086"/>
<name status="s000003" import="i000007" active="True">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="e7ded148d6e4a" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="476" wordCount="93" paraCount="3" cursorPos="428"/>
<name status="s000003" import="i000007" active="True">Another Scene</name>
</item>
<item handle="ba8a28a246524" parent="e7ded148d6e4a" root="None" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="633" wordCount="101" paraCount="3" cursorPos="1238"/>
<name status="s000006" import="i000007" active="True">Interlude</name>
</item>
<item handle="96b68994dfa3d" parent="e7ded148d6e4a" root="None" order="4" type="FILE" class="NOVEL" layout="NOTE">
<meta expanded="False" heading="H0" charCount="1692" wordCount="313" paraCount="6" cursorPos="1721"/>
<name status="s000004" import="i000007" active="False">A Note on Structure</name>
</item>
<item handle="88706ddc78b1b" parent="e7ded148d6e4a" root="None" order="5" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="139" wordCount="28" paraCount="1" cursorPos="343"/>
<name status="s000003" import="i000007" active="True">Chapter Two</name>
</item>
<item handle="ae7339df26ded" parent="e7ded148d6e4a" root="None" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="189" wordCount="37" paraCount="1" cursorPos="224"/>
<name status="s000003" import="i000007" active="True">We Found John!</name>
</item>
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="1" type="ROOT" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Characters</name>
</item>
<item handle="f7e2d9f330615" parent="f6622b4617424" root="None" order="0" type="FOLDER" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Main Characters</name>
</item>
<item handle="14298de4d9524" parent="f7e2d9f330615" root="None" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
<name status="s000000" import="i000008" active="True">John Smith</name>
</item>
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="None" order="1" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
<name status="s000000" import="i000009" active="True">Jane Smith</name>
</item>
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="2" type="ROOT" class="WORLD">
<meta expanded="True"/>
<name status="s000000" import="i000007">Locations</name>
</item>
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="None" order="0" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
<name status="s000000" import="i00000a" active="True">Earth</name>
</item>
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="None" order="1" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
<name status="s000000" import="i000008" active="True">Space</name>
</item>
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="None" order="2" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
<name status="s000000" import="i000009" active="True">Mars</name>
</item>
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="3" type="ROOT" class="TRASH">
<meta expanded="True"/>
<name status="s000000" import="i000007">Trash</name>
</item>
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/>
<name status="s000000" import="i000007" active="True">Delete Me!</name>
</item>
</content>
</novelWriterXML>
@@ -0,0 +1,387 @@
[
{
"handle": "7031beac91f75",
"parent": null,
"root": null,
"order": 0,
"heading": "H0",
"label": "Novel",
"type": "ROOT",
"class": "NOVEL",
"expanded": true,
"status": "s000002"
},
{
"handle": "53b69b83cdafc",
"parent": "7031beac91f75",
"root": null,
"order": 0,
"heading": "H0",
"label": "Title Page",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 241,
"wordCount": 42,
"paraCount": 3,
"cursorPos": 252,
"status": "s000002"
},
{
"handle": "974e400180a99",
"parent": "7031beac91f75",
"root": null,
"order": 1,
"heading": "H0",
"label": "Page",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 125,
"wordCount": 26,
"paraCount": 2,
"cursorPos": 127,
"status": "s000000"
},
{
"handle": "edca4be2fcaf8",
"parent": "7031beac91f75",
"root": null,
"order": 2,
"heading": "H0",
"label": "Part One",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 26,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 30,
"status": "s000000"
},
{
"handle": "e7ded148d6e4a",
"parent": "7031beac91f75",
"root": null,
"order": 3,
"heading": "H0",
"label": "A Folder",
"type": "FOLDER",
"class": "NOVEL",
"expanded": true,
"status": "s000003"
},
{
"handle": "6a2d6d5f4f401",
"parent": "e7ded148d6e4a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Chapter One",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 75,
"wordCount": 14,
"paraCount": 1,
"cursorPos": 279,
"status": "s000001"
},
{
"handle": "636b6aa9b697b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 1,
"heading": "H0",
"label": "Making a Scene",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 2429,
"wordCount": 432,
"paraCount": 14,
"cursorPos": 61,
"status": "s000003"
},
{
"handle": "bc0cbd2a407f3",
"parent": "e7ded148d6e4a",
"root": null,
"order": 2,
"heading": "H0",
"label": "Another Scene",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 476,
"wordCount": 93,
"paraCount": 3,
"cursorPos": 577,
"status": "s000003"
},
{
"handle": "ba8a28a246524",
"parent": "e7ded148d6e4a",
"root": null,
"order": 3,
"heading": "H0",
"label": "Interlude",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 617,
"wordCount": 101,
"paraCount": 3,
"cursorPos": 1137,
"status": "s000000"
},
{
"handle": "96b68994dfa3d",
"parent": "e7ded148d6e4a",
"root": null,
"order": 4,
"heading": "H0",
"label": "A Note on Structure",
"type": "FILE",
"class": "NOVEL",
"active": false,
"layout": "NOTE",
"charCount": 1692,
"wordCount": 313,
"paraCount": 6,
"cursorPos": 1110,
"status": "s000004"
},
{
"handle": "88706ddc78b1b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 5,
"heading": "H0",
"label": "Chapter Two",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 139,
"wordCount": 28,
"paraCount": 1,
"cursorPos": 343,
"status": "s000003"
},
{
"handle": "ae7339df26ded",
"parent": "e7ded148d6e4a",
"root": null,
"order": 6,
"heading": "H0",
"label": "We Found John!",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 189,
"wordCount": 37,
"paraCount": 1,
"cursorPos": 224,
"status": "s000003"
},
{
"handle": "f6622b4617424",
"parent": null,
"root": null,
"order": 1,
"heading": "H0",
"label": "Characters",
"type": "ROOT",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "f7e2d9f330615",
"parent": "f6622b4617424",
"root": null,
"order": 0,
"heading": "H0",
"label": "Main Characters",
"type": "FOLDER",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "14298de4d9524",
"parent": "f7e2d9f330615",
"root": null,
"order": 0,
"heading": "H0",
"label": "John Smith",
"type": "FILE",
"class": "CHARACTER",
"active": true,
"layout": "NOTE",
"charCount": 49,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 24,
"import": "i000008"
},
{
"handle": "bb2c23b3c42cc",
"parent": "f7e2d9f330615",
"root": null,
"order": 1,
"heading": "H0",
"label": "Jane Smith",
"type": "FILE",
"class": "CHARACTER",
"active": true,
"layout": "NOTE",
"charCount": 55,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 25,
"import": "i000009"
},
{
"handle": "15c4492bd5107",
"parent": null,
"root": null,
"order": 2,
"heading": "H0",
"label": "Locations",
"type": "ROOT",
"class": "WORLD",
"expanded": true,
"import": null
},
{
"handle": "b3e74dbc1f584",
"parent": "15c4492bd5107",
"root": null,
"order": 0,
"heading": "H0",
"label": "Earth",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 76,
"wordCount": 15,
"paraCount": 1,
"cursorPos": 20,
"import": "i00000a"
},
{
"handle": "f1471bef9f2ae",
"parent": "15c4492bd5107",
"root": null,
"order": 1,
"heading": "H0",
"label": "Space",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 115,
"wordCount": 24,
"paraCount": 1,
"cursorPos": 133,
"import": "i000008"
},
{
"handle": "5eaea4e8cdee8",
"parent": "15c4492bd5107",
"root": null,
"order": 2,
"heading": "H0",
"label": "Mars",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 28,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 45,
"import": "i000009"
},
{
"handle": "6827118336ac1",
"parent": null,
"root": null,
"order": 3,
"heading": "H0",
"label": "Outtakes",
"type": "ROOT",
"class": "ARCHIVE",
"expanded": true,
"status": null
},
{
"handle": "ae9bf3c3ea159",
"parent": "6827118336ac1",
"root": null,
"order": 0,
"heading": "H0",
"label": "Scenes",
"type": "FOLDER",
"class": "ARCHIVE",
"expanded": true,
"status": null
},
{
"handle": "8a5deb88c0e97",
"parent": "ae9bf3c3ea159",
"root": null,
"order": 0,
"heading": "H0",
"label": "Old File",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 315,
"wordCount": 55,
"paraCount": 1,
"cursorPos": 322,
"status": "s000003"
},
{
"handle": "98acd8c76c93a",
"parent": null,
"root": null,
"order": 4,
"heading": "H0",
"label": "Trash",
"type": "ROOT",
"class": "TRASH",
"expanded": true,
"import": null
},
{
"handle": "b8136a5a774a0",
"parent": "98acd8c76c93a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Delete Me!",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 30,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 36,
"status": "s000000"
}
]
+155
View File
@@ -0,0 +1,155 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2021-08-30 23:33:44">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>True</doBackup>
<language>en_GB</language>
<spellCheck>True</spellCheck>
<spellLang>en_GB</spellLang>
<novelWordCount>840</novelWordCount>
<notesWordCount>376</notesWordCount>
<lastHandle>
<entry key="editor">None</entry>
<entry key="viewer">None</entry>
<entry key="novelTree">None</entry>
<entry key="outline">None</entry>
</lastHandle>
<autoReplace>
<entry key="A">B</entry>
<entry key="B">E</entry>
<entry key="C">D</entry>
</autoReplace>
<titleFormat>
<entry key="title">%title%</entry>
<entry key="chapter">Chapter %chw%: %title%</entry>
<entry key="unnumbered">%title%</entry>
<entry key="scene">Scene %ch%.%sc%: %title%</entry>
<entry key="section"></entry>
</titleFormat>
<status>
<entry key="s000000" count="0" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58">Finished</entry>
</status>
<importance>
<entry key="i000007" count="0" red="100" green="100" blue="100">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175">Main</entry>
</importance>
</settings>
<content count="25">
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
<meta expanded="True"/>
<name status="s000002" import="i000007">Novel</name>
</item>
<item handle="53b69b83cdafc" parent="7031beac91f75" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="241" wordCount="42" paraCount="3" cursorPos="252"/>
<name status="s000002" import="i000007" active="True">Title Page</name>
</item>
<item handle="974e400180a99" parent="7031beac91f75" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="125" wordCount="26" paraCount="2" cursorPos="127"/>
<name status="s000000" import="i000007" active="True">Page</name>
</item>
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="26" wordCount="6" paraCount="1" cursorPos="30"/>
<name status="s000000" import="i000007" active="True">Part One</name>
</item>
<item handle="e7ded148d6e4a" parent="7031beac91f75" root="None" order="3" type="FOLDER" class="NOVEL">
<meta expanded="True"/>
<name status="s000003" import="i000007">A Folder</name>
</item>
<item handle="6a2d6d5f4f401" parent="e7ded148d6e4a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="75" wordCount="14" paraCount="1" cursorPos="279"/>
<name status="s000001" import="i000007" active="True">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="e7ded148d6e4a" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="2429" wordCount="432" paraCount="14" cursorPos="61"/>
<name status="s000003" import="i000007" active="True">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="e7ded148d6e4a" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="476" wordCount="93" paraCount="3" cursorPos="577"/>
<name status="s000003" import="i000007" active="True">Another Scene</name>
</item>
<item handle="ba8a28a246524" parent="e7ded148d6e4a" root="None" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="617" wordCount="101" paraCount="3" cursorPos="1137"/>
<name status="s000000" import="i000007" active="True">Interlude</name>
</item>
<item handle="96b68994dfa3d" parent="e7ded148d6e4a" root="None" order="4" type="FILE" class="NOVEL" layout="NOTE">
<meta expanded="False" heading="H0" charCount="1692" wordCount="313" paraCount="6" cursorPos="1110"/>
<name status="s000004" import="i000007" active="False">A Note on Structure</name>
</item>
<item handle="88706ddc78b1b" parent="e7ded148d6e4a" root="None" order="5" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="139" wordCount="28" paraCount="1" cursorPos="343"/>
<name status="s000003" import="i000007" active="True">Chapter Two</name>
</item>
<item handle="ae7339df26ded" parent="e7ded148d6e4a" root="None" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="189" wordCount="37" paraCount="1" cursorPos="224"/>
<name status="s000003" import="i000007" active="True">We Found John!</name>
</item>
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="1" type="ROOT" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Characters</name>
</item>
<item handle="f7e2d9f330615" parent="f6622b4617424" root="None" order="0" type="FOLDER" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Main Characters</name>
</item>
<item handle="14298de4d9524" parent="f7e2d9f330615" root="None" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
<name status="s000000" import="i000008" active="True">John Smith</name>
</item>
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="None" order="1" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
<name status="s000000" import="i000009" active="True">Jane Smith</name>
</item>
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="2" type="ROOT" class="WORLD">
<meta expanded="True"/>
<name status="s000000" import="i000007">Locations</name>
</item>
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="None" order="0" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
<name status="s000000" import="i00000a" active="True">Earth</name>
</item>
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="None" order="1" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
<name status="s000000" import="i000008" active="True">Space</name>
</item>
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="None" order="2" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
<name status="s000000" import="i000009" active="True">Mars</name>
</item>
<item handle="6827118336ac1" parent="None" root="6827118336ac1" order="3" type="ROOT" class="ARCHIVE">
<meta expanded="True"/>
<name status="s000000" import="i000007">Outtakes</name>
</item>
<item handle="ae9bf3c3ea159" parent="6827118336ac1" root="None" order="0" type="FOLDER" class="ARCHIVE">
<meta expanded="True"/>
<name status="s000000" import="i000007">Scenes</name>
</item>
<item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="315" wordCount="55" paraCount="1" cursorPos="322"/>
<name status="s000003" import="i000007" active="True">Old File</name>
</item>
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="4" type="ROOT" class="TRASH">
<meta expanded="True"/>
<name status="s000000" import="i000007">Trash</name>
</item>
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/>
<name status="s000000" import="i000007" active="True">Delete Me!</name>
</item>
</content>
</novelWriterXML>
@@ -0,0 +1,387 @@
[
{
"handle": "7031beac91f75",
"parent": null,
"root": null,
"order": 0,
"heading": "H0",
"label": "Novel",
"type": "ROOT",
"class": "NOVEL",
"expanded": true,
"status": "s000002"
},
{
"handle": "53b69b83cdafc",
"parent": "7031beac91f75",
"root": null,
"order": 0,
"heading": "H0",
"label": "Title Page",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 93,
"wordCount": 19,
"paraCount": 2,
"cursorPos": 2,
"status": "s000002"
},
{
"handle": "974e400180a99",
"parent": "7031beac91f75",
"root": null,
"order": 1,
"heading": "H0",
"label": "Page",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 186,
"wordCount": 39,
"paraCount": 2,
"cursorPos": 212,
"status": "s000000"
},
{
"handle": "edca4be2fcaf8",
"parent": "7031beac91f75",
"root": null,
"order": 2,
"heading": "H0",
"label": "Part One",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 26,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 33,
"status": "s000000"
},
{
"handle": "e7ded148d6e4a",
"parent": "7031beac91f75",
"root": null,
"order": 3,
"heading": "H0",
"label": "A Folder",
"type": "FOLDER",
"class": "NOVEL",
"expanded": true,
"status": "s000003"
},
{
"handle": "6a2d6d5f4f401",
"parent": "e7ded148d6e4a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Chapter One",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 75,
"wordCount": 14,
"paraCount": 1,
"cursorPos": 279,
"status": "s000001"
},
{
"handle": "636b6aa9b697b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 1,
"heading": "H0",
"label": "Making a Scene",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 2429,
"wordCount": 432,
"paraCount": 14,
"cursorPos": 62,
"status": "s000003"
},
{
"handle": "bc0cbd2a407f3",
"parent": "e7ded148d6e4a",
"root": null,
"order": 2,
"heading": "H0",
"label": "Another Scene",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 476,
"wordCount": 93,
"paraCount": 3,
"cursorPos": 577,
"status": "s000003"
},
{
"handle": "ba8a28a246524",
"parent": "e7ded148d6e4a",
"root": null,
"order": 3,
"heading": "H0",
"label": "Interlude",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 617,
"wordCount": 101,
"paraCount": 3,
"cursorPos": 4,
"status": "s000000"
},
{
"handle": "96b68994dfa3d",
"parent": "e7ded148d6e4a",
"root": null,
"order": 4,
"heading": "H0",
"label": "A Note on Structure",
"type": "FILE",
"class": "NOVEL",
"active": false,
"layout": "NOTE",
"charCount": 1692,
"wordCount": 313,
"paraCount": 6,
"cursorPos": 1110,
"status": "s000004"
},
{
"handle": "88706ddc78b1b",
"parent": "e7ded148d6e4a",
"root": null,
"order": 5,
"heading": "H0",
"label": "Chapter Two",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 139,
"wordCount": 28,
"paraCount": 1,
"cursorPos": 343,
"status": "s000003"
},
{
"handle": "ae7339df26ded",
"parent": "e7ded148d6e4a",
"root": null,
"order": 6,
"heading": "H0",
"label": "We Found John!",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 189,
"wordCount": 37,
"paraCount": 1,
"cursorPos": 224,
"status": "s000003"
},
{
"handle": "f6622b4617424",
"parent": null,
"root": null,
"order": 1,
"heading": "H0",
"label": "Characters",
"type": "ROOT",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "f7e2d9f330615",
"parent": "f6622b4617424",
"root": null,
"order": 0,
"heading": "H0",
"label": "Main Characters",
"type": "FOLDER",
"class": "CHARACTER",
"expanded": true,
"import": null
},
{
"handle": "14298de4d9524",
"parent": "f7e2d9f330615",
"root": null,
"order": 0,
"heading": "H0",
"label": "John Smith",
"type": "FILE",
"class": "CHARACTER",
"active": true,
"layout": "NOTE",
"charCount": 49,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 24,
"import": "i000008"
},
{
"handle": "bb2c23b3c42cc",
"parent": "f7e2d9f330615",
"root": null,
"order": 1,
"heading": "H0",
"label": "Jane Smith",
"type": "FILE",
"class": "CHARACTER",
"active": true,
"layout": "NOTE",
"charCount": 55,
"wordCount": 9,
"paraCount": 1,
"cursorPos": 25,
"import": "i000009"
},
{
"handle": "15c4492bd5107",
"parent": null,
"root": null,
"order": 2,
"heading": "H0",
"label": "Locations",
"type": "ROOT",
"class": "WORLD",
"expanded": true,
"import": null
},
{
"handle": "b3e74dbc1f584",
"parent": "15c4492bd5107",
"root": null,
"order": 0,
"heading": "H0",
"label": "Earth",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 76,
"wordCount": 15,
"paraCount": 1,
"cursorPos": 20,
"import": "i00000a"
},
{
"handle": "f1471bef9f2ae",
"parent": "15c4492bd5107",
"root": null,
"order": 1,
"heading": "H0",
"label": "Space",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 115,
"wordCount": 24,
"paraCount": 1,
"cursorPos": 133,
"import": "i000008"
},
{
"handle": "5eaea4e8cdee8",
"parent": "15c4492bd5107",
"root": null,
"order": 2,
"heading": "H0",
"label": "Mars",
"type": "FILE",
"class": "WORLD",
"active": true,
"layout": "NOTE",
"charCount": 28,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 45,
"import": "i000009"
},
{
"handle": "6827118336ac1",
"parent": null,
"root": null,
"order": 3,
"heading": "H0",
"label": "Archive",
"type": "ROOT",
"class": "ARCHIVE",
"expanded": true,
"status": "s000000"
},
{
"handle": "ae9bf3c3ea159",
"parent": "6827118336ac1",
"root": null,
"order": 0,
"heading": "H0",
"label": "Scenes",
"type": "FOLDER",
"class": "ARCHIVE",
"expanded": true,
"status": "s000000"
},
{
"handle": "8a5deb88c0e97",
"parent": "ae9bf3c3ea159",
"root": null,
"order": 0,
"heading": "H0",
"label": "Old File",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 314,
"wordCount": 55,
"paraCount": 1,
"cursorPos": 322,
"status": "s000003"
},
{
"handle": "98acd8c76c93a",
"parent": null,
"root": null,
"order": 4,
"heading": "H0",
"label": "Trash",
"type": "ROOT",
"class": "TRASH",
"expanded": true,
"import": null
},
{
"handle": "b8136a5a774a0",
"parent": "98acd8c76c93a",
"root": null,
"order": 0,
"heading": "H0",
"label": "Delete Me!",
"type": "FILE",
"class": "NOVEL",
"active": true,
"layout": "DOCUMENT",
"charCount": 30,
"wordCount": 6,
"paraCount": 1,
"cursorPos": 36,
"status": "s000000"
}
]
+155
View File
@@ -0,0 +1,155 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.4" timeStamp="2022-10-25 18:26:15">
<project>
<name>Sample Project</name>
<title>Sample Project</title>
<author>Jane Smith</author>
<author>Jay Doh</author>
<saveCount>5</saveCount>
<autoCount>10</autoCount>
<editTime>1000</editTime>
</project>
<settings>
<doBackup>True</doBackup>
<language>en_GB</language>
<spellCheck>True</spellCheck>
<spellLang>en_GB</spellLang>
<novelWordCount>830</novelWordCount>
<notesWordCount>376</notesWordCount>
<lastHandle>
<entry key="editor">None</entry>
<entry key="viewer">None</entry>
<entry key="novelTree">None</entry>
<entry key="outline">None</entry>
</lastHandle>
<autoReplace>
<entry key="A">B</entry>
<entry key="B">E</entry>
<entry key="C">D</entry>
</autoReplace>
<titleFormat>
<entry key="title">%title%</entry>
<entry key="chapter">Chapter %chw%: %title%</entry>
<entry key="unnumbered">%title%</entry>
<entry key="scene">Scene %ch%.%sc%: %title%</entry>
<entry key="section"></entry>
</titleFormat>
<status>
<entry key="s000000" count="0" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58">Finished</entry>
</status>
<importance>
<entry key="i000007" count="0" red="100" green="100" blue="100">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175">Main</entry>
</importance>
</settings>
<content count="25">
<item handle="7031beac91f75" parent="None" root="7031beac91f75" order="0" type="ROOT" class="NOVEL">
<meta expanded="True"/>
<name status="s000002" import="i000007">Novel</name>
</item>
<item handle="53b69b83cdafc" parent="7031beac91f75" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="93" wordCount="19" paraCount="2" cursorPos="2"/>
<name status="s000002" import="i000007" active="True">Title Page</name>
</item>
<item handle="974e400180a99" parent="7031beac91f75" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="186" wordCount="39" paraCount="2" cursorPos="212"/>
<name status="s000000" import="i000007" active="True">Page</name>
</item>
<item handle="edca4be2fcaf8" parent="7031beac91f75" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="26" wordCount="6" paraCount="1" cursorPos="33"/>
<name status="s000000" import="i000007" active="True">Part One</name>
</item>
<item handle="e7ded148d6e4a" parent="7031beac91f75" root="None" order="3" type="FOLDER" class="NOVEL">
<meta expanded="True"/>
<name status="s000003" import="i000007">A Folder</name>
</item>
<item handle="6a2d6d5f4f401" parent="e7ded148d6e4a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="75" wordCount="14" paraCount="1" cursorPos="279"/>
<name status="s000001" import="i000007" active="True">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="e7ded148d6e4a" root="None" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="2429" wordCount="432" paraCount="14" cursorPos="62"/>
<name status="s000003" import="i000007" active="True">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="e7ded148d6e4a" root="None" order="2" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="476" wordCount="93" paraCount="3" cursorPos="577"/>
<name status="s000003" import="i000007" active="True">Another Scene</name>
</item>
<item handle="ba8a28a246524" parent="e7ded148d6e4a" root="None" order="3" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="617" wordCount="101" paraCount="3" cursorPos="4"/>
<name status="s000000" import="i000007" active="True">Interlude</name>
</item>
<item handle="96b68994dfa3d" parent="e7ded148d6e4a" root="None" order="4" type="FILE" class="NOVEL" layout="NOTE">
<meta expanded="False" heading="H0" charCount="1692" wordCount="313" paraCount="6" cursorPos="1110"/>
<name status="s000004" import="i000007" active="False">A Note on Structure</name>
</item>
<item handle="88706ddc78b1b" parent="e7ded148d6e4a" root="None" order="5" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="139" wordCount="28" paraCount="1" cursorPos="343"/>
<name status="s000003" import="i000007" active="True">Chapter Two</name>
</item>
<item handle="ae7339df26ded" parent="e7ded148d6e4a" root="None" order="6" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="189" wordCount="37" paraCount="1" cursorPos="224"/>
<name status="s000003" import="i000007" active="True">We Found John!</name>
</item>
<item handle="f6622b4617424" parent="None" root="f6622b4617424" order="1" type="ROOT" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Characters</name>
</item>
<item handle="f7e2d9f330615" parent="f6622b4617424" root="None" order="0" type="FOLDER" class="CHARACTER">
<meta expanded="True"/>
<name status="s000000" import="i000007">Main Characters</name>
</item>
<item handle="14298de4d9524" parent="f7e2d9f330615" root="None" order="0" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="49" wordCount="9" paraCount="1" cursorPos="24"/>
<name status="s000000" import="i000008" active="True">John Smith</name>
</item>
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="None" order="1" type="FILE" class="CHARACTER" layout="NOTE">
<meta expanded="False" heading="H0" charCount="55" wordCount="9" paraCount="1" cursorPos="25"/>
<name status="s000000" import="i000009" active="True">Jane Smith</name>
</item>
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="2" type="ROOT" class="WORLD">
<meta expanded="True"/>
<name status="s000000" import="i000007">Locations</name>
</item>
<item handle="b3e74dbc1f584" parent="15c4492bd5107" root="None" order="0" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="76" wordCount="15" paraCount="1" cursorPos="20"/>
<name status="s000000" import="i00000a" active="True">Earth</name>
</item>
<item handle="f1471bef9f2ae" parent="15c4492bd5107" root="None" order="1" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="115" wordCount="24" paraCount="1" cursorPos="133"/>
<name status="s000000" import="i000008" active="True">Space</name>
</item>
<item handle="5eaea4e8cdee8" parent="15c4492bd5107" root="None" order="2" type="FILE" class="WORLD" layout="NOTE">
<meta expanded="False" heading="H0" charCount="28" wordCount="6" paraCount="1" cursorPos="45"/>
<name status="s000000" import="i000009" active="True">Mars</name>
</item>
<item handle="6827118336ac1" parent="None" root="6827118336ac1" order="3" type="ROOT" class="ARCHIVE">
<meta expanded="True"/>
<name status="s000000" import="i000007">Archive</name>
</item>
<item handle="ae9bf3c3ea159" parent="6827118336ac1" root="None" order="0" type="FOLDER" class="ARCHIVE">
<meta expanded="True"/>
<name status="s000000" import="i000007">Scenes</name>
</item>
<item handle="8a5deb88c0e97" parent="ae9bf3c3ea159" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="314" wordCount="55" paraCount="1" cursorPos="322"/>
<name status="s000003" import="i000007" active="True">Old File</name>
</item>
<item handle="98acd8c76c93a" parent="None" root="98acd8c76c93a" order="4" type="ROOT" class="TRASH">
<meta expanded="True"/>
<name status="s000000" import="i000007">Trash</name>
</item>
<item handle="b8136a5a774a0" parent="98acd8c76c93a" root="None" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="False" heading="H0" charCount="30" wordCount="6" paraCount="1" cursorPos="36"/>
<name status="s000000" import="i000007" active="True">Delete Me!</name>
</item>
</content>
</novelWriterXML>
+798
View File
@@ -0,0 +1,798 @@
"""
novelWriter ProjectXMLReader/Writer Class Tester
==================================================
This file is a part of novelWriter
Copyright 20182022, Veronica Berglyd Olsen
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
import json
import os
import pytest
import shutil
from datetime import datetime
from mock import causeOSError
from tools import cmpFiles, writeFile
from novelwriter.core.item import NWItem
from novelwriter.core.project import NWProjectData
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter, XMLReadState
class MockProject:
def setProjectChanged(self, *a):
pass
@pytest.mark.core
def testCoreProjectXML_ReadCurrent(monkeypatch, filesDir, fncDir, outDir, refDir):
"""Test reading the current XML file format.
"""
refFile = os.path.join(filesDir, "nwProject-1.4.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.4.nwx")
bakFile = os.path.join(fncDir, "nwProject-1.4.bak")
outFile = os.path.join(fncDir, "nwProject.nwx")
xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION
data = NWProjectData(MockProject())
content = []
# With no valid files, the read should fail
writeFile(xmlFile, "")
assert xmlReader.read(data, content) is False
assert xmlReader.state == XMLReadState.CANNOT_PARSE
# Also add an invalid backup file
writeFile(bakFile, "")
assert xmlReader.read(data, content) is False
assert xmlReader.state == XMLReadState.CANNOT_PARSE
# Add a valid backup file, that is not novelWriter
writeFile(bakFile, "<xml/>")
assert xmlReader.read(data, content) is False
assert xmlReader.state == XMLReadState.NOT_NWX_FILE
# Add a valid project file, that is not novelWriter
writeFile(xmlFile, "<xml/>")
assert xmlReader.read(data, content) is False
assert xmlReader.state == XMLReadState.NOT_NWX_FILE
# Add a valid novelwriter file without a file version
writeFile(xmlFile, "<novelWriterXML/>")
assert xmlReader.read(data, content) is False
assert xmlReader.state == XMLReadState.UNKNOWN_VERSION
# Check parsing of unkown sections
writeFile(xmlFile, (
"<novelWriterXML fileVersion='1.4'>"
" <project>"
" <stuff></stuff>"
" </project>"
" <settings>"
" <stuff></stuff>"
" </settings>"
" <content>"
" <item>"
" <stuff></stuff>"
" </item>"
" <stuff></stuff>"
" </content>"
" <stuff></stuff>"
"</novelWriterXML>"
))
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.PARSED_OK
writeFile(xmlFile, (
"<novelWriterXML fileVersion='1.0'>"
" <project>"
" <stuff></stuff>"
" </project>"
" <settings>"
" <stuff></stuff>"
" </settings>"
" <content>"
" <item>"
" <stuff></stuff>"
" </item>"
" <stuff></stuff>"
" </content>"
" <stuff></stuff>"
"</novelWriterXML>"
))
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.WAS_LEGACY
# Reset data objects
data = NWProjectData(MockProject())
content = []
# Parse a valid, complete file
shutil.copy(refFile, xmlFile)
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.PARSED_OK
assert xmlReader.xmlRoot == "novelWriterXML"
assert xmlReader.xmlVersion == 0x0104
assert xmlReader.appVersion == "2.0-rc1"
assert xmlReader.hexVersion == "0x020000c1"
# Check loaded data
assert data.name == "Sample Project"
assert data.title == "Sample Project"
assert data.authors == ["Jane Smith", "Jay Doh"]
assert data.saveCount == 5
assert data.autoCount == 10
assert data.editTime == 1000
assert data.doBackup is True
assert data.language == "en_GB"
assert data.spellCheck is True
assert data.spellLang == "en_GB"
assert data.initCounts == (954, 409)
assert data.currCounts == (954, 409)
assert data.getLastHandle("editor") == "636b6aa9b697b"
assert data.getLastHandle("viewer") == "636b6aa9b697b"
assert data.getLastHandle("novelTree") == "7031beac91f75"
assert data.getLastHandle("outline") == "7031beac91f75"
assert data.getTitleFormat("title") == "%title%"
assert data.getTitleFormat("chapter") == "Chapter %chw%: %title%"
assert data.getTitleFormat("unnumbered") == "%title%"
assert data.getTitleFormat("scene") == "Scene %ch%.%sc%: %title%"
assert data.getTitleFormat("section") == ""
assert data.itemStatus.name("sf12341") == "New"
assert data.itemStatus.name("sf24ce6") == "Notes"
assert data.itemStatus.name("sc24b8f") == "Started"
assert data.itemStatus.name("s90e6c9") == "1st Draft"
assert data.itemStatus.name("sd51c5b") == "2nd Draft"
assert data.itemStatus.name("s8ae72a") == "3rd Draft"
assert data.itemStatus.name("s78ea90") == "Finished"
assert data.itemImport.name("ia857f0") == "None"
assert data.itemImport.name("icfb3a5") == "Minor"
assert data.itemImport.name("i2d7a54") == "Major"
assert data.itemImport.name("i56be10") == "Main"
assert data.itemStatus.cols("sf12341") == (100, 100, 100)
assert data.itemStatus.cols("sf24ce6") == (200, 50, 0)
assert data.itemStatus.cols("sc24b8f") == (182, 60, 0)
assert data.itemStatus.cols("s90e6c9") == (193, 129, 0)
assert data.itemStatus.cols("sd51c5b") == (193, 129, 0)
assert data.itemStatus.cols("s8ae72a") == (193, 129, 0)
assert data.itemStatus.cols("s78ea90") == (58, 180, 58)
assert data.itemImport.cols("ia857f0") == (100, 100, 100)
assert data.itemImport.cols("icfb3a5") == (0, 122, 188)
assert data.itemImport.cols("i2d7a54") == (21, 0, 180)
assert data.itemImport.cols("i56be10") == (117, 0, 175)
assert data.itemStatus.count("sf12341") == 4
assert data.itemStatus.count("sf24ce6") == 2
assert data.itemStatus.count("sc24b8f") == 3
assert data.itemStatus.count("s90e6c9") == 7
assert data.itemStatus.count("sd51c5b") == 0
assert data.itemStatus.count("s8ae72a") == 0
assert data.itemStatus.count("s78ea90") == 1
assert data.itemImport.count("ia857f0") == 5
assert data.itemImport.count("icfb3a5") == 2
assert data.itemImport.count("i2d7a54") == 2
assert data.itemImport.count("i56be10") == 1
# Compare content
dumpFile = os.path.join(outDir, "projectXML_ReadCurrent.json")
compFile = os.path.join(refDir, "projectXML_ReadCurrent.json")
with open(dumpFile, mode="w", encoding="utf-8") as dump:
json.dump(content, dump, indent=2)
assert cmpFiles(dumpFile, compFile)
packedContent = []
mockProject = MockProject()
mockProject.__setattr__("data", data)
for entry in content:
item = NWItem(mockProject)
item.unpack(entry)
packedContent.append(item.pack())
# Save the project again, which should produce an identical project xml
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir)
# Fail saving
with monkeypatch.context() as mp:
mp.setattr("builtins.open", causeOSError)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is False
assert str(xmlWriter.error) == "Mock OSError"
with monkeypatch.context() as mp:
mp.setattr("os.replace", causeOSError)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is False
assert str(xmlWriter.error) == "Mock OSError"
# Successful save (should be twice)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
assert cmpFiles(outFile, xmlFile)
# END Test testCoreProjectXML_ReadCurrent
@pytest.mark.core
def testCoreProjectXML_ReadLegacy10(filesDir, fncDir, outDir, refDir, mockRnd):
"""Test reading the version 1.0 XML file format.
"""
refFile = os.path.join(filesDir, "nwProject-1.0.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.0.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION
data = NWProjectData(MockProject())
content = []
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.WAS_LEGACY
assert xmlReader.xmlRoot == "novelWriterXML"
assert xmlReader.xmlVersion == 0x0100
assert xmlReader.appVersion == "0.6.1"
assert xmlReader.hexVersion == "0x000601f0"
# Check loaded data
assert data.name == "Sample Project"
assert data.title == "Sample Project"
assert data.authors == ["Jane Smith", "Jay Doh"]
assert data.saveCount == 0 # Doesn't exist in 1.0
assert data.autoCount == 0 # Doesn't exist in 1.0
assert data.editTime == 0 # Doesn't exist in 1.0
assert data.doBackup is True
assert data.language is None # Doesn't exist in 1.0
assert data.spellCheck is True
assert data.spellLang is None # Doesn't exist in 1.0
assert data.initCounts == (0, 0)
assert data.currCounts == (0, 0)
assert data.getLastHandle("editor") is None # Dropped by conversion
assert data.getLastHandle("viewer") is None # Dropped by conversion
assert data.getLastHandle("novelTree") is None # Doesn't exist in 1.0
assert data.getLastHandle("outline") is None # Doesn't exist in 1.0
assert data.getTitleFormat("title") == "%title%"
assert data.getTitleFormat("chapter") == "Chapter %ch%: %title%"
assert data.getTitleFormat("unnumbered") == "%title%"
assert data.getTitleFormat("scene") == "Scene %ch%.%sc%: %title%"
assert data.getTitleFormat("section") == ""
assert data.itemStatus.name("s000000") == "New"
assert data.itemStatus.name("s000001") == "Notes"
assert data.itemStatus.name("s000002") == "Started"
assert data.itemStatus.name("s000003") == "1st Draft"
assert data.itemStatus.name("s000004") == "2nd Draft"
assert data.itemStatus.name("s000005") == "3rd Draft"
assert data.itemStatus.name("s000006") == "Finished"
assert data.itemImport.name("i000007") == "None"
assert data.itemImport.name("i000008") == "Minor"
assert data.itemImport.name("i000009") == "Major"
assert data.itemImport.name("i00000a") == "Main"
assert data.itemStatus.cols("s000000") == (100, 100, 100)
assert data.itemStatus.cols("s000001") == (200, 50, 0)
assert data.itemStatus.cols("s000002") == (182, 60, 0)
assert data.itemStatus.cols("s000003") == (193, 129, 0)
assert data.itemStatus.cols("s000004") == (193, 129, 0)
assert data.itemStatus.cols("s000005") == (193, 129, 0)
assert data.itemStatus.cols("s000006") == (58, 180, 58)
assert data.itemImport.cols("i000007") == (100, 100, 100)
assert data.itemImport.cols("i000008") == (0, 122, 188)
assert data.itemImport.cols("i000009") == (21, 0, 180)
assert data.itemImport.cols("i00000a") == (117, 0, 175)
assert data.itemStatus.count("s000000") == 0
assert data.itemStatus.count("s000001") == 0
assert data.itemStatus.count("s000002") == 0
assert data.itemStatus.count("s000003") == 0
assert data.itemStatus.count("s000004") == 0
assert data.itemStatus.count("s000005") == 0
assert data.itemStatus.count("s000006") == 0
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
# Compare content
dumpFile = os.path.join(outDir, "projectXML_ReadLegacy10.json")
compFile = os.path.join(refDir, "projectXML_ReadLegacy10.json")
with open(dumpFile, mode="w", encoding="utf-8") as dump:
json.dump(content, dump, indent=2)
assert cmpFiles(dumpFile, compFile)
packedContent = []
mockProject = MockProject()
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
assert status == {
"7031beac91f75": "Started",
"53b69b83cdafc": "Started",
"974e400180a99": "New",
"edca4be2fcaf8": "New",
"e7ded148d6e4a": "1st Draft",
"6a2d6d5f4f401": "Notes",
"636b6aa9b697b": "1st Draft",
"bc0cbd2a407f3": "1st Draft",
"ba8a28a246524": "Finished",
"96b68994dfa3d": "2nd Draft",
"88706ddc78b1b": "1st Draft",
"ae7339df26ded": "1st Draft",
"f6622b4617424": "None",
"f7e2d9f330615": "None",
"14298de4d9524": "Minor",
"bb2c23b3c42cc": "Major",
"15c4492bd5107": "None",
"b3e74dbc1f584": "Main",
"f1471bef9f2ae": "Minor",
"5eaea4e8cdee8": "Major",
"98acd8c76c93a": "None",
"b8136a5a774a0": "New",
}
# Save the project again, which should produce an identical project xml
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
compFile = os.path.join(refDir, "projectXML_ReadLegacy10.nwx")
assert cmpFiles(outFile, compFile)
# END Test testCoreProjectXML_ReadLegacy10
@pytest.mark.core
def testCoreProjectXML_ReadLegacy11(filesDir, fncDir, outDir, refDir, mockRnd):
"""Test reading the version 1.1 XML file format.
"""
refFile = os.path.join(filesDir, "nwProject-1.1.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.1.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION
data = NWProjectData(MockProject())
content = []
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.WAS_LEGACY
assert xmlReader.xmlRoot == "novelWriterXML"
assert xmlReader.xmlVersion == 0x0101
assert xmlReader.appVersion == "0.9.2"
assert xmlReader.hexVersion == "0x000902f0"
# Check loaded data
assert data.name == "Sample Project"
assert data.title == "Sample Project"
assert data.authors == ["Jane Smith", "Jay Doh"]
assert data.saveCount == 5
assert data.autoCount == 10
assert data.editTime == 1000
assert data.doBackup is True
assert data.language is None # Doesn't exist in 1.1
assert data.spellCheck is True
assert data.spellLang is None # Doesn't exist in 1.1
assert data.initCounts == (0, 0)
assert data.currCounts == (0, 0)
assert data.getLastHandle("editor") is None # Dropped by conversion
assert data.getLastHandle("viewer") is None # Dropped by conversion
assert data.getLastHandle("novelTree") is None # Doesn't exist in 1.1
assert data.getLastHandle("outline") is None # Doesn't exist in 1.1
assert data.getTitleFormat("title") == "%title%"
assert data.getTitleFormat("chapter") == "Chapter %ch%: %title%"
assert data.getTitleFormat("unnumbered") == "%title%"
assert data.getTitleFormat("scene") == "Scene %ch%.%sc%: %title%"
assert data.getTitleFormat("section") == ""
assert data.itemStatus.name("s000000") == "New"
assert data.itemStatus.name("s000001") == "Notes"
assert data.itemStatus.name("s000002") == "Started"
assert data.itemStatus.name("s000003") == "1st Draft"
assert data.itemStatus.name("s000004") == "2nd Draft"
assert data.itemStatus.name("s000005") == "3rd Draft"
assert data.itemStatus.name("s000006") == "Finished"
assert data.itemImport.name("i000007") == "None"
assert data.itemImport.name("i000008") == "Minor"
assert data.itemImport.name("i000009") == "Major"
assert data.itemImport.name("i00000a") == "Main"
assert data.itemStatus.cols("s000000") == (100, 100, 100)
assert data.itemStatus.cols("s000001") == (200, 50, 0)
assert data.itemStatus.cols("s000002") == (182, 60, 0)
assert data.itemStatus.cols("s000003") == (193, 129, 0)
assert data.itemStatus.cols("s000004") == (193, 129, 0)
assert data.itemStatus.cols("s000005") == (193, 129, 0)
assert data.itemStatus.cols("s000006") == (58, 180, 58)
assert data.itemImport.cols("i000007") == (100, 100, 100)
assert data.itemImport.cols("i000008") == (0, 122, 188)
assert data.itemImport.cols("i000009") == (21, 0, 180)
assert data.itemImport.cols("i00000a") == (117, 0, 175)
assert data.itemStatus.count("s000000") == 0
assert data.itemStatus.count("s000001") == 0
assert data.itemStatus.count("s000002") == 0
assert data.itemStatus.count("s000003") == 0
assert data.itemStatus.count("s000004") == 0
assert data.itemStatus.count("s000005") == 0
assert data.itemStatus.count("s000006") == 0
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
# Compare content
dumpFile = os.path.join(outDir, "projectXML_ReadLegacy11.json")
compFile = os.path.join(refDir, "projectXML_ReadLegacy11.json")
with open(dumpFile, mode="w", encoding="utf-8") as dump:
json.dump(content, dump, indent=2)
assert cmpFiles(dumpFile, compFile)
packedContent = []
mockProject = MockProject()
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
assert status == {
"7031beac91f75": "Started",
"53b69b83cdafc": "Started",
"974e400180a99": "New",
"edca4be2fcaf8": "New",
"e7ded148d6e4a": "1st Draft",
"6a2d6d5f4f401": "Notes",
"636b6aa9b697b": "1st Draft",
"bc0cbd2a407f3": "1st Draft",
"ba8a28a246524": "Finished",
"96b68994dfa3d": "2nd Draft",
"88706ddc78b1b": "1st Draft",
"ae7339df26ded": "1st Draft",
"f6622b4617424": "None",
"f7e2d9f330615": "None",
"14298de4d9524": "Minor",
"bb2c23b3c42cc": "Major",
"15c4492bd5107": "None",
"b3e74dbc1f584": "Main",
"f1471bef9f2ae": "Minor",
"5eaea4e8cdee8": "Major",
"98acd8c76c93a": "None",
"b8136a5a774a0": "New",
}
# Save the project again, which should produce an identical project xml
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
compFile = os.path.join(refDir, "projectXML_ReadLegacy11.nwx")
assert cmpFiles(outFile, compFile)
# END Test testCoreProjectXML_ReadLegacy11
@pytest.mark.core
def testCoreProjectXML_ReadLegacy12(filesDir, fncDir, outDir, refDir, mockRnd):
"""Test reading the version 1.2 XML file format.
"""
refFile = os.path.join(filesDir, "nwProject-1.2.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.2.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION
data = NWProjectData(MockProject())
content = []
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.WAS_LEGACY
assert xmlReader.xmlRoot == "novelWriterXML"
assert xmlReader.xmlVersion == 0x0102
assert xmlReader.appVersion == "1.4.2"
assert xmlReader.hexVersion == "0x010402f0"
# Check loaded data
assert data.name == "Sample Project"
assert data.title == "Sample Project"
assert data.authors == ["Jane Smith", "Jay Doh"]
assert data.saveCount == 5
assert data.autoCount == 10
assert data.editTime == 1000
assert data.doBackup is True
assert data.language == "en_GB"
assert data.spellCheck is True
assert data.spellLang == "en_GB"
assert data.initCounts == (840, 376)
assert data.currCounts == (840, 376)
assert data.getLastHandle("editor") is None # Dropped by conversion
assert data.getLastHandle("viewer") is None # Dropped by conversion
assert data.getLastHandle("novelTree") is None # Doesn't exist in 1.2
assert data.getLastHandle("outline") is None # Doesn't exist in 1.2
assert data.getTitleFormat("title") == "%title%"
assert data.getTitleFormat("chapter") == "Chapter %chw%: %title%"
assert data.getTitleFormat("unnumbered") == "%title%"
assert data.getTitleFormat("scene") == "Scene %ch%.%sc%: %title%"
assert data.getTitleFormat("section") == ""
assert data.itemStatus.name("s000000") == "New"
assert data.itemStatus.name("s000001") == "Notes"
assert data.itemStatus.name("s000002") == "Started"
assert data.itemStatus.name("s000003") == "1st Draft"
assert data.itemStatus.name("s000004") == "2nd Draft"
assert data.itemStatus.name("s000005") == "3rd Draft"
assert data.itemStatus.name("s000006") == "Finished"
assert data.itemImport.name("i000007") == "None"
assert data.itemImport.name("i000008") == "Minor"
assert data.itemImport.name("i000009") == "Major"
assert data.itemImport.name("i00000a") == "Main"
assert data.itemStatus.cols("s000000") == (100, 100, 100)
assert data.itemStatus.cols("s000001") == (200, 50, 0)
assert data.itemStatus.cols("s000002") == (182, 60, 0)
assert data.itemStatus.cols("s000003") == (193, 129, 0)
assert data.itemStatus.cols("s000004") == (193, 129, 0)
assert data.itemStatus.cols("s000005") == (193, 129, 0)
assert data.itemStatus.cols("s000006") == (58, 180, 58)
assert data.itemImport.cols("i000007") == (100, 100, 100)
assert data.itemImport.cols("i000008") == (0, 122, 188)
assert data.itemImport.cols("i000009") == (21, 0, 180)
assert data.itemImport.cols("i00000a") == (117, 0, 175)
assert data.itemStatus.count("s000000") == 0
assert data.itemStatus.count("s000001") == 0
assert data.itemStatus.count("s000002") == 0
assert data.itemStatus.count("s000003") == 0
assert data.itemStatus.count("s000004") == 0
assert data.itemStatus.count("s000005") == 0
assert data.itemStatus.count("s000006") == 0
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
# Compare content
dumpFile = os.path.join(outDir, "projectXML_ReadLegacy12.json")
compFile = os.path.join(refDir, "projectXML_ReadLegacy12.json")
with open(dumpFile, mode="w", encoding="utf-8") as dump:
json.dump(content, dump, indent=2)
assert cmpFiles(dumpFile, compFile)
packedContent = []
mockProject = MockProject()
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
assert status == {
"7031beac91f75": "Started",
"53b69b83cdafc": "Started",
"974e400180a99": "New",
"edca4be2fcaf8": "New",
"e7ded148d6e4a": "1st Draft",
"6a2d6d5f4f401": "Notes",
"636b6aa9b697b": "1st Draft",
"bc0cbd2a407f3": "1st Draft",
"ba8a28a246524": "New",
"96b68994dfa3d": "2nd Draft",
"88706ddc78b1b": "1st Draft",
"ae7339df26ded": "1st Draft",
"f6622b4617424": "None",
"f7e2d9f330615": "None",
"14298de4d9524": "Minor",
"bb2c23b3c42cc": "Major",
"15c4492bd5107": "None",
"b3e74dbc1f584": "Main",
"f1471bef9f2ae": "Minor",
"5eaea4e8cdee8": "Major",
"6827118336ac1": "New", # Is now treated as novel-like
"ae9bf3c3ea159": "New", # Is now treated as novel-like
"8a5deb88c0e97": "1st Draft",
"98acd8c76c93a": "None",
"b8136a5a774a0": "New",
}
# Save the project again, which should produce an identical project xml
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
compFile = os.path.join(refDir, "projectXML_ReadLegacy12.nwx")
assert cmpFiles(outFile, compFile)
# END Test testCoreProjectXML_ReadLegacy12
@pytest.mark.core
def testCoreProjectXML_ReadLegacy13(filesDir, fncDir, outDir, refDir, mockRnd):
"""Test reading the version 1.3 XML file format.
"""
refFile = os.path.join(filesDir, "nwProject-1.3.nwx")
xmlFile = os.path.join(fncDir, "nwProject-1.3.nwx")
outFile = os.path.join(fncDir, "nwProject.nwx")
shutil.copy(refFile, xmlFile)
xmlReader = ProjectXMLReader(xmlFile)
assert xmlReader.state == XMLReadState.NO_ACTION
data = NWProjectData(MockProject())
content = []
assert xmlReader.read(data, content) is True
assert xmlReader.state == XMLReadState.WAS_LEGACY
assert xmlReader.xmlRoot == "novelWriterXML"
assert xmlReader.xmlVersion == 0x0103
assert xmlReader.appVersion == "1.6.6"
assert xmlReader.hexVersion == "0x010606f0"
# Check loaded data
assert data.name == "Sample Project"
assert data.title == "Sample Project"
assert data.authors == ["Jane Smith", "Jay Doh"]
assert data.saveCount == 5
assert data.autoCount == 10
assert data.editTime == 1000
assert data.doBackup is True
assert data.language == "en_GB"
assert data.spellCheck is True
assert data.spellLang == "en_GB"
assert data.initCounts == (830, 376)
assert data.currCounts == (830, 376)
assert data.getLastHandle("editor") is None # Dropped by conversion
assert data.getLastHandle("viewer") is None # Dropped by conversion
assert data.getLastHandle("novelTree") is None # Doesn't exist in 1.3
assert data.getLastHandle("outline") is None # Doesn't exist in 1.3
assert data.getTitleFormat("title") == "%title%"
assert data.getTitleFormat("chapter") == "Chapter %chw%: %title%"
assert data.getTitleFormat("unnumbered") == "%title%"
assert data.getTitleFormat("scene") == "Scene %ch%.%sc%: %title%"
assert data.getTitleFormat("section") == ""
assert data.itemStatus.name("s000000") == "New"
assert data.itemStatus.name("s000001") == "Notes"
assert data.itemStatus.name("s000002") == "Started"
assert data.itemStatus.name("s000003") == "1st Draft"
assert data.itemStatus.name("s000004") == "2nd Draft"
assert data.itemStatus.name("s000005") == "3rd Draft"
assert data.itemStatus.name("s000006") == "Finished"
assert data.itemImport.name("i000007") == "None"
assert data.itemImport.name("i000008") == "Minor"
assert data.itemImport.name("i000009") == "Major"
assert data.itemImport.name("i00000a") == "Main"
assert data.itemStatus.cols("s000000") == (100, 100, 100)
assert data.itemStatus.cols("s000001") == (200, 50, 0)
assert data.itemStatus.cols("s000002") == (182, 60, 0)
assert data.itemStatus.cols("s000003") == (193, 129, 0)
assert data.itemStatus.cols("s000004") == (193, 129, 0)
assert data.itemStatus.cols("s000005") == (193, 129, 0)
assert data.itemStatus.cols("s000006") == (58, 180, 58)
assert data.itemImport.cols("i000007") == (100, 100, 100)
assert data.itemImport.cols("i000008") == (0, 122, 188)
assert data.itemImport.cols("i000009") == (21, 0, 180)
assert data.itemImport.cols("i00000a") == (117, 0, 175)
assert data.itemStatus.count("s000000") == 0
assert data.itemStatus.count("s000001") == 0
assert data.itemStatus.count("s000002") == 0
assert data.itemStatus.count("s000003") == 0
assert data.itemStatus.count("s000004") == 0
assert data.itemStatus.count("s000005") == 0
assert data.itemStatus.count("s000006") == 0
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
# Compare content
dumpFile = os.path.join(outDir, "projectXML_ReadLegacy13.json")
compFile = os.path.join(refDir, "projectXML_ReadLegacy13.json")
with open(dumpFile, mode="w", encoding="utf-8") as dump:
json.dump(content, dump, indent=2)
assert cmpFiles(dumpFile, compFile)
packedContent = []
mockProject = MockProject()
mockProject.__setattr__("data", data)
status = {}
for entry in content:
item = NWItem(mockProject)
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
packedContent.append(item.pack())
assert status == {
"7031beac91f75": "Started",
"53b69b83cdafc": "Started",
"974e400180a99": "New",
"edca4be2fcaf8": "New",
"e7ded148d6e4a": "1st Draft",
"6a2d6d5f4f401": "Notes",
"636b6aa9b697b": "1st Draft",
"bc0cbd2a407f3": "1st Draft",
"ba8a28a246524": "New",
"96b68994dfa3d": "2nd Draft",
"88706ddc78b1b": "1st Draft",
"ae7339df26ded": "1st Draft",
"f6622b4617424": "None",
"f7e2d9f330615": "None",
"14298de4d9524": "Minor",
"bb2c23b3c42cc": "Major",
"15c4492bd5107": "None",
"b3e74dbc1f584": "Main",
"f1471bef9f2ae": "Minor",
"5eaea4e8cdee8": "Major",
"6827118336ac1": "New", # Is now treated as novel-like
"ae9bf3c3ea159": "New", # Is now treated as novel-like
"8a5deb88c0e97": "1st Draft",
"98acd8c76c93a": "None",
"b8136a5a774a0": "New",
}
# Save the project again, which should produce an identical project xml
timeStamp = int(datetime.fromisoformat(xmlReader.timeStamp).timestamp())
xmlWriter = ProjectXMLWriter(fncDir)
assert xmlWriter.write(data, packedContent, timeStamp, 1000) is True
compFile = os.path.join(refDir, "projectXML_ReadLegacy13.nwx")
assert cmpFiles(outFile, compFile)
# END Test testCoreProjectXML_ReadLegacy13