Merge branch 'main' into features/footnotes

This commit is contained in:
Veronica Berglyd Olsen
2024-04-14 22:17:23 +02:00
120 changed files with 5019 additions and 4672 deletions
+12 -12
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="3" timeStamp="2022-11-07 13:00:48">
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="4" timeStamp="2022-11-07 13:00:48">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="5" autoCount="10" editTime="1000">
<name>Sample Project</name>
<author>Jane Smith</author>
@@ -20,19 +20,19 @@
<entry key="C">D</entry>
</autoReplace>
<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>
<entry key="sf12341" count="4" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="sf24ce6" count="2" red="200" green="50" blue="0" shape="SQUARE">Notes</entry>
<entry key="sc24b8f" count="3" red="182" green="60" blue="0" shape="SQUARE">Started</entry>
<entry key="s90e6c9" count="7" red="193" green="129" blue="0" shape="SQUARE">1st Draft</entry>
<entry key="sd51c5b" count="0" red="193" green="129" blue="0" shape="SQUARE">2nd Draft</entry>
<entry key="s8ae72a" count="0" red="193" green="129" blue="0" shape="SQUARE">3rd Draft</entry>
<entry key="s78ea90" count="1" red="58" green="180" blue="58" shape="SQUARE">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>
<entry key="ia857f0" count="5" red="100" green="100" blue="100" shape="SQUARE">None</entry>
<entry key="icfb3a5" count="2" red="0" green="122" blue="188" shape="SQUARE">Minor</entry>
<entry key="i2d7a54" count="2" red="21" green="0" blue="180" shape="SQUARE">Major</entry>
<entry key="i56be10" count="1" red="117" green="0" blue="175" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="27" novelWords="954" notesWords="409">
+1 -1
View File
@@ -75,7 +75,7 @@ class MockStatusBar:
class MockTheme:
def __init__(self):
self.baseIconHeight = 10
self.baseIconHeight = 20
return
def getPixmap(self, *a):
+1 -1
View File
@@ -1,5 +1,5 @@
[Meta]
timestamp = 2024-03-25 11:57:35
timestamp = 2024-04-13 18:57:38
[Main]
theme = default
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3a4" hexVersion="0x020300a4" fileVersion="1.5" fileRevision="2" timeStamp="2024-02-08 21:34:07">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:34:16">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="1" autoCount="1" editTime="0">
<name>New Project</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="7" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="7" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="5" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="5" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="12" novelWords="10" notesWords="6">
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3a1" hexVersion="0x020300a1" fileVersion="1.5" fileRevision="2" timeStamp="2024-01-26 22:50:57">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:34:16">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="1" autoCount="1" editTime="0">
<name>New Project</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="6" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="6" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="10" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="10" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="16" novelWords="9" notesWords="0">
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3a1" hexVersion="0x020300a1" fileVersion="1.5" fileRevision="2" timeStamp="2024-01-26 22:53:40">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:34:16">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="1" autoCount="1" editTime="0">
<name>New Project</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="15" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="15" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="3" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="3" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="18" novelWords="26" notesWords="0">
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3b1" hexVersion="0x020300b1" fileVersion="1.5" fileRevision="2" timeStamp="2024-02-20 12:52:16">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:34:16">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="1" autoCount="0" editTime="0">
<name>Test Project A</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="15" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="15" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="7" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="7" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="22" novelWords="0" notesWords="0">
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3b1" hexVersion="0x020300b1" fileVersion="1.5" fileRevision="2" timeStamp="2024-02-20 12:52:16">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:34:16">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="1" autoCount="0" editTime="0">
<name>Test Project B</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="9" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="9" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="7" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="7" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="16" novelWords="0" notesWords="0">
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3a1" hexVersion="0x020300a1" fileVersion="1.5" fileRevision="2" timeStamp="2024-01-26 22:48:13">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:31:18">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="3" autoCount="2" editTime="3">
<name>New Project</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="5" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="5" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="6" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="6" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="11" novelWords="142" notesWords="27">
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.3a1" hexVersion="0x020300a1" fileVersion="1.5" fileRevision="2" timeStamp="2024-01-26 22:45:36">
<novelWriterXML appVersion="2.4rc1" hexVersion="0x020400c1" fileVersion="1.5" fileRevision="4" timeStamp="2024-04-09 22:31:14">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="2" autoCount="1" editTime="0">
<name>New Project</name>
<author>Jane Doe</author>
@@ -16,16 +16,16 @@
</lastHandle>
<autoReplace />
<status>
<entry key="s000000" count="5" red="100" green="100" blue="100">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0">Finished</entry>
<entry key="s000000" count="5" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Note</entry>
<entry key="s000002" count="0" red="200" green="150" blue="0" shape="SQUARE">Draft</entry>
<entry key="s000003" count="0" red="50" green="200" blue="0" shape="SQUARE">Finished</entry>
</status>
<importance>
<entry key="i000004" count="3" red="100" green="100" blue="100">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0">Main</entry>
<entry key="i000004" count="3" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="i000005" count="0" red="200" green="50" blue="0" shape="SQUARE">Minor</entry>
<entry key="i000006" count="0" red="200" green="150" blue="0" shape="SQUARE">Major</entry>
<entry key="i000007" count="0" red="50" green="200" blue="0" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="8" novelWords="9" notesWords="0">
+12 -12
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="3" timeStamp="2020-05-28 09:59:15">
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="4" timeStamp="2020-05-28 09:59:15">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="0" autoCount="0" editTime="1000">
<name>Sample Project</name>
<author>Jay Doh</author>
@@ -20,19 +20,19 @@
<entry key="C">D</entry>
</autoReplace>
<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>
<entry key="s000000" count="0" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0" shape="SQUARE">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0" shape="SQUARE">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0" shape="SQUARE">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0" shape="SQUARE">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58" shape="SQUARE">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>
<entry key="i000007" count="0" red="100" green="100" blue="100" shape="SQUARE">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188" shape="SQUARE">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180" shape="SQUARE">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="22" novelWords="0" notesWords="0">
+12 -12
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="3" timeStamp="2020-06-26 21:20:24">
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="4" timeStamp="2020-06-26 21:20:24">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="5" autoCount="10" editTime="1000">
<name>Sample Project</name>
<author>Jay Doh</author>
@@ -20,19 +20,19 @@
<entry key="C">D</entry>
</autoReplace>
<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>
<entry key="s000000" count="0" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0" shape="SQUARE">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0" shape="SQUARE">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0" shape="SQUARE">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0" shape="SQUARE">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58" shape="SQUARE">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>
<entry key="i000007" count="0" red="100" green="100" blue="100" shape="SQUARE">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188" shape="SQUARE">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180" shape="SQUARE">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="22" novelWords="0" notesWords="0">
+12 -12
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="3" timeStamp="2021-08-30 23:33:44">
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="4" timeStamp="2021-08-30 23:33:44">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="5" autoCount="10" editTime="1000">
<name>Sample Project</name>
<author>Jay Doh</author>
@@ -20,19 +20,19 @@
<entry key="C">D</entry>
</autoReplace>
<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>
<entry key="s000000" count="0" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0" shape="SQUARE">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0" shape="SQUARE">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0" shape="SQUARE">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0" shape="SQUARE">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58" shape="SQUARE">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>
<entry key="i000007" count="0" red="100" green="100" blue="100" shape="SQUARE">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188" shape="SQUARE">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180" shape="SQUARE">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="25" novelWords="840" notesWords="376">
+12 -12
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="3" timeStamp="2022-10-25 18:26:15">
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="4" timeStamp="2022-10-25 18:26:15">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="5" autoCount="10" editTime="1000">
<name>Sample Project</name>
<author>Jay Doh</author>
@@ -20,19 +20,19 @@
<entry key="C">D</entry>
</autoReplace>
<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>
<entry key="s000000" count="0" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="s000001" count="0" red="200" green="50" blue="0" shape="SQUARE">Notes</entry>
<entry key="s000002" count="0" red="182" green="60" blue="0" shape="SQUARE">Started</entry>
<entry key="s000003" count="0" red="193" green="129" blue="0" shape="SQUARE">1st Draft</entry>
<entry key="s000004" count="0" red="193" green="129" blue="0" shape="SQUARE">2nd Draft</entry>
<entry key="s000005" count="0" red="193" green="129" blue="0" shape="SQUARE">3rd Draft</entry>
<entry key="s000006" count="0" red="58" green="180" blue="58" shape="SQUARE">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>
<entry key="i000007" count="0" red="100" green="100" blue="100" shape="SQUARE">None</entry>
<entry key="i000008" count="0" red="0" green="122" blue="188" shape="SQUARE">Minor</entry>
<entry key="i000009" count="0" red="21" green="0" blue="180" shape="SQUARE">Major</entry>
<entry key="i00000a" count="0" red="117" green="0" blue="175" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="25" novelWords="830" notesWords="376">
+12 -12
View File
@@ -1,5 +1,5 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="3" timeStamp="2022-10-15 12:12:59">
<novelWriterXML appVersion="2.0-rc1" hexVersion="0x020000c1" fileVersion="1.5" fileRevision="4" timeStamp="2022-10-15 12:12:59">
<project id="d0f3fe10-c6e6-4310-8bfd-181eb4224eed" saveCount="5" autoCount="10" editTime="1000">
<name>Sample Project</name>
<author>Jay Doh</author>
@@ -20,19 +20,19 @@
<entry key="C">D</entry>
</autoReplace>
<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>
<entry key="sf12341" count="4" red="100" green="100" blue="100" shape="SQUARE">New</entry>
<entry key="sf24ce6" count="2" red="200" green="50" blue="0" shape="SQUARE">Notes</entry>
<entry key="sc24b8f" count="3" red="182" green="60" blue="0" shape="SQUARE">Started</entry>
<entry key="s90e6c9" count="7" red="193" green="129" blue="0" shape="SQUARE">1st Draft</entry>
<entry key="sd51c5b" count="0" red="193" green="129" blue="0" shape="SQUARE">2nd Draft</entry>
<entry key="s8ae72a" count="0" red="193" green="129" blue="0" shape="SQUARE">3rd Draft</entry>
<entry key="s78ea90" count="1" red="58" green="180" blue="58" shape="SQUARE">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>
<entry key="ia857f0" count="5" red="100" green="100" blue="100" shape="SQUARE">None</entry>
<entry key="icfb3a5" count="2" red="0" green="122" blue="188" shape="SQUARE">Minor</entry>
<entry key="i2d7a54" count="2" red="21" green="0" blue="180" shape="SQUARE">Major</entry>
<entry key="i56be10" count="1" red="117" green="0" blue="175" shape="SQUARE">Main</entry>
</importance>
</settings>
<content items="27" novelWords="954" notesWords="409">
+3
View File
@@ -200,6 +200,9 @@ def testBaseConfig_Methods(fncPath):
tstConf = Config()
tstConf.initConfig(confPath=fncPath, dataPath=fncPath)
# Home Path
assert tstConf.homePath() == Path.home().absolute()
# Data Path
assert tstConf.dataPath() == fncPath
assert tstConf.dataPath("stuff") == fncPath / "stuff"
+6 -5
View File
@@ -27,6 +27,7 @@ import shutil
from pathlib import Path
from novelwriter import CONFIG
from tools import C, buildTestProject
from mocked import causeOSError
@@ -58,7 +59,7 @@ def testCoreBuildSettings_ClassAttributes(fncPath: Path):
build.setName("Test Build")
assert build.name == "Test Build"
# Only valid UUIDs are accpeted, anything else generates a new UUID
# Only valid UUIDs are accepted, anything else generates a new UUID
build.setBuildID("5cf45d24-f496-42c9-8733-529a9e52a62b")
assert build.buildID == "5cf45d24-f496-42c9-8733-529a9e52a62b"
@@ -72,14 +73,14 @@ def testCoreBuildSettings_ClassAttributes(fncPath: Path):
# Last path must be valid, if not it defaults to $HOME
build.setLastPath("/path/to/nowhere")
assert build.lastPath == Path.home()
assert build.lastPath == CONFIG.homePath()
build.setLastPath(None)
assert build.lastPath == Path.home()
assert build.lastPath == CONFIG.homePath()
(fncPath / "test.txt").write_text("foobar")
build.setLastPath(fncPath / "test.txt") # Can't be a file
assert build.lastPath == Path.home()
assert build.lastPath == CONFIG.homePath()
build.setLastPath(fncPath)
assert build.lastPath == fncPath
@@ -93,7 +94,7 @@ def testCoreBuildSettings_ClassAttributes(fncPath: Path):
build.setLastPath(testDir)
assert build.lastPath == testDir
testDir.rmdir()
assert build.lastPath == Path.home()
assert build.lastPath == CONFIG.homePath()
# Last build name
build.setLastBuildName(None) # type: ignore
+2 -2
View File
@@ -553,8 +553,8 @@ def testCoreItem_ClassDefaults(mockGUI):
def testCoreItem_PackUnpack(mockGUI, caplog, mockRnd):
"""Test packing and unpacking entries for the NWItem class."""
project = NWProject()
project.data.itemStatus.write(None, "New", (100, 100, 100))
project.data.itemImport.write(None, "New", (100, 100, 100))
project.data.itemStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
project.data.itemImport.add(None, "New", (100, 100, 100), "SQUARE", 0)
# Invalid
item = NWItem(project, "0000000000000")
-109
View File
@@ -400,115 +400,6 @@ def testCoreProject_AccessItems(mockGUI, fncPath, mockRnd):
# END Test testCoreProject_AccessItems
@pytest.mark.core
def testCoreProject_StatusImport(mockGUI, fncPath, mockRnd):
"""Test the status and importance flag handling."""
project = NWProject()
mockRnd.reset()
buildTestProject(project, fncPath)
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
# Change Status
# =============
project.tree[C.hNovelRoot].setStatus(statusKeys[3]) # type: ignore
project.tree[C.hPlotRoot].setStatus(statusKeys[2]) # type: ignore
project.tree[C.hCharRoot].setStatus(statusKeys[1]) # type: ignore
project.tree[C.hWorldRoot].setStatus(statusKeys[3]) # type: ignore
assert project.tree[C.hNovelRoot].itemStatus == statusKeys[3] # type: ignore
assert project.tree[C.hPlotRoot].itemStatus == statusKeys[2] # type: ignore
assert project.tree[C.hCharRoot].itemStatus == statusKeys[1] # type: ignore
assert project.tree[C.hWorldRoot].itemStatus == statusKeys[3] # type: ignore
newList = [
{"key": statusKeys[0], "name": "New", "cols": (1, 1, 1)},
{"key": statusKeys[1], "name": "Draft", "cols": (2, 2, 2)}, # These are swapped
{"key": statusKeys[2], "name": "Note", "cols": (3, 3, 3)}, # These are swapped
{"key": statusKeys[3], "name": "Edited", "cols": (4, 4, 4)}, # Renamed
{"key": None, "name": "Finished", "cols": (5, 5, 5)}, # New, reused name
]
assert project.setStatusColours(None, None) is False # type: ignore
assert project.setStatusColours([], []) is False
assert project.setStatusColours(newList, []) is True
assert project.data.itemStatus.name(statusKeys[0]) == "New"
assert project.data.itemStatus.name(statusKeys[1]) == "Draft"
assert project.data.itemStatus.name(statusKeys[2]) == "Note"
assert project.data.itemStatus.name(statusKeys[3]) == "Edited"
assert project.data.itemStatus.cols(statusKeys[0]) == (1, 1, 1)
assert project.data.itemStatus.cols(statusKeys[1]) == (2, 2, 2)
assert project.data.itemStatus.cols(statusKeys[2]) == (3, 3, 3)
assert project.data.itemStatus.cols(statusKeys[3]) == (4, 4, 4)
# Check the new entry
lastKey = project.data.itemStatus.check("s000010")
assert lastKey == "s000010"
assert project.data.itemStatus.name(lastKey) == "Finished"
assert project.data.itemStatus.cols(lastKey) == (5, 5, 5)
# Delete last entry
assert project.setStatusColours([], [lastKey]) is True
assert project.data.itemStatus.name(lastKey) == "New"
# Change Importance
# =================
fHandle = project.newFile("Jane Doe", C.hCharRoot)
project.tree[fHandle].setImport(importKeys[3]) # type: ignore
assert project.tree[fHandle].itemImport == importKeys[3] # type: ignore
newList = [
{"key": importKeys[0], "name": "New", "cols": (1, 1, 1)},
{"key": importKeys[1], "name": "Minor", "cols": (2, 2, 2)},
{"key": importKeys[2], "name": "Major", "cols": (3, 3, 3)},
{"key": importKeys[3], "name": "Min", "cols": (4, 4, 4)},
{"key": None, "name": "Max", "cols": (5, 5, 5)},
]
assert project.setImportColours(None, None) is False # type: ignore
assert project.setImportColours([], []) is False
assert project.setImportColours(newList, []) is True
assert project.data.itemImport.name(importKeys[0]) == "New"
assert project.data.itemImport.name(importKeys[1]) == "Minor"
assert project.data.itemImport.name(importKeys[2]) == "Major"
assert project.data.itemImport.name(importKeys[3]) == "Min"
assert project.data.itemImport.cols(importKeys[0]) == (1, 1, 1)
assert project.data.itemImport.cols(importKeys[1]) == (2, 2, 2)
assert project.data.itemImport.cols(importKeys[2]) == (3, 3, 3)
assert project.data.itemImport.cols(importKeys[3]) == (4, 4, 4)
# Check the new entry
lastKey = project.data.itemImport.check("i000012")
assert lastKey == "i000012"
assert project.data.itemImport.name(lastKey) == "Max"
assert project.data.itemImport.cols(lastKey) == (5, 5, 5)
# Delete last entry
assert project.setImportColours([], [lastKey]) is True
assert project.data.itemImport.name(lastKey) == "New"
# Delete Status/Import
# ====================
project.data.itemStatus.resetCounts()
for key in list(project.data.itemStatus.keys()):
assert project.data.itemStatus.remove(key) is True
project.data.itemImport.resetCounts()
for key in list(project.data.itemImport.keys()):
assert project.data.itemImport.remove(key) is True
assert len(project.data.itemStatus) == 0
assert len(project.data.itemImport) == 0
assert project.saveProject() is True
project.closeProject()
# END Test testCoreProject_StatusImport
@pytest.mark.core
def testCoreProject_Methods(monkeypatch, mockGUI, fncPath, mockRnd):
"""Test other project class methods and functions."""
+284 -204
View File
@@ -27,9 +27,12 @@ from shutil import copyfile
from datetime import datetime
from novelwriter.constants import nwFiles
from novelwriter.enum import nwStatusShape
from tools import cmpFiles, writeFile
from mocked import causeOSError
from PyQt5.QtGui import QColor
from novelwriter.core.item import NWItem
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter, XMLReadState
from novelwriter.core.projectdata import NWProjectData
@@ -131,7 +134,7 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, tstPaths, fncPath):
assert xmlReader.state == XMLReadState.PARSED_OK
assert xmlReader.xmlRoot == "novelWriterXML"
assert xmlReader.xmlVersion == 0x0105
assert xmlReader.xmlRevision == 3
assert xmlReader.xmlRevision == 4
assert xmlReader.appVersion == "2.0-rc1"
assert xmlReader.hexVersion == 0x020000c1
@@ -154,44 +157,57 @@ def testCoreProjectXML_ReadCurrent(monkeypatch, tstPaths, fncPath):
assert data.getLastHandle("novelTree") == "7031beac91f75"
assert data.getLastHandle("outline") == "7031beac91f75"
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.itemStatus["sf12341"].name == "New"
assert data.itemStatus["sf24ce6"].name == "Notes"
assert data.itemStatus["sc24b8f"].name == "Started"
assert data.itemStatus["s90e6c9"].name == "1st Draft"
assert data.itemStatus["sd51c5b"].name == "2nd Draft"
assert data.itemStatus["s8ae72a"].name == "3rd Draft"
assert data.itemStatus["s78ea90"].name == "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.itemImport["ia857f0"].name == "None"
assert data.itemImport["icfb3a5"].name == "Minor"
assert data.itemImport["i2d7a54"].name == "Major"
assert data.itemImport["i56be10"].name == "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.itemStatus["sf12341"].color == QColor(100, 100, 100)
assert data.itemStatus["sf24ce6"].color == QColor(200, 50, 0)
assert data.itemStatus["sc24b8f"].color == QColor(182, 60, 0)
assert data.itemStatus["s90e6c9"].color == QColor(193, 129, 0)
assert data.itemStatus["sd51c5b"].color == QColor(193, 129, 0)
assert data.itemStatus["s8ae72a"].color == QColor(193, 129, 0)
assert data.itemStatus["s78ea90"].color == QColor(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.itemImport["ia857f0"].color == QColor(100, 100, 100)
assert data.itemImport["icfb3a5"].color == QColor(0, 122, 188)
assert data.itemImport["i2d7a54"].color == QColor(21, 0, 180)
assert data.itemImport["i56be10"].color == QColor(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.itemStatus["sf12341"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sf24ce6"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sc24b8f"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s90e6c9"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sd51c5b"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s8ae72a"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s78ea90"].shape == nwStatusShape.SQUARE
assert data.itemImport.count("ia857f0") == 5
assert data.itemImport.count("icfb3a5") == 2
assert data.itemImport.count("i2d7a54") == 2
assert data.itemImport.count("i56be10") == 1
assert data.itemImport["ia857f0"].shape == nwStatusShape.SQUARE
assert data.itemImport["icfb3a5"].shape == nwStatusShape.SQUARE
assert data.itemImport["i2d7a54"].shape == nwStatusShape.SQUARE
assert data.itemImport["i56be10"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sf12341"].count == 4
assert data.itemStatus["sf24ce6"].count == 2
assert data.itemStatus["sc24b8f"].count == 3
assert data.itemStatus["s90e6c9"].count == 7
assert data.itemStatus["sd51c5b"].count == 0
assert data.itemStatus["s8ae72a"].count == 0
assert data.itemStatus["s78ea90"].count == 1
assert data.itemImport["ia857f0"].count == 5
assert data.itemImport["icfb3a5"].count == 2
assert data.itemImport["i2d7a54"].count == 2
assert data.itemImport["i56be10"].count == 1
# Compare content
dumpFile = tstPaths.outDir / "projectXML_ReadCurrent.json"
@@ -272,44 +288,57 @@ def testCoreProjectXML_ReadLegacy10(tstPaths, fncPath, mockRnd):
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.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.itemStatus["s000000"].name == "New"
assert data.itemStatus["s000001"].name == "Notes"
assert data.itemStatus["s000002"].name == "Started"
assert data.itemStatus["s000003"].name == "1st Draft"
assert data.itemStatus["s000004"].name == "2nd Draft"
assert data.itemStatus["s000005"].name == "3rd Draft"
assert data.itemStatus["s000006"].name == "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.itemImport["i000007"].name == "None"
assert data.itemImport["i000008"].name == "Minor"
assert data.itemImport["i000009"].name == "Major"
assert data.itemImport["i00000a"].name == "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.itemStatus["s000000"].color == QColor(100, 100, 100)
assert data.itemStatus["s000001"].color == QColor(200, 50, 0)
assert data.itemStatus["s000002"].color == QColor(182, 60, 0)
assert data.itemStatus["s000003"].color == QColor(193, 129, 0)
assert data.itemStatus["s000004"].color == QColor(193, 129, 0)
assert data.itemStatus["s000005"].color == QColor(193, 129, 0)
assert data.itemStatus["s000006"].color == QColor(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.itemImport["i000007"].color == QColor(100, 100, 100)
assert data.itemImport["i000008"].color == QColor(0, 122, 188)
assert data.itemImport["i000009"].color == QColor(21, 0, 180)
assert data.itemImport["i00000a"].color == QColor(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.itemStatus["s000000"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000001"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000002"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000003"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000004"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000005"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000006"].shape == nwStatusShape.SQUARE
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
assert data.itemImport["i000007"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000008"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000009"].shape == nwStatusShape.SQUARE
assert data.itemImport["i00000a"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000000"].count == 0
assert data.itemStatus["s000001"].count == 0
assert data.itemStatus["s000002"].count == 0
assert data.itemStatus["s000003"].count == 0
assert data.itemStatus["s000004"].count == 0
assert data.itemStatus["s000005"].count == 0
assert data.itemStatus["s000006"].count == 0
assert data.itemImport["i000007"].count == 0
assert data.itemImport["i000008"].count == 0
assert data.itemImport["i000009"].count == 0
assert data.itemImport["i00000a"].count == 0
# Compare content
dumpFile = tstPaths.outDir / "projectXML_ReadLegacy10.json"
@@ -325,7 +354,7 @@ def testCoreProjectXML_ReadLegacy10(tstPaths, fncPath, mockRnd):
for entry in content:
item = NWItem(mockProject, "0000000000000") # type: ignore
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
status[item.itemHandle] = item.getImportStatus()[0]
packedContent.append(item.pack())
assert status == {
@@ -406,44 +435,57 @@ def testCoreProjectXML_ReadLegacy11(tstPaths, fncPath, mockRnd):
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.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.itemStatus["s000000"].name == "New"
assert data.itemStatus["s000001"].name == "Notes"
assert data.itemStatus["s000002"].name == "Started"
assert data.itemStatus["s000003"].name == "1st Draft"
assert data.itemStatus["s000004"].name == "2nd Draft"
assert data.itemStatus["s000005"].name == "3rd Draft"
assert data.itemStatus["s000006"].name == "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.itemImport["i000007"].name == "None"
assert data.itemImport["i000008"].name == "Minor"
assert data.itemImport["i000009"].name == "Major"
assert data.itemImport["i00000a"].name == "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.itemStatus["s000000"].color == QColor(100, 100, 100)
assert data.itemStatus["s000001"].color == QColor(200, 50, 0)
assert data.itemStatus["s000002"].color == QColor(182, 60, 0)
assert data.itemStatus["s000003"].color == QColor(193, 129, 0)
assert data.itemStatus["s000004"].color == QColor(193, 129, 0)
assert data.itemStatus["s000005"].color == QColor(193, 129, 0)
assert data.itemStatus["s000006"].color == QColor(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.itemImport["i000007"].color == QColor(100, 100, 100)
assert data.itemImport["i000008"].color == QColor(0, 122, 188)
assert data.itemImport["i000009"].color == QColor(21, 0, 180)
assert data.itemImport["i00000a"].color == QColor(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.itemStatus["s000000"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000001"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000002"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000003"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000004"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000005"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000006"].shape == nwStatusShape.SQUARE
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
assert data.itemImport["i000007"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000008"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000009"].shape == nwStatusShape.SQUARE
assert data.itemImport["i00000a"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000000"].count == 0
assert data.itemStatus["s000001"].count == 0
assert data.itemStatus["s000002"].count == 0
assert data.itemStatus["s000003"].count == 0
assert data.itemStatus["s000004"].count == 0
assert data.itemStatus["s000005"].count == 0
assert data.itemStatus["s000006"].count == 0
assert data.itemImport["i000007"].count == 0
assert data.itemImport["i000008"].count == 0
assert data.itemImport["i000009"].count == 0
assert data.itemImport["i00000a"].count == 0
# Compare content
dumpFile = tstPaths.outDir / "projectXML_ReadLegacy11.json"
@@ -459,7 +501,7 @@ def testCoreProjectXML_ReadLegacy11(tstPaths, fncPath, mockRnd):
for entry in content:
item = NWItem(mockProject, "0000000000000") # type: ignore
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
status[item.itemHandle] = item.getImportStatus()[0]
packedContent.append(item.pack())
assert status == {
@@ -540,44 +582,57 @@ def testCoreProjectXML_ReadLegacy12(tstPaths, fncPath, mockRnd):
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.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.itemStatus["s000000"].name == "New"
assert data.itemStatus["s000001"].name == "Notes"
assert data.itemStatus["s000002"].name == "Started"
assert data.itemStatus["s000003"].name == "1st Draft"
assert data.itemStatus["s000004"].name == "2nd Draft"
assert data.itemStatus["s000005"].name == "3rd Draft"
assert data.itemStatus["s000006"].name == "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.itemImport["i000007"].name == "None"
assert data.itemImport["i000008"].name == "Minor"
assert data.itemImport["i000009"].name == "Major"
assert data.itemImport["i00000a"].name == "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.itemStatus["s000000"].color == QColor(100, 100, 100)
assert data.itemStatus["s000001"].color == QColor(200, 50, 0)
assert data.itemStatus["s000002"].color == QColor(182, 60, 0)
assert data.itemStatus["s000003"].color == QColor(193, 129, 0)
assert data.itemStatus["s000004"].color == QColor(193, 129, 0)
assert data.itemStatus["s000005"].color == QColor(193, 129, 0)
assert data.itemStatus["s000006"].color == QColor(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.itemImport["i000007"].color == QColor(100, 100, 100)
assert data.itemImport["i000008"].color == QColor(0, 122, 188)
assert data.itemImport["i000009"].color == QColor(21, 0, 180)
assert data.itemImport["i00000a"].color == QColor(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.itemStatus["s000000"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000001"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000002"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000003"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000004"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000005"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000006"].shape == nwStatusShape.SQUARE
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
assert data.itemImport["i000007"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000008"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000009"].shape == nwStatusShape.SQUARE
assert data.itemImport["i00000a"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000000"].count == 0
assert data.itemStatus["s000001"].count == 0
assert data.itemStatus["s000002"].count == 0
assert data.itemStatus["s000003"].count == 0
assert data.itemStatus["s000004"].count == 0
assert data.itemStatus["s000005"].count == 0
assert data.itemStatus["s000006"].count == 0
assert data.itemImport["i000007"].count == 0
assert data.itemImport["i000008"].count == 0
assert data.itemImport["i000009"].count == 0
assert data.itemImport["i00000a"].count == 0
# Compare content
dumpFile = tstPaths.outDir / "projectXML_ReadLegacy12.json"
@@ -593,7 +648,7 @@ def testCoreProjectXML_ReadLegacy12(tstPaths, fncPath, mockRnd):
for entry in content:
item = NWItem(mockProject, "0000000000000") # type: ignore
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
status[item.itemHandle] = item.getImportStatus()[0]
packedContent.append(item.pack())
assert status == {
@@ -677,44 +732,57 @@ def testCoreProjectXML_ReadLegacy13(tstPaths, fncPath, mockRnd):
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.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.itemStatus["s000000"].name == "New"
assert data.itemStatus["s000001"].name == "Notes"
assert data.itemStatus["s000002"].name == "Started"
assert data.itemStatus["s000003"].name == "1st Draft"
assert data.itemStatus["s000004"].name == "2nd Draft"
assert data.itemStatus["s000005"].name == "3rd Draft"
assert data.itemStatus["s000006"].name == "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.itemImport["i000007"].name == "None"
assert data.itemImport["i000008"].name == "Minor"
assert data.itemImport["i000009"].name == "Major"
assert data.itemImport["i00000a"].name == "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.itemStatus["s000000"].color == QColor(100, 100, 100)
assert data.itemStatus["s000001"].color == QColor(200, 50, 0)
assert data.itemStatus["s000002"].color == QColor(182, 60, 0)
assert data.itemStatus["s000003"].color == QColor(193, 129, 0)
assert data.itemStatus["s000004"].color == QColor(193, 129, 0)
assert data.itemStatus["s000005"].color == QColor(193, 129, 0)
assert data.itemStatus["s000006"].color == QColor(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.itemImport["i000007"].color == QColor(100, 100, 100)
assert data.itemImport["i000008"].color == QColor(0, 122, 188)
assert data.itemImport["i000009"].color == QColor(21, 0, 180)
assert data.itemImport["i00000a"].color == QColor(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.itemStatus["s000000"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000001"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000002"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000003"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000004"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000005"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000006"].shape == nwStatusShape.SQUARE
assert data.itemImport.count("i000007") == 0
assert data.itemImport.count("i000008") == 0
assert data.itemImport.count("i000009") == 0
assert data.itemImport.count("i00000a") == 0
assert data.itemImport["i000007"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000008"].shape == nwStatusShape.SQUARE
assert data.itemImport["i000009"].shape == nwStatusShape.SQUARE
assert data.itemImport["i00000a"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s000000"].count == 0
assert data.itemStatus["s000001"].count == 0
assert data.itemStatus["s000002"].count == 0
assert data.itemStatus["s000003"].count == 0
assert data.itemStatus["s000004"].count == 0
assert data.itemStatus["s000005"].count == 0
assert data.itemStatus["s000006"].count == 0
assert data.itemImport["i000007"].count == 0
assert data.itemImport["i000008"].count == 0
assert data.itemImport["i000009"].count == 0
assert data.itemImport["i00000a"].count == 0
# Compare content
dumpFile = tstPaths.outDir / "projectXML_ReadLegacy13.json"
@@ -730,7 +798,7 @@ def testCoreProjectXML_ReadLegacy13(tstPaths, fncPath, mockRnd):
for entry in content:
item = NWItem(mockProject, "0000000000000") # type: ignore
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
status[item.itemHandle] = item.getImportStatus()[0]
packedContent.append(item.pack())
assert status == {
@@ -814,44 +882,56 @@ def testCoreProjectXML_ReadLegacy14(tstPaths, fncPath, mockRnd):
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.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.itemStatus["sf12341"].name == "New"
assert data.itemStatus["sf24ce6"].name == "Notes"
assert data.itemStatus["sc24b8f"].name == "Started"
assert data.itemStatus["s90e6c9"].name == "1st Draft"
assert data.itemStatus["sd51c5b"].name == "2nd Draft"
assert data.itemStatus["s8ae72a"].name == "3rd Draft"
assert data.itemStatus["s78ea90"].name == "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.itemImport["ia857f0"].name == "None"
assert data.itemImport["icfb3a5"].name == "Minor"
assert data.itemImport["i2d7a54"].name == "Major"
assert data.itemImport["i56be10"].name == "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.itemStatus["sf12341"].color == QColor(100, 100, 100)
assert data.itemStatus["sf24ce6"].color == QColor(200, 50, 0)
assert data.itemStatus["sc24b8f"].color == QColor(182, 60, 0)
assert data.itemStatus["s90e6c9"].color == QColor(193, 129, 0)
assert data.itemStatus["sd51c5b"].color == QColor(193, 129, 0)
assert data.itemStatus["s8ae72a"].color == QColor(193, 129, 0)
assert data.itemStatus["s78ea90"].color == QColor(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.itemImport["ia857f0"].color == QColor(100, 100, 100)
assert data.itemImport["icfb3a5"].color == QColor(0, 122, 188)
assert data.itemImport["i2d7a54"].color == QColor(21, 0, 180)
assert data.itemImport["i56be10"].color == QColor(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.itemStatus["sf12341"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sf24ce6"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sc24b8f"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s90e6c9"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sd51c5b"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s8ae72a"].shape == nwStatusShape.SQUARE
assert data.itemStatus["s78ea90"].shape == nwStatusShape.SQUARE
assert data.itemImport.count("ia857f0") == 5
assert data.itemImport.count("icfb3a5") == 2
assert data.itemImport.count("i2d7a54") == 2
assert data.itemImport.count("i56be10") == 1
assert data.itemImport["ia857f0"].shape == nwStatusShape.SQUARE
assert data.itemImport["icfb3a5"].shape == nwStatusShape.SQUARE
assert data.itemImport["i2d7a54"].shape == nwStatusShape.SQUARE
assert data.itemImport["i56be10"].shape == nwStatusShape.SQUARE
assert data.itemStatus["sf12341"].count == 4
assert data.itemStatus["sf24ce6"].count == 2
assert data.itemStatus["sc24b8f"].count == 3
assert data.itemStatus["s90e6c9"].count == 7
assert data.itemStatus["sd51c5b"].count == 0
assert data.itemStatus["s8ae72a"].count == 0
assert data.itemStatus["s78ea90"].count == 1
assert data.itemImport["ia857f0"].count == 5
assert data.itemImport["icfb3a5"].count == 2
assert data.itemImport["i2d7a54"].count == 2
assert data.itemImport["i56be10"].count == 1
# Compare content
dumpFile = tstPaths.outDir / "projectXML_ReadLegacy14.json"
@@ -867,7 +947,7 @@ def testCoreProjectXML_ReadLegacy14(tstPaths, fncPath, mockRnd):
for entry in content:
item = NWItem(mockProject, "0000000000000") # type: ignore
item.unpack(entry)
status[item.itemHandle] = item.getImportStatus(incIcon=False)[0]
status[item.itemHandle] = item.getImportStatus()[0]
packedContent.append(item.pack())
assert status == {
+223 -175
View File
@@ -24,24 +24,50 @@ import pytest
from tools import C
from PyQt5.QtGui import QIcon
from PyQt5.QtGui import QColor, QIcon
from novelwriter.core.status import NWStatus
from novelwriter.core.status import NWStatus, StatusEntry, _ShapeCache
from novelwriter.enum import nwStatusShape
statusKeys = [C.sNew, C.sNote, C.sDraft, C.sFinished]
importKeys = [C.iNew, C.iMinor, C.iMajor, C.iMain]
@pytest.mark.core
def testCoreStatus_Internal(mockRnd):
"""Test all the internal functions of the NWStatus class.
"""
def testCoreStatus_StatusEntry():
"""Test the StatusEntry class."""
color = QColor(255, 0, 0)
icon = NWStatus.createIcon(24, color, nwStatusShape.CIRCLE)
entry = StatusEntry("Test", color, nwStatusShape.CIRCLE, icon, 42)
# Check values
assert entry.name == "Test"
assert entry.color is color
assert entry.shape == nwStatusShape.CIRCLE
assert entry.icon is icon
assert entry.count == 42
# Make a copy
other = StatusEntry.duplicate(entry)
assert other is not entry
# Check copy is not the same
assert other.name == "Test"
assert other.color is not color # Not the same object
assert other.color == color # But same colours
assert other.shape == nwStatusShape.CIRCLE
assert other.icon is not icon # Not the same icon, but a copy
assert other.count == 42
# END Test testCoreStatus_StatusEntry
@pytest.mark.core
def testCoreStatus_Internal(mockGUI, mockRnd):
"""Test all the internal functions of the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
nImport = NWStatus(NWStatus.IMPORT)
with pytest.raises(Exception):
NWStatus(999)
# Generate Key
# ============
@@ -49,14 +75,14 @@ def testCoreStatus_Internal(mockRnd):
assert nStatus._newKey() == statusKeys[1]
# Key collision, should move to key 3
nStatus.write(statusKeys[2], "Crash", (0, 0, 0))
nStatus.add(statusKeys[2], "Crash", (0, 0, 0), "SQUARE", 0)
assert nStatus._newKey() == statusKeys[3]
assert nImport._newKey() == importKeys[0]
assert nImport._newKey() == importKeys[1]
# Key collision, should move to key 3
nImport.write(importKeys[2], "Crash", (0, 0, 0))
nImport.add(importKeys[2], "Crash", (0, 0, 0), "SQUARE", 0)
assert nImport._newKey() == importKeys[3]
# Check Key
@@ -82,81 +108,94 @@ def testCoreStatus_Internal(mockRnd):
assert nImport._isKey("i12345F") is False # Not a lower case hex value
assert nImport._isKey("i12345f") is True # Valid hex value
assert nStatus._checkKey(None) == "s000008" # Creates next key
assert nStatus._checkKey("s654321") == "s654321" # Status key accepted
assert nStatus._checkKey("i123456") == "s000009" # Import key not accepted
assert nImport._checkKey(None) == "i00000a" # Creates next key
assert nImport._checkKey("s654321") == "i00000b" # Status key not accepted
assert nImport._checkKey("i123456") == "i123456" # Import key accepted
# END Test testCoreStatus_Internal
@pytest.mark.core
def testCoreStatus_Iterator(mockRnd):
"""Test the iterator functions of the NWStatus class.
"""
def testCoreStatus_Iterator(mockGUI, mockRnd):
"""Test the iterator functions of the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
nStatus.write(None, "New", (100, 100, 100))
nStatus.write(None, "Note", (200, 50, 0))
nStatus.write(None, "Draft", (200, 150, 0))
nStatus.write(None, "Finished", (50, 200, 0))
nStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
nStatus.add(None, "Note", (200, 50, 0), "CIRCLE", 1)
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 2)
nStatus.add(None, "Finished", (50, 200, 0), "CIRCLE", 3)
# Direct access
entry = nStatus[statusKeys[0]]
assert entry["cols"] == (100, 100, 100)
assert entry["name"] == "New"
assert entry["count"] == 0
assert isinstance(entry["icon"], QIcon)
assert entry.color == QColor(100, 100, 100)
assert entry.name == "New"
assert entry.count == 0
assert isinstance(entry.icon, QIcon)
# Iterate
entries = list(nStatus)
assert len(entries) == 4
# Length
assert len(nStatus._store) == 4
assert len(nStatus) == 4
# Keys
assert list(nStatus.keys()) == statusKeys
# Content : Keys
assert [k for k, _ in nStatus.iterItems()] == [
"s000000", "s000001", "s000002", "s000003"
]
# Items
for index, (key, entry) in enumerate(nStatus.items()):
assert key == statusKeys[index]
assert "cols" in entry
assert "name" in entry
assert "count" in entry
assert "icon" in entry
# Content : Names
assert [e.name for _, e in nStatus.iterItems()] == [
"New", "Note", "Draft", "Finished"
]
# Valuse
for entry in nStatus.values():
assert "cols" in entry
assert "name" in entry
assert "count" in entry
assert "icon" in entry
# Content : Colours
assert [e.color for _, e in nStatus.iterItems()] == [
QColor(100, 100, 100), QColor(200, 50, 0), QColor(200, 150, 0), QColor(50, 200, 0)
]
# Content : Shape
assert [e.shape for _, e in nStatus.iterItems()] == [
nwStatusShape.SQUARE, nwStatusShape.CIRCLE, nwStatusShape.SQUARE, nwStatusShape.CIRCLE
]
# Content : Count
assert [e.count for _, e in nStatus.iterItems()] == [0, 1, 2, 3]
# END Test testCoreStatus_Iterator
@pytest.mark.core
def testCoreStatus_Entries(mockRnd):
"""Test all the simple setters for the NWStatus class.
"""
def testCoreStatus_Entries(mockGUI, mockRnd):
"""Test all the simple setters for the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
# Write
# =====
# Add
# ===
# Have a key
nStatus.write(statusKeys[0], "Entry 1", (200, 100, 50))
assert nStatus[statusKeys[0]]["name"] == "Entry 1"
assert nStatus[statusKeys[0]]["cols"] == (200, 100, 50)
# Has a key
nStatus.add(statusKeys[0], "Entry 1", (200, 100, 50), "SQUARE", 0)
assert nStatus[statusKeys[0]].name == "Entry 1"
assert nStatus[statusKeys[0]].color == QColor(200, 100, 50)
assert nStatus[statusKeys[0]].shape == nwStatusShape.SQUARE
# Don't have a key
nStatus.write(None, "Entry 2", (210, 110, 60))
assert nStatus[statusKeys[1]]["name"] == "Entry 2"
assert nStatus[statusKeys[1]]["cols"] == (210, 110, 60)
# Doesn't have a key
nStatus.add(None, "Entry 2", (210, 110, 60), "SQUARE", 0)
assert nStatus[statusKeys[1]].name == "Entry 2"
assert nStatus[statusKeys[1]].color == QColor(210, 110, 60)
assert nStatus[statusKeys[1]].shape == nwStatusShape.SQUARE
# Wrong colour spec
nStatus.write(None, "Entry 3", "what?")
assert nStatus[statusKeys[2]]["name"] == "Entry 3"
assert nStatus[statusKeys[2]]["cols"] == (100, 100, 100)
# Wrong colour spec, unknown shape
nStatus.add(None, "Entry 3", "what?", "", 0) # type: ignore
assert nStatus[statusKeys[2]].name == "Entry 3"
assert nStatus[statusKeys[2]].color == QColor(100, 100, 100)
assert nStatus[statusKeys[2]].shape == nwStatusShape.SQUARE
# Wrong colour count
nStatus.write(None, "Entry 4", (10, 20))
assert nStatus[statusKeys[3]]["name"] == "Entry 4"
assert nStatus[statusKeys[3]]["cols"] == (100, 100, 100)
nStatus.add(None, "Entry 4", (10, 20), "CIRCLE", 0) # type: ignore
assert nStatus[statusKeys[3]].name == "Entry 4"
assert nStatus[statusKeys[3]].color == QColor(100, 100, 100)
assert nStatus[statusKeys[3]].shape == nwStatusShape.CIRCLE
# Check
# =====
@@ -171,29 +210,38 @@ def testCoreStatus_Entries(mockRnd):
# Name Access
# ===========
assert nStatus.name(statusKeys[0]) == "Entry 1"
assert nStatus.name(statusKeys[1]) == "Entry 2"
assert nStatus.name(statusKeys[2]) == "Entry 3"
assert nStatus.name(statusKeys[3]) == "Entry 4"
assert nStatus.name("blablabla") == "Entry 1"
assert nStatus[statusKeys[0]].name == "Entry 1"
assert nStatus[statusKeys[1]].name == "Entry 2"
assert nStatus[statusKeys[2]].name == "Entry 3"
assert nStatus[statusKeys[3]].name == "Entry 4"
assert nStatus["blablabla"].name == "Entry 1"
# Colour Access
# =============
assert nStatus.cols(statusKeys[0]) == (200, 100, 50)
assert nStatus.cols(statusKeys[1]) == (210, 110, 60)
assert nStatus.cols(statusKeys[2]) == (100, 100, 100)
assert nStatus.cols(statusKeys[3]) == (100, 100, 100)
assert nStatus.cols("blablabla") == (200, 100, 50)
assert nStatus[statusKeys[0]].color == QColor(200, 100, 50)
assert nStatus[statusKeys[1]].color == QColor(210, 110, 60)
assert nStatus[statusKeys[2]].color == QColor(100, 100, 100)
assert nStatus[statusKeys[3]].color == QColor(100, 100, 100)
assert nStatus["blablabla"].color == QColor(200, 100, 50)
# Icon Access
# ===========
assert isinstance(nStatus.icon(statusKeys[0]), QIcon)
assert isinstance(nStatus.icon(statusKeys[1]), QIcon)
assert isinstance(nStatus.icon(statusKeys[2]), QIcon)
assert isinstance(nStatus.icon(statusKeys[3]), QIcon)
assert isinstance(nStatus.icon("blablabla"), QIcon)
assert isinstance(nStatus[statusKeys[0]].icon, QIcon)
assert isinstance(nStatus[statusKeys[1]].icon, QIcon)
assert isinstance(nStatus[statusKeys[2]].icon, QIcon)
assert isinstance(nStatus[statusKeys[3]].icon, QIcon)
assert isinstance(nStatus["blablabla"].icon, QIcon)
# Shape Access
# ============
assert nStatus[statusKeys[0]].shape == nwStatusShape.SQUARE
assert nStatus[statusKeys[1]].shape == nwStatusShape.SQUARE
assert nStatus[statusKeys[2]].shape == nwStatusShape.SQUARE
assert nStatus[statusKeys[3]].shape == nwStatusShape.CIRCLE
assert nStatus["blablabla"].shape == nwStatusShape.SQUARE
# Increment and Count Access
# ==========================
@@ -203,50 +251,32 @@ def testCoreStatus_Entries(mockRnd):
for _ in range(n):
nStatus.increment(statusKeys[i])
assert nStatus.count(statusKeys[0]) == countTo[0]
assert nStatus.count(statusKeys[1]) == countTo[1]
assert nStatus.count(statusKeys[2]) == countTo[2]
assert nStatus.count(statusKeys[3]) == countTo[3]
assert nStatus.count("blablabla") == countTo[0]
assert nStatus[statusKeys[0]].count == countTo[0]
assert nStatus[statusKeys[1]].count == countTo[1]
assert nStatus[statusKeys[2]].count == countTo[2]
assert nStatus[statusKeys[3]].count == countTo[3]
assert nStatus["blablabla"].count == countTo[0]
nStatus.resetCounts()
assert nStatus.count(statusKeys[0]) == 0
assert nStatus.count(statusKeys[1]) == 0
assert nStatus.count(statusKeys[2]) == 0
assert nStatus.count(statusKeys[3]) == 0
assert nStatus[statusKeys[0]].count == 0
assert nStatus[statusKeys[1]].count == 0
assert nStatus[statusKeys[2]].count == 0
assert nStatus[statusKeys[3]].count == 0
# Reorder
# =======
# Update
# ======
cOrder = list(nStatus.keys())
assert cOrder == statusKeys
assert list(nStatus._store.keys()) == statusKeys
# Wrong length
assert nStatus.reorder([]) is False
# Reverse
order: list[tuple[str | None, StatusEntry]] = list(nStatus.iterItems())
nStatus.update(list(reversed(order)))
assert list(nStatus._store.keys()) == list(reversed(statusKeys))
# No change
assert nStatus.reorder(cOrder) is False
# Actual reaorder
nOrder = [
statusKeys[0],
statusKeys[2],
statusKeys[1],
statusKeys[3],
]
assert nStatus.reorder(nOrder) is True
assert list(nStatus.keys()) == nOrder
# Add an unknown key
wOrder = nOrder.copy()
wOrder[3] = nStatus._newKey()
assert nStatus.reorder(wOrder) is False
assert list(nStatus.keys()) == nOrder
# Put it back
assert nStatus.reorder(cOrder) is True
assert list(nStatus.keys()) == cOrder
# Restore
nStatus.update(order)
assert list(nStatus._store.keys()) == statusKeys
# Default
# =======
@@ -255,56 +285,41 @@ def testCoreStatus_Entries(mockRnd):
nStatus._default = None
assert nStatus.check("Entry 5") == ""
assert nStatus.name("blablabla") == ""
assert nStatus.cols("blablabla") == (100, 100, 100)
assert nStatus.count("blablabla") == 0
assert isinstance(nStatus.icon("blablabla"), QIcon)
assert nStatus["blablabla"].name == ""
assert nStatus["blablabla"].color == QColor(0, 0, 0)
assert nStatus["blablabla"].shape == nwStatusShape.SQUARE
assert nStatus["blablabla"].icon.isNull()
assert nStatus["blablabla"].count == 0
nStatus._default = default
# Remove
# ======
# This uses update with deleted items
# Non-existing entry
assert nStatus.remove("blablabla") is False
order: list[tuple[str | None, StatusEntry]] = list(nStatus.iterItems())
# Non-zero entry
nStatus.increment(statusKeys[3])
assert nStatus.remove(statusKeys[3]) is False
# Remove Entry 0
nStatus.update([order[1], order[3], order[2]])
assert list(nStatus._store.keys()) == [statusKeys[1], statusKeys[3], statusKeys[2]]
assert nStatus._default == statusKeys[1]
# Delete last entry
nStatus.resetCounts()
lastName = nStatus.name(statusKeys[3])
assert lastName == "Entry 4"
assert nStatus.remove(statusKeys[3]) is True
assert nStatus.check(statusKeys[3]) == nStatus._default
assert nStatus.check(lastName) == nStatus._default
# Delete default entry, Entry 2 is new default
firstName = nStatus.name(nStatus._default)
assert firstName == "Entry 1"
assert nStatus.remove(nStatus._default) is True
assert nStatus.name(firstName) == "Entry 2"
# Remove remaining entries
assert nStatus.remove(statusKeys[1]) is True
assert nStatus.remove(statusKeys[2]) is True
assert len(nStatus) == 0
assert nStatus._default is None
# Remove Entry 1
nStatus.update([order[3], order[2]])
assert list(nStatus._store.keys()) == [statusKeys[3], statusKeys[2]]
assert nStatus._default == statusKeys[3]
# END Test testCoreStatus_Entries
@pytest.mark.core
def testCoreStatus_PackUnpack(mockRnd):
"""Test all the pack/unpack of the NWStatus class.
"""
def testCoreStatus_Pack(mockGUI, mockRnd):
"""Test data packing of the NWStatus class."""
nStatus = NWStatus(NWStatus.STATUS)
nStatus.write(None, "New", (100, 100, 100))
nStatus.write(None, "Note", (200, 50, 0))
nStatus.write(None, "Draft", (200, 150, 0))
nStatus.write(None, "Finished", (50, 200, 0))
nStatus.add(None, "New", (100, 100, 100), "SQUARE", 0)
nStatus.add(None, "Note", (200, 50, 0), "CIRCLE", 0)
nStatus.add(None, "Draft", (200, 150, 0), "SQUARE", 0)
nStatus.add(None, "Finished", (50, 200, 0), "SQUARE", 0)
countTo = [3, 5, 7, 9]
for i, n in enumerate(countTo):
@@ -318,52 +333,85 @@ def testCoreStatus_PackUnpack(mockRnd):
"count": "3",
"red": "100",
"green": "100",
"blue": "100"
"blue": "100",
"shape": "SQUARE",
}),
("Note", {
"key": statusKeys[1],
"count": "5",
"red": "200",
"green": "50",
"blue": "0"
"blue": "0",
"shape": "CIRCLE",
}),
("Draft", {
"key": statusKeys[2],
"count": "7",
"red": "200",
"green": "150",
"blue": "0"
"blue": "0",
"shape": "SQUARE",
}),
("Finished", {
"key": statusKeys[3],
"count": "9",
"red": "50",
"green": "200",
"blue": "0"
"blue": "0",
"shape": "SQUARE",
}),
]
# Unpack
nStatus = NWStatus(NWStatus.STATUS)
nStatus.unpack({
statusKeys[0]: {"label": "New0", "colour": (100, 100, 100), "count": countTo[0]},
statusKeys[1]: {"label": "New1", "colour": (150, 150, 150), "count": countTo[1]},
statusKeys[2]: {"label": "New2", "colour": (200, 200, 200), "count": countTo[2]},
statusKeys[3]: {"label": "New3", "colour": (250, 250, 250), "count": countTo[3]},
})
assert len(nStatus._store) == 4
assert list(nStatus._store.keys()) == statusKeys
assert nStatus._store[statusKeys[0]]["name"] == "New0"
assert nStatus._store[statusKeys[1]]["name"] == "New1"
assert nStatus._store[statusKeys[2]]["name"] == "New2"
assert nStatus._store[statusKeys[3]]["name"] == "New3"
assert nStatus._store[statusKeys[0]]["cols"] == (100, 100, 100)
assert nStatus._store[statusKeys[1]]["cols"] == (150, 150, 150)
assert nStatus._store[statusKeys[2]]["cols"] == (200, 200, 200)
assert nStatus._store[statusKeys[3]]["cols"] == (250, 250, 250)
assert nStatus._store[statusKeys[0]]["count"] == countTo[0]
assert nStatus._store[statusKeys[1]]["count"] == countTo[1]
assert nStatus._store[statusKeys[2]]["count"] == countTo[2]
assert nStatus._store[statusKeys[3]]["count"] == countTo[3]
# END Test testCoreStatus_Pack
# END Test testCoreStatus_PackUnpack
@pytest.mark.core
def testCoreStatus_ShapeCache():
"""Test the _ShapeCache class."""
shapes = _ShapeCache()
# Generate all shapes
square = shapes.getShape(nwStatusShape.SQUARE)
circleQ = shapes.getShape(nwStatusShape.CIRCLE_Q)
circleH = shapes.getShape(nwStatusShape.CIRCLE_H)
circleT = shapes.getShape(nwStatusShape.CIRCLE_T)
circle = shapes.getShape(nwStatusShape.CIRCLE)
triangle = shapes.getShape(nwStatusShape.TRIANGLE)
nabla = shapes.getShape(nwStatusShape.NABLA)
diamond = shapes.getShape(nwStatusShape.DIAMOND)
pentagon = shapes.getShape(nwStatusShape.PENTAGON)
hexagon = shapes.getShape(nwStatusShape.HEXAGON)
star = shapes.getShape(nwStatusShape.STAR)
pacman = shapes.getShape(nwStatusShape.PACMAN)
bars1 = shapes.getShape(nwStatusShape.BARS_1)
bars2 = shapes.getShape(nwStatusShape.BARS_2)
bars3 = shapes.getShape(nwStatusShape.BARS_3)
bars4 = shapes.getShape(nwStatusShape.BARS_4)
block1 = shapes.getShape(nwStatusShape.BLOCK_1)
block2 = shapes.getShape(nwStatusShape.BLOCK_2)
block3 = shapes.getShape(nwStatusShape.BLOCK_3)
block4 = shapes.getShape(nwStatusShape.BLOCK_4)
# Request again should return from cache
assert shapes.getShape(nwStatusShape.SQUARE) is square
assert shapes.getShape(nwStatusShape.CIRCLE_Q) is circleQ
assert shapes.getShape(nwStatusShape.CIRCLE_H) is circleH
assert shapes.getShape(nwStatusShape.CIRCLE_T) is circleT
assert shapes.getShape(nwStatusShape.CIRCLE) is circle
assert shapes.getShape(nwStatusShape.TRIANGLE) is triangle
assert shapes.getShape(nwStatusShape.NABLA) is nabla
assert shapes.getShape(nwStatusShape.DIAMOND) is diamond
assert shapes.getShape(nwStatusShape.PENTAGON) is pentagon
assert shapes.getShape(nwStatusShape.HEXAGON) is hexagon
assert shapes.getShape(nwStatusShape.STAR) is star
assert shapes.getShape(nwStatusShape.PACMAN) is pacman
assert shapes.getShape(nwStatusShape.BARS_1) is bars1
assert shapes.getShape(nwStatusShape.BARS_2) is bars2
assert shapes.getShape(nwStatusShape.BARS_3) is bars3
assert shapes.getShape(nwStatusShape.BARS_4) is bars4
assert shapes.getShape(nwStatusShape.BLOCK_1) is block1
assert shapes.getShape(nwStatusShape.BLOCK_2) is block2
assert shapes.getShape(nwStatusShape.BLOCK_3) is block3
assert shapes.getShape(nwStatusShape.BLOCK_4) is block4
# END Test testCoreStatus_ShapeCache
+9
View File
@@ -949,6 +949,15 @@ def testCoreToken_ExtractFormats(mockGUI):
(10, tokens.FMT_B_B), (31, tokens.FMT_I_B), (38, tokens.FMT_B_E), (38, tokens.FMT_I_E)
]
# So does this
text, fmt = tokens._extractFormats(
"Text with [b]bold and overlapping [i]italics[/b] in[/i] it."
)
assert text == "Text with bold and overlapping italics in it."
assert fmt == [
(10, tokens.FMT_B_B), (31, tokens.FMT_I_B), (38, tokens.FMT_B_E), (41, tokens.FMT_I_E)
]
# END Test testCoreToken_ExtractFormats
+76 -82
View File
@@ -24,14 +24,13 @@ import pytest
from tools import C, buildTestProject
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QColor
from PyQt5.QtWidgets import QDialog, QAction, QColorDialog
from novelwriter import CONFIG, SHARED
from novelwriter.dialogs.editlabel import GuiEditLabel
from novelwriter.dialogs.projectsettings import GuiProjectSettings
from novelwriter.enum import nwItemType
from novelwriter.enum import nwItemType, nwStatusShape
from novelwriter.types import QtMouseLeft
KEY_DELAY = 1
@@ -169,8 +168,8 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
nwGUI.rebuildTrees()
project.countStatus()
assert [e["count"] for _, e in project.data.itemStatus.items()] == [2, 0, 2, 1]
assert [e["count"] for _, e in project.data.itemImport.items()] == [3, 0, 2, 1]
assert [e.count for _, e in project.data.itemStatus.iterItems()] == [2, 0, 2, 1]
assert [e.count for _, e in project.data.itemImport.iterItems()] == [3, 0, 2, 1]
# Create Dialog
projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_STATUS)
@@ -182,20 +181,20 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
status = projSettings.statusPage
assert status.wasChanged is False
assert status.getNewList() == ([], [])
assert status.changed is False
assert status.getNewList() == []
assert status.listBox.topLevelItemCount() == 4
# Can't delete the first item (it's in use)
status.listBox.clearSelection()
status.listBox.setCurrentItem(status.listBox.topLevelItem(0))
qtbot.mouseClick(status.delButton, QtMouseLeft)
status.delButton.click()
assert status.listBox.topLevelItemCount() == 4
# Can delete the second item
status.listBox.clearSelection()
status.listBox.setCurrentItem(status.listBox.topLevelItem(1))
qtbot.mouseClick(status.delButton, QtMouseLeft)
status.delButton.click()
assert status.listBox.topLevelItemCount() == 3
# Add a new item
@@ -204,39 +203,38 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
status.addButton.click()
status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
status.editName.setText("Final")
status.colButton.click()
status.saveButton.click()
status.colorButton.click()
status._selectShape(nwStatusShape.CIRCLE)
status.applyButton.click()
assert status.listBox.topLevelItemCount() == 4
assert status.wasChanged is True
assert status.getNewList() == (
[
{
"key": C.sNew,
"name": "New",
"cols": (100, 100, 100)
}, {
"key": C.sDraft,
"name": "Draft",
"cols": (200, 150, 0)
}, {
"key": C.sFinished,
"name": "Finished",
"cols": (50, 200, 0)
}, {
"key": None,
"name": "Final",
"cols": (20, 30, 40)
}
], [
C.sNote # Deleted item
]
)
assert status.changed is True
update = status.getNewList()
assert update[0][0] == C.sNew
assert update[0][1].name == "New"
assert update[0][1].color == QColor(100, 100, 100)
assert update[0][1].shape == nwStatusShape.SQUARE
assert update[1][0] == C.sDraft
assert update[1][1].name == "Draft"
assert update[1][1].color == QColor(200, 150, 0)
assert update[1][1].shape == nwStatusShape.SQUARE
assert update[2][0] == C.sFinished
assert update[2][1].name == "Finished"
assert update[2][1].color == QColor(50, 200, 0)
assert update[2][1].shape == nwStatusShape.SQUARE
assert update[3][0] is None
assert update[3][1].name == "Final"
assert update[3][1].color == QColor(20, 30, 40)
assert update[3][1].shape == nwStatusShape.CIRCLE
# Move items, none selected -> no change
status.listBox.clearSelection()
status._moveItem(1)
assert [x["key"] for x in status.getNewList()[0]] == [
assert [x[0] for x in status.getNewList()] == [
C.sNew, C.sDraft, C.sFinished, None
]
@@ -244,7 +242,7 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
status.listBox.clearSelection()
status.listBox.setCurrentItem(status.listBox.topLevelItem(0))
status._moveItem(-1)
assert [x["key"] for x in status.getNewList()[0]] == [
assert [x[0] for x in status.getNewList()] == [
C.sNew, C.sDraft, C.sFinished, None
]
@@ -252,13 +250,13 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
status.listBox.clearSelection()
status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
status._moveItem(-1)
assert [x["key"] for x in status.getNewList()[0]] == [
assert [x[0] for x in status.getNewList()] == [
C.sNew, C.sDraft, None, C.sFinished
]
# Move items, same selected, move down -> allowed
status._moveItem(1)
assert [x["key"] for x in status.getNewList()[0]] == [
assert [x[0] for x in status.getNewList()] == [
C.sNew, C.sDraft, C.sFinished, None
]
@@ -271,62 +269,58 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRn
# Delete unused entry
importance.listBox.clearSelection()
importance.listBox.setCurrentItem(importance.listBox.topLevelItem(1))
qtbot.mouseClick(importance.delButton, QtMouseLeft)
importance.delButton.click()
assert importance.listBox.topLevelItemCount() == 3
# Add a new entry
with monkeypatch.context() as mp:
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
qtbot.mouseClick(importance.addButton, QtMouseLeft)
importance.addButton.click()
importance.listBox.clearSelection()
importance.listBox.setCurrentItem(importance.listBox.topLevelItem(3))
for _ in range(8):
qtbot.keyClick(importance.editName, Qt.Key.Key_Backspace, delay=KEY_DELAY)
for c in "Final":
qtbot.keyClick(importance.editName, c, delay=KEY_DELAY)
qtbot.mouseClick(importance.colButton, QtMouseLeft)
qtbot.mouseClick(importance.saveButton, QtMouseLeft)
importance.editName.setText("Final")
importance.colorButton.click()
importance._selectShape(nwStatusShape.TRIANGLE)
importance.applyButton.click()
assert importance.listBox.topLevelItemCount() == 4
assert importance.wasChanged is True
assert importance.getNewList() == (
[
{
"key": C.iNew,
"name": "New",
"cols": (100, 100, 100)
}, {
"key": C.iMajor,
"name": "Major",
"cols": (200, 150, 0)
}, {
"key": C.iMain,
"name": "Main",
"cols": (50, 200, 0)
}, {
"key": None,
"name": "Final",
"cols": (20, 30, 40)
}
], [
C.iMinor # Deleted item
]
)
assert importance.changed is True
update = importance.getNewList()
assert update[0][0] == C.iNew
assert update[0][1].name == "New"
assert update[0][1].color == QColor(100, 100, 100)
assert update[0][1].shape == nwStatusShape.SQUARE
assert update[1][0] == C.iMajor
assert update[1][1].name == "Major"
assert update[1][1].color == QColor(200, 150, 0)
assert update[1][1].shape == nwStatusShape.SQUARE
assert update[2][0] == C.iMain
assert update[2][1].name == "Main"
assert update[2][1].color == QColor(50, 200, 0)
assert update[2][1].shape == nwStatusShape.SQUARE
assert update[3][0] is None
assert update[3][1].name == "Final"
assert update[3][1].color == QColor(20, 30, 40)
assert update[3][1].shape == nwStatusShape.TRIANGLE
# Check Project
projSettings._doSave()
statusItems = dict(project.data.itemStatus.items())
assert statusItems[C.sNew]["name"] == "New"
assert statusItems[C.sDraft]["name"] == "Draft"
assert statusItems[C.sFinished]["name"] == "Finished"
assert statusItems["s000013"]["name"] == "Final"
statusItems = dict(project.data.itemStatus.iterItems())
assert statusItems[C.sNew].name == "New"
assert statusItems[C.sDraft].name == "Draft"
assert statusItems[C.sFinished].name == "Finished"
assert statusItems["s000013"].name == "Final"
importItems = dict(project.data.itemImport.items())
assert importItems[C.iNew]["name"] == "New"
assert importItems[C.iMajor]["name"] == "Major"
assert importItems[C.iMain]["name"] == "Main"
assert importItems["i000014"]["name"] == "Final"
importItems = dict(project.data.itemImport.iterItems())
assert importItems[C.iNew].name == "New"
assert importItems[C.iMajor].name == "Major"
assert importItems[C.iMain].name == "Main"
assert importItems["i000014"].name == "Final"
# qtbot.stop()
@@ -363,7 +357,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
# Nothing to save or delete
replace.listBox.clearSelection()
replace._saveEntry()
replace._applyChanges()
replace._delEntry()
assert replace.listBox.topLevelItemCount() == 2
@@ -381,7 +375,7 @@ def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
replace.editValue.setText("")
for c in "With This Stuff ":
qtbot.keyClick(replace.editValue, c, delay=KEY_DELAY)
qtbot.mouseClick(replace.saveButton, QtMouseLeft)
qtbot.mouseClick(replace.applyButton, QtMouseLeft)
assert replace.listBox.topLevelItem(2).text(0) == "<This>" # type: ignore
assert replace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore
+29 -17
View File
@@ -880,13 +880,13 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# Wrap Equal
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._wrapSelection("=") is True
nwGUI.docEditor._wrapSelection("=")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "=consectetur=")
# Wrap Unequal
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._wrapSelection("=", "*") is True
nwGUI.docEditor._wrapSelection("=", "*")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "=consectetur*")
# Past Paragraph
@@ -895,7 +895,7 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
cursor.setPosition(13, QTextCursor.MoveAnchor)
cursor.setPosition(1000, QTextCursor.KeepAnchor)
nwGUI.docEditor.setTextCursor(cursor)
assert nwGUI.docEditor._wrapSelection("=") is True
nwGUI.docEditor._wrapSelection("=")
newText = nwGUI.docEditor.getText()
newPara = list(filter(str.strip, newText.split("\n")))
@@ -910,14 +910,15 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# Block format repetition
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(39)
assert nwGUI.docEditor._toggleFormat(1, "=") is True
nwGUI.docEditor._toggleFormat(1, "=")
assert nwGUI.docEditor.getText() == text.replace("amet", "=amet=", 1)
nwGUI.docEditor._toggleFormat(1, "=")
assert nwGUI.docEditor.getText() == text.replace("amet", "=amet=", 1)
assert nwGUI.docEditor._toggleFormat(1, "=") is False
# Wrap Single Equal
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(1, "=") is True
nwGUI.docEditor._toggleFormat(1, "=")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "=consectetur=")
# Past Paragraph
@@ -926,7 +927,7 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
cursor.setPosition(13, QTextCursor.MoveAnchor)
cursor.setPosition(1000, QTextCursor.KeepAnchor)
nwGUI.docEditor.setTextCursor(cursor)
assert nwGUI.docEditor._toggleFormat(1, "=") is True
nwGUI.docEditor._toggleFormat(1, "=")
newText = nwGUI.docEditor.getText()
newPara = list(filter(str.strip, newText.split("\n")))
@@ -936,30 +937,40 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
# Wrap Double Equal
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(2, "=") is True
nwGUI.docEditor._toggleFormat(2, "=")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "==consectetur==")
# Toggle Double Equal with Selection
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorSelection(41, 11)
nwGUI.docEditor._toggleFormat(2, "=")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "==consectetur==")
assert nwGUI.docEditor.getSelectedText() == "consectetur"
nwGUI.docEditor._toggleFormat(2, "=")
assert nwGUI.docEditor.getText() == text
assert nwGUI.docEditor.getSelectedText() == "consectetur"
# Toggle Double Equal
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(2, "=") is True
assert nwGUI.docEditor._toggleFormat(2, "=") is True
nwGUI.docEditor._toggleFormat(2, "=")
nwGUI.docEditor._toggleFormat(2, "=")
assert nwGUI.docEditor.getText() == text
# Toggle Triple+Double Equal
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(3, "=") is True
assert nwGUI.docEditor._toggleFormat(2, "=") is True
nwGUI.docEditor._toggleFormat(3, "=")
nwGUI.docEditor._toggleFormat(2, "=")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "=consectetur=")
# Toggle Unequal
repText = text.replace("consectetur", "=consectetur==")
nwGUI.docEditor.replaceText(repText)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._toggleFormat(1, "=") is True
nwGUI.docEditor._toggleFormat(1, "=")
assert nwGUI.docEditor.getText() == text.replace("consectetur", "consectetur=")
assert nwGUI.docEditor._toggleFormat(1, "=") is True
nwGUI.docEditor._toggleFormat(1, "=")
assert nwGUI.docEditor.getText() == repText
# Replace Quotes
@@ -969,7 +980,8 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
text = "### A Scene\n\n%s" % ipsumText[0].replace("consectetur", "=consectetur=")
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor._replaceQuotes("=", "<", ">") is False
nwGUI.docEditor._replaceQuotes("=", "<", ">")
assert nwGUI.docEditor.getText() == text
# First Paragraph Selected
# This should not replace anything in second paragraph
@@ -977,7 +989,7 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_PARA)
assert nwGUI.docEditor._replaceQuotes("=", "<", ">") is True
nwGUI.docEditor._replaceQuotes("=", "<", ">")
newText = nwGUI.docEditor.getText()
newPara = list(filter(str.strip, newText.split("\n")))
@@ -989,7 +1001,7 @@ def testGuiEditor_TextManipulation(qtbot, nwGUI, projPath, ipsumText, mockRnd):
nwGUI.docEditor.replaceText(text)
nwGUI.docEditor.setCursorPosition(45)
assert nwGUI.docEditor.docAction(nwDocAction.SEL_ALL)
assert nwGUI.docEditor._replaceQuotes("=", "<", ">") is True
nwGUI.docEditor._replaceQuotes("=", "<", ">")
assert nwGUI.docEditor.getText() == text.replace("=Lorem=", "<Lorem>")
# Remove Line Breaks
+3 -3
View File
@@ -186,11 +186,11 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI):
# Check a few values
assert mainTheme._guiPalette.color(
QPalette.ColorRole.Window).getRgb() == (239, 239, 239, 255)
QPalette.ColorRole.Window).getRgb() == (239, 239, 239, 255)
assert mainTheme._guiPalette.color(
QPalette.ColorRole.WindowText).getRgb() == (0, 0, 0, 255)
QPalette.ColorRole.WindowText).getRgb() == (0, 0, 0, 255)
assert mainTheme._guiPalette.color(
QPalette.ColorRole.Base).getRgb() == (255, 255, 255, 255)
QPalette.ColorRole.Base).getRgb() == (255, 255, 255, 255)
assert mainTheme._guiPalette.color(
QPalette.ColorRole.AlternateBase).getRgb() == (239, 239, 239, 255)
+10 -5
View File
@@ -29,7 +29,7 @@ from novelwriter.text.counting import bodyTextCounter, preProcessText, standardC
def testTextCounting_preProcessText():
"""Test the text preprocessor for counters."""
# Not Text
assert preProcessText(None) == []
assert preProcessText(None) == [] # type: ignore
# No Text
assert preProcessText("") == []
@@ -81,6 +81,10 @@ def testTextCounting_standardCounter():
assert standardCounter(None) == (0, 0, 0) # type: ignore
assert standardCounter(1234) == (0, 0, 0) # type: ignore
# Test Corner Cases, Bug #1816
assert standardCounter("> ") == (0, 0, 0)
assert standardCounter(" <") == (0, 0, 0)
# General Text
cC, wC, pC = standardCounter((
"#! Title\n\n"
@@ -88,7 +92,8 @@ def testTextCounting_standardCounter():
"# Heading One\n"
"## Heading Two\n"
"### Heading Three\n"
"#### Heading Four\n\n"
"###! Heading Four\n"
"#### Heading Five\n\n"
"@tag: value\n\n"
"% A comment that should not be counted.\n\n"
"The first paragraph.\n\n"
@@ -96,8 +101,8 @@ def testTextCounting_standardCounter():
"The third paragraph.\n\n"
"Dashes\u2013and even longer\u2014dashes."
))
assert cC == 151
assert wC == 24
assert cC == 163
assert wC == 26
assert pC == 4
# Text Alignment
@@ -182,7 +187,7 @@ def testTextCounting_standardCounter():
def testTextCounting_bodyTextCounter():
"""Test the body text counter."""
# Not Text
assert bodyTextCounter(None) == (0, 0, 0)
assert bodyTextCounter(None) == (0, 0, 0) # type: ignore
# General Text
wC, cC, sC = bodyTextCounter((
+1 -1
View File
@@ -212,7 +212,7 @@ def testManuscript_Features(monkeypatch, qtbot, nwGUI, projPath, mockRnd):
build = manus._builds.getBuild(first.data(GuiManuscript.D_KEY))
assert isinstance(build, BuildSettings)
build.setValue("headings.fmtScene", nwHeadFmt.TITLE)
build.setValue("headings.fmtHardScene", nwHeadFmt.TITLE)
build.setValue("headings.fmtAltScene", nwHeadFmt.TITLE)
manus._builds.setBuild(build)
# Preview again, and allow cache file to be created
+5 -5
View File
@@ -335,7 +335,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
build.setValue("headings.fmtChapter", chTitle)
build.setValue("headings.fmtUnnumbered", unTitle)
build.setValue("headings.fmtScene", scTitle)
build.setValue("headings.fmtHardScene", shTitle)
build.setValue("headings.fmtAltScene", shTitle)
build.setValue("headings.fmtSection", sxTitle)
build.setValue("headings.hideScene", False)
build.setValue("headings.hideSection", False)
@@ -354,7 +354,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
assert headTab.fmtChapter.text() == chTitle
assert headTab.fmtUnnumbered.text() == unTitle
assert headTab.fmtScene.text() == scTitle
assert headTab.fmtHScene.text() == shTitle
assert headTab.fmtAScene.text() == shTitle
assert headTab.fmtSection.text() == sxTitle
assert headTab.swtScene.isChecked() is False
assert headTab.swtSection.isChecked() is False
@@ -401,7 +401,7 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
assert headTab.editTextBox.isEnabled() is False
# Hard Scene
headTab.btnHScene.click()
headTab.btnAScene.click()
assert headTab._editing == headTab.EDIT_HSCENE
assert headTab.editTextBox.isEnabled() is True
assert headTab.editTextBox.toPlainText() == shTitle
@@ -467,10 +467,10 @@ def testBuildSettings_Headings(qtbot: QtBot, nwGUI: GuiMain):
headTab.btnApply.click()
assert build.getStr("headings.fmtScene") == nwHeadFmt.TITLE
headTab.btnHScene.click()
headTab.btnAScene.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)
headTab.btnApply.click()
assert build.getStr("headings.fmtHardScene") == nwHeadFmt.TITLE
assert build.getStr("headings.fmtAltScene") == nwHeadFmt.TITLE
headTab.btnSection.click()
headTab.editTextBox.setPlainText(nwHeadFmt.TITLE)