Merge branch 'main' into release_1.0b1
This commit is contained in:
@@ -57,26 +57,27 @@ already familiar with how to run Python applications on your platform.
|
||||
:maxdepth: 2
|
||||
:caption: First Steps
|
||||
|
||||
introduction
|
||||
started
|
||||
interface
|
||||
int_introduction
|
||||
int_started
|
||||
int_interface
|
||||
int_typography
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Writing Novels
|
||||
|
||||
projects
|
||||
structure
|
||||
notes
|
||||
export
|
||||
write_projects
|
||||
write_structure
|
||||
write_notes
|
||||
write_export
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Under the Hood
|
||||
|
||||
technical
|
||||
tech_technical
|
||||
|
||||
|
||||
Indices and Tables
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.. _a_ui:
|
||||
|
||||
***************
|
||||
**************
|
||||
User Interface
|
||||
***************
|
||||
**************
|
||||
|
||||
The user interface is kept as simple as possible to avoid distractions when writing. This page lists
|
||||
all the main GUI elements, and explains what they do.
|
||||
@@ -341,11 +341,12 @@ Most features are available as keyboard shortcuts. These are as follows:
|
||||
":kbd:`Ctrl`:kbd:`B`", "Format selected text, or word under cursor, with strong emphasis (bold)."
|
||||
":kbd:`Ctrl`:kbd:`C`", "Copy selected text to clipboard."
|
||||
":kbd:`Ctrl`:kbd:`D`", "Wrap selected text, or word under cursor, in double quotes."
|
||||
":kbd:`Ctrl`:kbd:`E`", "If in the project tree, edit a document or folder settings. (Same as :kbd:`F2`)"
|
||||
":kbd:`Ctrl`:kbd:`E`", "If in the project tree, edit a document or folder settings. (Same as :kbd:`F2`.)"
|
||||
":kbd:`Ctrl`:kbd:`F`", "Open the search bar and search for the selected word, if any is selected."
|
||||
":kbd:`Ctrl`:kbd:`G`", "Find next occurrence of search word in current document. (Same as :kbd:`F3`)"
|
||||
":kbd:`Ctrl`:kbd:`H`", "Open the search and replace bar and search for the selected word, if any is selected. (On Mac, this is :kbd:`Cmd`:kbd:`=`)"
|
||||
":kbd:`Ctrl`:kbd:`G`", "Find next occurrence of search word in current document. (Same as :kbd:`F3`.)"
|
||||
":kbd:`Ctrl`:kbd:`H`", "Open the search and replace bar and search for the selected word, if any is selected. (On Mac, this is :kbd:`Cmd`:kbd:`=`.)"
|
||||
":kbd:`Ctrl`:kbd:`I`", "Format selected text, or word under cursor, with emphasis (italic)."
|
||||
":kbd:`Ctrl`:kbd:`K`", "Activate the insert commands. The commands are listed in :ref:`a_ui_shortcuts_ins`."
|
||||
":kbd:`Ctrl`:kbd:`N`", "Create new document."
|
||||
":kbd:`Ctrl`:kbd:`O`", "Open selected document."
|
||||
":kbd:`Ctrl`:kbd:`Q`", "Exit novelWriter."
|
||||
@@ -365,7 +366,7 @@ Most features are available as keyboard shortcuts. These are as follows:
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`1`", "Replace occurrence of search word in current document, and search for next occurrence."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`A`", "Select all text in current paragraph."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`D`", "Wrap selected text, or word under cursor, in single quotes."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`G`", "Find previous occurrence of search word in current document. (Same as :kbd:`Shift`:kbd:`F3`)"
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`G`", "Find previous occurrence of search word in current document. (Same as :kbd:`Shift`:kbd:`F3`.)"
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`I`", "Import text to the current document from a text file."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`N`", "Create new folder."
|
||||
":kbd:`Ctrl`:kbd:`Shift`:kbd:`O`", "Open a project."
|
||||
@@ -386,7 +387,7 @@ Most features are available as keyboard shortcuts. These are as follows:
|
||||
":kbd:`F10`", "Re-build the project outline."
|
||||
":kbd:`F11`", "Activate full screen mode."
|
||||
":kbd:`Shift`:kbd:`F1`", "Open the online documentation in the system default browser."
|
||||
":kbd:`Shift`:kbd:`F3`", "Find previous occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`Shift`:kbd:`G`)"
|
||||
":kbd:`Shift`:kbd:`F3`", "Find previous occurrence of search word in current document. (Same as :kbd:`Ctrl`:kbd:`Shift`:kbd:`G`.)"
|
||||
":kbd:`Return`", "If in the project tree, open a document for editing."
|
||||
|
||||
.. note::
|
||||
@@ -409,11 +410,12 @@ combination for the inserted character or punctuation.
|
||||
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`-`", "Insert a short dash (en dash)."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`_`", "Insert a long dash (em dash)."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`.`", "Insert ellipsis."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`1`", "Insert left single quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`2`", "Insert right single quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`3`", "Insert left double quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`4`", "Insert right double quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`.`", "Insert an ellipsis."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`1`", "Insert a left single quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`2`", "Insert a right single quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`3`", "Insert a left double quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`4`", "Insert a right double quote."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`'`", "Insert a modifier apostrophe."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`Return`", "Insert a hard line break."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`Space`", "Insert a non-breaking space."
|
||||
":kbd:`Ctrl`:kbd:`K`, :kbd:`Shift`:kbd:`Space`", "Insert a thin space."
|
||||
@@ -0,0 +1,87 @@
|
||||
.. _a_typ:
|
||||
|
||||
*******************
|
||||
Typographical Notes
|
||||
*******************
|
||||
|
||||
novelWriter has some support for typographical symbols that are not usually easily available in many
|
||||
text editors. This includes for instance the proper unicode quotation marks, dashes, ellipsis, thin
|
||||
spaces, etc. All these symbols are available from the :guilabel:`Insert` menu, and via keyboard
|
||||
shortcuts. See :ref:`a_ui_shortcuts_ins`.
|
||||
|
||||
This chapter provides some additional information on how novelWriter handles these symbols.
|
||||
|
||||
|
||||
.. _a_typ_notes:
|
||||
|
||||
Special Notes on Symbols
|
||||
========================
|
||||
|
||||
Some additional notes on these symbols.
|
||||
|
||||
|
||||
Dashes and Ellipsis
|
||||
-------------------
|
||||
|
||||
With the auto-replace feature enabled (see :ref:`a_ui_edit_auto`), multiple hyphens are converted
|
||||
automatically to short and long dashes, and three dots to ellipsis. The last auto-replace can always
|
||||
be reverted with the undo command :kbd:`Ctrl`:kbd:`Z`, reverting the text to what you typed before
|
||||
the automatic replacement occurred.
|
||||
|
||||
|
||||
Single and Double Quotes
|
||||
------------------------
|
||||
|
||||
All the different quotation marks listed on the `Quotation Mark`_ Wikipedia page are available, and
|
||||
can be selected as auto-replaced symbols for straight single and double quote key strokes. The
|
||||
settings can be found in the :guilabel:`Preferences`.
|
||||
|
||||
Ordinarily, text wrapped in quotes are highlighted by the editor. This is meant as a convenience for
|
||||
highlighting dialogue between characters. This feature can be disabled in the
|
||||
:guilabel:`Preferences` if this feature isn't wanted.
|
||||
|
||||
The editor distinguishes between text wrapped in straight quotes and with the user-selected double
|
||||
quote symbols. This is to help the writer recognise which parts of the text are not using the chosen
|
||||
quote symbols. Two convenience functions in the :guilabel:`Format` menu can be used to re-format a
|
||||
selected section of text with the correct quote symbols.
|
||||
|
||||
.. _Quotation Mark: https://en.wikipedia.org/wiki/Quotation_mark
|
||||
|
||||
|
||||
Modifier Letter Apostrophes
|
||||
---------------------------
|
||||
|
||||
The auto-replace feature will consider any right-facing single straight quote as a quote symbol,
|
||||
even if it's intended as an apostrophe. This also includes the syntax highlighter, which may assume
|
||||
the first following apostrophe is the closing symbol of a single quoted region of text.
|
||||
|
||||
To get around this, an alternative apostrophe is available. It is a special Unicode character that
|
||||
is not categorised as punctuation, but as a modifier. It is usually renderred the same way as right
|
||||
single quotation marks, but not always, depending on the font. There is a Wikipedia article for the
|
||||
`Modifier letter apostrophe`_ with more details.
|
||||
|
||||
.. note::
|
||||
On export with the :guilabel:`Build Novel Project` tool, these apostrophes will be replaced
|
||||
automatically with the corresponding right hand quote symbols as is generally recommended.
|
||||
Therefore it doesn't really matter if you only use them to correct highlighting.
|
||||
|
||||
.. _Modifier letter apostrophe: https://en.wikipedia.org/wiki/Modifier_letter_apostrophe
|
||||
|
||||
|
||||
Special Space Symbols
|
||||
---------------------
|
||||
|
||||
A few variations of the regular space character is supported. The correct typographical way to
|
||||
separate a number from its unit is with a `thin space`_. It is usually 2/3 the width of a regular
|
||||
space. For numbers and units, this should in addition be a non-breaking space, that is, the text
|
||||
wrapping should not add a line break on this particular space.
|
||||
|
||||
A regular space can also be made into a non-breaking space.
|
||||
|
||||
All non-breaking spaces are highlighted with a differently coloured packground. The colour will
|
||||
depend on the selected colour theme.
|
||||
|
||||
The thin and non-breaking spaces are converted to their corresponding HTML codes on export to HTML
|
||||
format. For plain text, they are exported as regular spaces.
|
||||
|
||||
.. _thin space: https://en.wikipedia.org/wiki/Thin_space
|
||||
@@ -233,6 +233,7 @@ class nwUnicode:
|
||||
U_ENDASH = "\u2013" # Short dash
|
||||
U_EMDASH = "\u2014" # Long dash
|
||||
U_HELLIP = "\u2026" # Ellipsis
|
||||
U_MAPOSS = "\u02bc" # Modifier letter single apostrophe
|
||||
|
||||
## Spaces and Lines
|
||||
U_NBSP = "\u00a0" # Non-breaking space
|
||||
@@ -283,6 +284,7 @@ class nwUnicode:
|
||||
H_ENDASH = "–"
|
||||
H_EMDASH = "—"
|
||||
H_HELLIP = "…"
|
||||
H_MAPOSS = "ʼ"
|
||||
|
||||
## Spaces
|
||||
H_NBSP = " "
|
||||
|
||||
@@ -112,6 +112,7 @@ class nwDocInsert(Enum):
|
||||
QUOTE_RS = 9
|
||||
QUOTE_LD = 10
|
||||
QUOTE_RD = 11
|
||||
MODAPOS_S = 12
|
||||
|
||||
# END Enum nwDocInsert
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ class ToHtml(Tokenizer):
|
||||
nwUnicode.U_NBSP : nwUnicode.H_NBSP,
|
||||
nwUnicode.U_THNSP : nwUnicode.H_THNSP,
|
||||
nwUnicode.U_THNBSP : nwUnicode.H_THNBSP,
|
||||
nwUnicode.U_MAPOSS : nwUnicode.H_RSQUO,
|
||||
}
|
||||
self.revDict = {}
|
||||
self.reReplace = []
|
||||
|
||||
@@ -612,6 +612,8 @@ class GuiDocEditor(QTextEdit):
|
||||
theText = nwUnicode.U_EMDASH
|
||||
elif theInsert == nwDocInsert.ELLIPSIS:
|
||||
theText = nwUnicode.U_HELLIP
|
||||
elif theInsert == nwDocInsert.MODAPOS_S:
|
||||
theText = nwUnicode.U_MAPOSS
|
||||
elif theInsert == nwDocInsert.QUOTE_LS:
|
||||
theText = self.typSQOpen
|
||||
elif theInsert == nwDocInsert.QUOTE_RS:
|
||||
|
||||
@@ -143,17 +143,17 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
# Quoted Strings
|
||||
if self.mainConf.highlightQuotes:
|
||||
self.hRules.append((
|
||||
"{:s}(.+?){:s}".format('"', '"'), {
|
||||
"\\B{:s}(.*?){:s}\\B".format('"', '"'), {
|
||||
0 : self.hStyles["dialogue1"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
"{:s}(.+?){:s}".format(*self.mainConf.fmtDoubleQuotes), {
|
||||
"\\B{:s}(.*?){:s}\\B".format(*self.mainConf.fmtDoubleQuotes), {
|
||||
0 : self.hStyles["dialogue2"],
|
||||
}
|
||||
))
|
||||
self.hRules.append((
|
||||
"{:s}(.+?){:s}".format(*self.mainConf.fmtSingleQuotes), {
|
||||
"\\B{:s}(.*?){:s}\\B".format(*self.mainConf.fmtSingleQuotes), {
|
||||
0 : self.hStyles["dialogue3"],
|
||||
}
|
||||
))
|
||||
@@ -198,7 +198,7 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
||||
# Build a QRegExp for spell checker
|
||||
# Include additional characters that the highlighter should
|
||||
# consider to be word separators
|
||||
wordSep = r"_\+"
|
||||
wordSep = r"_\+/"
|
||||
wordSep += nwUnicode.U_ENDASH
|
||||
wordSep += nwUnicode.U_EMDASH
|
||||
self.spellRx = QRegularExpression(r"\b[^\s"+wordSep+r"]+\b")
|
||||
|
||||
@@ -554,6 +554,16 @@ class GuiMainMenu(QMenuBar):
|
||||
# Insert > Separator
|
||||
self.insertMenu.addSeparator()
|
||||
|
||||
# Insert > Alternative Apostrophe
|
||||
self.aInsMSApos = QAction("Alternative Apostrophe", self)
|
||||
self.aInsMSApos.setStatusTip("Insert unicode modifier letter single apostrophe")
|
||||
self.aInsMSApos.setShortcut("Ctrl+K, '")
|
||||
self.aInsMSApos.triggered.connect(lambda: self._docInsert(nwDocInsert.MODAPOS_S))
|
||||
self.insertMenu.addAction(self.aInsMSApos)
|
||||
|
||||
# Insert > Separator
|
||||
self.insertMenu.addSeparator()
|
||||
|
||||
# Insert > Hard Line Break
|
||||
self.aInsHardBreak = QAction("Hard Line Break", self)
|
||||
self.aInsHardBreak.setStatusTip("Insert a hard line break")
|
||||
|
||||
@@ -1039,6 +1039,7 @@ class GuiMain(QMainWindow):
|
||||
self.addAction(self.mainMenu.aInsQuoteRS)
|
||||
self.addAction(self.mainMenu.aInsQuoteLD)
|
||||
self.addAction(self.mainMenu.aInsQuoteRD)
|
||||
self.addAction(self.mainMenu.aInsMSApos)
|
||||
self.addAction(self.mainMenu.aInsHardBreak)
|
||||
self.addAction(self.mainMenu.aInsNBSpace)
|
||||
self.addAction(self.mainMenu.aInsThinSpace)
|
||||
|
||||
+53
-23
@@ -5,10 +5,14 @@
|
||||
import sys
|
||||
import pytest
|
||||
import shutil
|
||||
|
||||
from os import path, mkdir
|
||||
from nwdummy import DummyMain
|
||||
|
||||
sys.path.insert(1, path.abspath(path.join(path.dirname(__file__), path.pardir)))
|
||||
|
||||
from nw.config import Config # noqa: E402
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwTemp():
|
||||
testDir = path.dirname(__file__)
|
||||
@@ -19,6 +23,31 @@ def nwTemp():
|
||||
mkdir(tempDir)
|
||||
return tempDir
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwRef():
|
||||
testDir = path.dirname(__file__)
|
||||
refDir = path.join(testDir, "reference")
|
||||
return refDir
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwConf(nwRef, nwTemp):
|
||||
theConf = Config()
|
||||
theConf.initConfig(nwRef, nwTemp)
|
||||
return theConf
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def tmpConf(nwRef, nwTemp):
|
||||
theConf = Config()
|
||||
theConf.initConfig(nwTemp, nwTemp)
|
||||
theConf.setLastPath("")
|
||||
return theConf
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwDummy(nwRef, nwTemp, nwConf):
|
||||
theDummy = DummyMain()
|
||||
theDummy.mainConf = nwConf
|
||||
return theDummy
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwTempProj(nwTemp):
|
||||
projDir = path.join(nwTemp, "proj")
|
||||
@@ -40,20 +69,6 @@ def nwTempBuild(nwTemp):
|
||||
mkdir(buildDir)
|
||||
return buildDir
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwTempCustom(nwTemp):
|
||||
customDir = path.join(nwTemp, "custom")
|
||||
if not path.isdir(customDir):
|
||||
mkdir(customDir)
|
||||
return customDir
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwTempSample(nwTemp):
|
||||
sampleDir = path.join(nwTemp, "sample")
|
||||
if not path.isdir(sampleDir):
|
||||
mkdir(sampleDir)
|
||||
return sampleDir
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def nwFuncTemp(nwTemp):
|
||||
funcDir = path.join(nwTemp, "ftemp")
|
||||
@@ -66,18 +81,30 @@ def nwFuncTemp(nwTemp):
|
||||
shutil.rmtree(funcDir)
|
||||
return
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwRef():
|
||||
@pytest.fixture(scope="function")
|
||||
def nwMinimal(nwTemp):
|
||||
testDir = path.dirname(__file__)
|
||||
refDir = path.join(testDir, "reference")
|
||||
return refDir
|
||||
minimalStore = path.join(testDir, "minimal")
|
||||
minimalDir = path.join(nwTemp, "minimal")
|
||||
if path.isdir(minimalDir):
|
||||
shutil.rmtree(minimalDir)
|
||||
shutil.copytree(minimalStore, minimalDir)
|
||||
cacheDir = path.join(minimalDir, "cache")
|
||||
if path.isdir(cacheDir):
|
||||
shutil.rmtree(cacheDir)
|
||||
metaDir = path.join(minimalDir, "meta")
|
||||
if path.isdir(metaDir):
|
||||
shutil.rmtree(metaDir)
|
||||
yield minimalDir
|
||||
if path.isdir(minimalDir):
|
||||
shutil.rmtree(minimalDir)
|
||||
return
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def nwLipsum():
|
||||
@pytest.fixture(scope="function")
|
||||
def nwLipsum(nwTemp):
|
||||
testDir = path.dirname(__file__)
|
||||
tempDir = path.join(testDir, "temp")
|
||||
lipsumStore = path.join(testDir, "lipsum")
|
||||
lipsumDir = path.join(tempDir, "lipsum")
|
||||
lipsumDir = path.join(nwTemp, "lipsum")
|
||||
if path.isdir(lipsumDir):
|
||||
shutil.rmtree(lipsumDir)
|
||||
shutil.copytree(lipsumStore, lipsumDir)
|
||||
@@ -87,4 +114,7 @@ def nwLipsum():
|
||||
metaDir = path.join(lipsumDir, "meta")
|
||||
if path.isdir(metaDir):
|
||||
shutil.rmtree(metaDir)
|
||||
return lipsumDir
|
||||
yield lipsumDir
|
||||
if path.isdir(lipsumDir):
|
||||
shutil.rmtree(lipsumDir)
|
||||
return
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
[
|
||||
"content/7a992350f3eb6.nwd",
|
||||
"NOVEL",
|
||||
"Lorem Ipusm"
|
||||
"Lorem Ipsum"
|
||||
],
|
||||
[
|
||||
"content/846352075de7d.nwd",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
content/441420a886d82.nwd NOVEL Chapter Two
|
||||
content/47666c91c7ccf.nwd NOVEL Scene Five
|
||||
content/4c4f28287af27.nwd CHARACTER Mr. Nobody
|
||||
content/7a992350f3eb6.nwd NOVEL Lorem Ipusm
|
||||
content/7a992350f3eb6.nwd NOVEL Lorem Ipsum
|
||||
content/846352075de7d.nwd NOVEL Interlude
|
||||
content/88243afbe5ed8.nwd NOVEL Scene One
|
||||
content/88d59a277361b.nwd NOVEL Prologue
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<novelWriterXML appVersion="0.9.0rc1" hexVersion="0x000900c1" fileVersion="1.1" timeStamp="2020-06-13 00:37:49">
|
||||
<novelWriterXML appVersion="0.12.1" hexVersion="0x001201f0" fileVersion="1.2" timeStamp="2020-08-28 15:49:43">
|
||||
<project>
|
||||
<name>Lorem Ipsum</name>
|
||||
<title>Lorem Ipsum</title>
|
||||
<author>lipsum.com</author>
|
||||
<saveCount>7</saveCount>
|
||||
<saveCount>8</saveCount>
|
||||
<autoCount>21</autoCount>
|
||||
<editTime>1459</editTime>
|
||||
<editTime>1472</editTime>
|
||||
</project>
|
||||
<settings>
|
||||
<doBackup>False</doBackup>
|
||||
<spellCheck>False</spellCheck>
|
||||
<autoOutline>True</autoOutline>
|
||||
<lastEdited>04468803b92e1</lastEdited>
|
||||
<lastEdited>fb609cd8319dc</lastEdited>
|
||||
<lastViewed>None</lastViewed>
|
||||
<lastWordCount>3847</lastWordCount>
|
||||
<novelWordCount>3109</novelWordCount>
|
||||
<notesWordCount>738</notesWordCount>
|
||||
<autoReplace>
|
||||
<Rep1>Replace Text 1</Rep1>
|
||||
<Rep2>Replace Text 2</Rep2>
|
||||
<entry key="Rep1">Replace Text 1</entry>
|
||||
<entry key="Rep2">Replace Text 2</entry>
|
||||
</autoReplace>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
[
|
||||
[
|
||||
"content/8c659a11cd429.nwd",
|
||||
"NOVEL",
|
||||
"New Scene"
|
||||
],
|
||||
[
|
||||
"content/a35baf2e93843.nwd",
|
||||
"NOVEL",
|
||||
"Title Page"
|
||||
],
|
||||
[
|
||||
"content/f5ab3e30151e1.nwd",
|
||||
"NOVEL",
|
||||
"New Chapter"
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
Table of Contents
|
||||
===================
|
||||
|
||||
File Name Class Document Label
|
||||
--------------------------------------------------------------------------------
|
||||
content/8c659a11cd429.nwd NOVEL New Scene
|
||||
content/a35baf2e93843.nwd NOVEL Title Page
|
||||
content/f5ab3e30151e1.nwd NOVEL New Chapter
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
%%~ 8c659a11cd429:a6d311a93600a:a508bb932959c:NOVEL:SCENE:New Scene
|
||||
### New Scene
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
%%~ a35baf2e93843:a508bb932959c:NOVEL:TITLE:Title Page
|
||||
# Minimal
|
||||
|
||||
By Jane Doe, John Doh
|
||||
@@ -0,0 +1,3 @@
|
||||
%%~ f5ab3e30151e1:a6d311a93600a:a508bb932959c:NOVEL:CHAPTER:New Chapter
|
||||
## New Chapter
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,2 @@
|
||||
# Start Time End Time Novel Notes
|
||||
2020-08-28 11:36:36 2020-08-28 11:36:48 10 0
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"tagIndex": {},
|
||||
"refIndex": {
|
||||
"a35baf2e93843": {
|
||||
"T000000": {
|
||||
"tags": [],
|
||||
"updated": 1598607396
|
||||
},
|
||||
"T000001": {
|
||||
"tags": [],
|
||||
"updated": 1598607396
|
||||
}
|
||||
},
|
||||
"f5ab3e30151e1": {
|
||||
"T000000": {
|
||||
"tags": [],
|
||||
"updated": 1598607396
|
||||
},
|
||||
"T000001": {
|
||||
"tags": [],
|
||||
"updated": 1598607396
|
||||
}
|
||||
},
|
||||
"8c659a11cd429": {
|
||||
"T000000": {
|
||||
"tags": [],
|
||||
"updated": 1598607396
|
||||
},
|
||||
"T000001": {
|
||||
"tags": [],
|
||||
"updated": 1598607396
|
||||
}
|
||||
}
|
||||
},
|
||||
"novelIndex": {
|
||||
"a35baf2e93843": {
|
||||
"T000001": {
|
||||
"level": "H1",
|
||||
"title": "Minimal",
|
||||
"layout": "TITLE",
|
||||
"synopsis": "",
|
||||
"cCount": 7,
|
||||
"wCount": 1,
|
||||
"pCount": 0,
|
||||
"updated": 1598607396
|
||||
}
|
||||
},
|
||||
"f5ab3e30151e1": {
|
||||
"T000001": {
|
||||
"level": "H2",
|
||||
"title": "New Chapter",
|
||||
"layout": "CHAPTER",
|
||||
"synopsis": "",
|
||||
"cCount": 11,
|
||||
"wCount": 2,
|
||||
"pCount": 0,
|
||||
"updated": 1598607396
|
||||
}
|
||||
},
|
||||
"8c659a11cd429": {
|
||||
"T000001": {
|
||||
"level": "H3",
|
||||
"title": "New Scene",
|
||||
"layout": "SCENE",
|
||||
"synopsis": "",
|
||||
"cCount": 9,
|
||||
"wCount": 2,
|
||||
"pCount": 0,
|
||||
"updated": 1598607396
|
||||
}
|
||||
}
|
||||
},
|
||||
"noteIndex": {},
|
||||
"textCounts": {
|
||||
"a35baf2e93843": [
|
||||
28,
|
||||
6,
|
||||
1
|
||||
],
|
||||
"f5ab3e30151e1": [
|
||||
11,
|
||||
2,
|
||||
0
|
||||
],
|
||||
"8c659a11cd429": [
|
||||
9,
|
||||
2,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<novelWriterXML appVersion="0.12.1" hexVersion="0x001201f0" fileVersion="1.2" timeStamp="2020-08-28 11:36:45">
|
||||
<project>
|
||||
<name>Test Minimal</name>
|
||||
<title>Minimal</title>
|
||||
<author>Jane Doe</author>
|
||||
<author>John Doh</author>
|
||||
<saveCount>1</saveCount>
|
||||
<autoCount>1</autoCount>
|
||||
<editTime>8</editTime>
|
||||
</project>
|
||||
<settings>
|
||||
<doBackup>True</doBackup>
|
||||
<spellCheck>False</spellCheck>
|
||||
<autoOutline>True</autoOutline>
|
||||
<lastEdited>None</lastEdited>
|
||||
<lastViewed>None</lastViewed>
|
||||
<lastWordCount>10</lastWordCount>
|
||||
<novelWordCount>10</novelWordCount>
|
||||
<notesWordCount>0</notesWordCount>
|
||||
<autoReplace/>
|
||||
<titleFormat>
|
||||
<title>%title%</title>
|
||||
<chapter>Chapter %ch%: %title%</chapter>
|
||||
<unnumbered>%title%</unnumbered>
|
||||
<scene>* * *</scene>
|
||||
<section></section>
|
||||
</titleFormat>
|
||||
<status>
|
||||
<entry blue="100" green="100" red="100">New</entry>
|
||||
<entry blue="0" green="50" red="200">Note</entry>
|
||||
<entry blue="0" green="150" red="200">Draft</entry>
|
||||
<entry blue="0" green="200" red="50">Finished</entry>
|
||||
</status>
|
||||
<importance>
|
||||
<entry blue="100" green="100" red="100">New</entry>
|
||||
<entry blue="0" green="50" red="200">Minor</entry>
|
||||
<entry blue="0" green="150" red="200">Major</entry>
|
||||
<entry blue="0" green="200" red="50">Main</entry>
|
||||
</importance>
|
||||
</settings>
|
||||
<content count="8">
|
||||
<item handle="a508bb932959c" order="0" parent="None">
|
||||
<name>Novel</name>
|
||||
<type>ROOT</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="a35baf2e93843" order="0" parent="a508bb932959c">
|
||||
<name>Title Page</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<exported>True</exported>
|
||||
<layout>TITLE</layout>
|
||||
<charCount>28</charCount>
|
||||
<wordCount>6</wordCount>
|
||||
<paraCount>1</paraCount>
|
||||
<cursorPos>0</cursorPos>
|
||||
</item>
|
||||
<item handle="a6d311a93600a" order="1" parent="a508bb932959c">
|
||||
<name>New Chapter</name>
|
||||
<type>FOLDER</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="f5ab3e30151e1" order="0" parent="a6d311a93600a">
|
||||
<name>New Chapter</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<exported>True</exported>
|
||||
<layout>CHAPTER</layout>
|
||||
<charCount>11</charCount>
|
||||
<wordCount>2</wordCount>
|
||||
<paraCount>0</paraCount>
|
||||
<cursorPos>0</cursorPos>
|
||||
</item>
|
||||
<item handle="8c659a11cd429" order="1" parent="a6d311a93600a">
|
||||
<name>New Scene</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
<status>New</status>
|
||||
<exported>True</exported>
|
||||
<layout>SCENE</layout>
|
||||
<charCount>9</charCount>
|
||||
<wordCount>2</wordCount>
|
||||
<paraCount>0</paraCount>
|
||||
<cursorPos>0</cursorPos>
|
||||
</item>
|
||||
<item handle="7695ce551d265" order="1" parent="None">
|
||||
<name>Plot</name>
|
||||
<type>ROOT</type>
|
||||
<class>PLOT</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="afb3043c7b2b3" order="2" parent="None">
|
||||
<name>Characters</name>
|
||||
<type>ROOT</type>
|
||||
<class>CHARACTER</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="9d5247ab588e0" order="3" parent="None">
|
||||
<name>World</name>
|
||||
<type>ROOT</type>
|
||||
<class>WORLD</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
</content>
|
||||
</novelWriterXML>
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<novelWriterXML appVersion="0.11.1" hexVersion="0x001101f0" fileVersion="1.2" timeStamp="2020-08-10 21:29:43">
|
||||
<novelWriterXML appVersion="0.12.1" hexVersion="0x001201f0" fileVersion="1.2" timeStamp="2020-08-28 11:58:47">
|
||||
<project>
|
||||
<name>New Project</name>
|
||||
<title></title>
|
||||
<saveCount>5</saveCount>
|
||||
<saveCount>2</saveCount>
|
||||
<autoCount>1</autoCount>
|
||||
<editTime>0</editTime>
|
||||
</project>
|
||||
@@ -37,7 +37,7 @@
|
||||
<entry blue="0" green="200" red="50">Main</entry>
|
||||
</importance>
|
||||
</settings>
|
||||
<content count="14">
|
||||
<content count="10">
|
||||
<item handle="73475cb40a568" order="None" parent="None">
|
||||
<name>Novel</name>
|
||||
<type>ROOT</type>
|
||||
@@ -109,35 +109,7 @@
|
||||
<paraCount>0</paraCount>
|
||||
<cursorPos>0</cursorPos>
|
||||
</item>
|
||||
<item handle="1a6562590ef19" order="None" parent="None">
|
||||
<name>Timeline</name>
|
||||
<type>ROOT</type>
|
||||
<class>TIMELINE</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="031b4af5197ec" order="None" parent="None">
|
||||
<name>Object</name>
|
||||
<type>ROOT</type>
|
||||
<class>OBJECT</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="41cfc0d1f2d12" order="None" parent="None">
|
||||
<name>Custom1</name>
|
||||
<type>ROOT</type>
|
||||
<class>CUSTOM</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="2858dcd1057d3" order="None" parent="None">
|
||||
<name>Custom2</name>
|
||||
<type>ROOT</type>
|
||||
<class>CUSTOM</class>
|
||||
<status>New</status>
|
||||
<expanded>False</expanded>
|
||||
</item>
|
||||
<item handle="2fca346db6561" order="None" parent="73475cb40a568">
|
||||
<item handle="1a6562590ef19" order="None" parent="31489056e0916">
|
||||
<name>Hello</name>
|
||||
<type>FILE</type>
|
||||
<class>NOVEL</class>
|
||||
@@ -149,7 +121,7 @@
|
||||
<paraCount>0</paraCount>
|
||||
<cursorPos>0</cursorPos>
|
||||
</item>
|
||||
<item handle="02d20bbd7e394" order="None" parent="71ee45a3c0db9">
|
||||
<item handle="031b4af5197ec" order="None" parent="71ee45a3c0db9">
|
||||
<name>Jane</name>
|
||||
<type>FILE</type>
|
||||
<class>CHARACTER</class>
|
||||
|
||||
+87
-89
@@ -5,112 +5,110 @@
|
||||
import pytest
|
||||
from nwtools import cmpFiles
|
||||
from os import path
|
||||
from nw.config import Config
|
||||
|
||||
theConf = Config()
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigInit(nwTemp, nwRef):
|
||||
tmpConf = path.join(nwTemp, "novelwriter.conf")
|
||||
def testConfigCore(tmpConf, nwTemp, nwRef):
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
assert theConf.initConfig(nwTemp, nwTemp)
|
||||
assert theConf.setLastPath("")
|
||||
assert theConf.saveConfig()
|
||||
assert cmpFiles(tmpConf, refConf, [2])
|
||||
assert not theConf.confChanged
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.saveConfig()
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
assert tmpConf.loadConfig()
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSave(nwTemp, nwRef):
|
||||
tmpConf = path.join(nwTemp, "novelwriter.conf")
|
||||
def testConfigSetConfPath(tmpConf, nwTemp):
|
||||
assert tmpConf.setConfPath(None)
|
||||
assert not tmpConf.setConfPath(path.join("somewhere", "over", "the", "rainbow"))
|
||||
assert tmpConf.setConfPath(path.join(nwTemp, "novelwriter.conf"))
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.confFile == "novelwriter.conf"
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetDataPath(tmpConf, nwTemp):
|
||||
assert tmpConf.setDataPath(None)
|
||||
assert not tmpConf.setDataPath(path.join("somewhere", "over", "the", "rainbow"))
|
||||
assert tmpConf.setDataPath(nwTemp)
|
||||
assert tmpConf.dataPath == nwTemp
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetWinSize(tmpConf, nwTemp, nwRef):
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
assert theConf.confPath == nwTemp
|
||||
assert theConf.saveConfig()
|
||||
assert cmpFiles(tmpConf, refConf, [2])
|
||||
assert not theConf.confChanged
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.setWinSize(1105, 655)
|
||||
assert not tmpConf.confChanged
|
||||
assert tmpConf.setWinSize(70, 70)
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.setWinSize(1100, 650)
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetConfPath(nwTemp):
|
||||
assert theConf.setConfPath(None)
|
||||
assert not theConf.setConfPath(path.join("somewhere", "over", "the", "rainbow"))
|
||||
assert theConf.setConfPath(path.join(nwTemp, "novelwriter.conf"))
|
||||
assert theConf.confPath == nwTemp
|
||||
assert theConf.confFile == "novelwriter.conf"
|
||||
assert not theConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetDataPath(nwTemp):
|
||||
assert theConf.setDataPath(None)
|
||||
assert not theConf.setDataPath(path.join("somewhere", "over", "the", "rainbow"))
|
||||
assert theConf.setDataPath(nwTemp)
|
||||
assert theConf.dataPath == nwTemp
|
||||
assert not theConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigLoad():
|
||||
assert theConf.loadConfig()
|
||||
assert not theConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetWinSize(nwTemp, nwRef):
|
||||
tmpConf = path.join(nwTemp, "novelwriter.conf")
|
||||
def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef):
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
assert theConf.setWinSize(1105, 655)
|
||||
assert not theConf.confChanged
|
||||
assert theConf.setWinSize(70, 70)
|
||||
assert theConf.confChanged
|
||||
assert theConf.setWinSize(1100, 650)
|
||||
assert theConf.saveConfig()
|
||||
assert cmpFiles(tmpConf, refConf, [2])
|
||||
assert not theConf.confChanged
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.setTreeColWidths([0, 0, 0])
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.setTreeColWidths([120, 30, 50])
|
||||
assert tmpConf.setProjColWidths([140, 55, 140])
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetTreeColWidths(nwTemp, nwRef):
|
||||
tmpConf = path.join(nwTemp, "novelwriter.conf")
|
||||
def testConfigSetPanePos(tmpConf, nwTemp, nwRef):
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
assert theConf.setTreeColWidths([0, 0, 0])
|
||||
assert theConf.confChanged
|
||||
assert theConf.setTreeColWidths([120, 30, 50])
|
||||
assert theConf.setProjColWidths([140, 55, 140])
|
||||
assert theConf.saveConfig()
|
||||
assert cmpFiles(tmpConf, refConf, [2])
|
||||
assert not theConf.confChanged
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert tmpConf.setMainPanePos([0, 0])
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.setMainPanePos([300, 800])
|
||||
assert tmpConf.setDocPanePos([400, 400])
|
||||
assert tmpConf.setViewPanePos([500, 150])
|
||||
assert tmpConf.setOutlinePanePos([500, 150])
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigSetPanePos(nwTemp, nwRef):
|
||||
tmpConf = path.join(nwTemp, "novelwriter.conf")
|
||||
def testConfigFlags(tmpConf, nwTemp, nwRef):
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
assert theConf.setMainPanePos([0, 0])
|
||||
assert theConf.confChanged
|
||||
assert theConf.setMainPanePos([300, 800])
|
||||
assert theConf.setDocPanePos([400, 400])
|
||||
assert theConf.setViewPanePos([500, 150])
|
||||
assert theConf.setOutlinePanePos([500, 150])
|
||||
assert theConf.saveConfig()
|
||||
assert cmpFiles(tmpConf, refConf, [2])
|
||||
assert not theConf.confChanged
|
||||
testConf = path.join(tmpConf.confPath, "novelwriter.conf")
|
||||
|
||||
assert tmpConf.confPath == nwTemp
|
||||
assert not tmpConf.setShowRefPanel(False)
|
||||
assert tmpConf.setShowRefPanel(True)
|
||||
assert tmpConf.confChanged
|
||||
assert tmpConf.saveConfig()
|
||||
|
||||
assert cmpFiles(testConf, refConf, [2])
|
||||
assert not tmpConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigFlags(nwTemp, nwRef):
|
||||
tmpConf = path.join(nwTemp, "novelwriter.conf")
|
||||
refConf = path.join(nwRef, "novelwriter.conf")
|
||||
assert not theConf.setShowRefPanel(False)
|
||||
assert theConf.setShowRefPanel(True)
|
||||
assert theConf.confChanged
|
||||
assert theConf.saveConfig()
|
||||
assert cmpFiles(tmpConf, refConf, [2])
|
||||
assert not theConf.confChanged
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigErrors(nwTemp):
|
||||
def testConfigErrors(tmpConf):
|
||||
nonPath = path.join("somewhere", "over", "the", "rainbow")
|
||||
assert theConf.initConfig(nonPath, nonPath)
|
||||
assert theConf.hasError
|
||||
assert not theConf.loadConfig()
|
||||
assert not theConf.saveConfig()
|
||||
assert not theConf.loadRecentCache()
|
||||
assert len(theConf.getErrData()) > 0
|
||||
assert tmpConf.initConfig(nonPath, nonPath)
|
||||
assert tmpConf.hasError
|
||||
assert not tmpConf.loadConfig()
|
||||
assert not tmpConf.saveConfig()
|
||||
assert not tmpConf.loadRecentCache()
|
||||
assert len(tmpConf.getErrData()) > 0
|
||||
|
||||
@pytest.mark.core
|
||||
def testConfigInternals():
|
||||
assert theConf._checkNone(None) is None
|
||||
assert theConf._checkNone("None") is None
|
||||
def testConfigInternals(tmpConf):
|
||||
assert tmpConf._checkNone(None) is None
|
||||
assert tmpConf._checkNone("None") is None
|
||||
|
||||
+245
-123
@@ -5,6 +5,7 @@
|
||||
import nw
|
||||
import pytest
|
||||
import json
|
||||
from shutil import copyfile
|
||||
from nwtools import cmpFiles
|
||||
|
||||
from os import path
|
||||
@@ -24,8 +25,9 @@ keyDelay = 2
|
||||
stepDelay = 20
|
||||
|
||||
@pytest.mark.gui
|
||||
def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testMainWindows(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -33,7 +35,7 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
|
||||
# Create new, save, close project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwTempGUI}, True)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
|
||||
@@ -50,14 +52,17 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert not nwGUI.theProject.spellCheck
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwTempGUI, "nwProject.nwx")
|
||||
assert cmpFiles(projFile, path.join(nwRef, "gui", "0_nwProject.nwx"), [2, 6, 7, 8])
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "0_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "0_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
# Re-open project
|
||||
assert nwGUI.openProject(nwTempGUI)
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check that we loaded the data
|
||||
@@ -65,8 +70,8 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert len(nwGUI.theProject.projTree._treeOrder) == 8
|
||||
assert len(nwGUI.theProject.projTree._treeRoots) == 4
|
||||
assert nwGUI.theProject.projTree.trashRoot() is None
|
||||
assert nwGUI.theProject.projPath == nwTempGUI
|
||||
assert nwGUI.theProject.projMeta == path.join(nwTempGUI, "meta")
|
||||
assert nwGUI.theProject.projPath == nwFuncTemp
|
||||
assert nwGUI.theProject.projMeta == path.join(nwFuncTemp, "meta")
|
||||
assert nwGUI.theProject.projFile == "nwProject.nwx"
|
||||
assert nwGUI.theProject.projName == "New Project"
|
||||
assert nwGUI.theProject.bookTitle == ""
|
||||
@@ -266,23 +271,42 @@ def testMainWindows(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert nwGUI.saveProject()
|
||||
|
||||
# Check the files
|
||||
refFile = path.join(nwTempGUI, "nwProject.nwx")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "1_nwProject.nwx"), [2, 6, 7, 8])
|
||||
refFile = path.join(nwTempGUI, "content", "031b4af5197ec.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "1_031b4af5197ec.nwd"))
|
||||
refFile = path.join(nwTempGUI, "content", "1a6562590ef19.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "1_1a6562590ef19.nwd"))
|
||||
refFile = path.join(nwTempGUI, "content", "0e17daca5f3e1.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "1_0e17daca5f3e1.nwd"))
|
||||
refFile = path.join(nwTempGUI, "content", "41cfc0d1f2d12.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "1_41cfc0d1f2d12.nwd"))
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "1_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "1_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
projFile = path.join(nwFuncTemp, "content", "031b4af5197ec.nwd")
|
||||
testFile = path.join(nwTempGUI, "1_031b4af5197ec.nwd")
|
||||
refFile = path.join(nwRef, "gui", "1_031b4af5197ec.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwFuncTemp, "content", "1a6562590ef19.nwd")
|
||||
testFile = path.join(nwTempGUI, "1_1a6562590ef19.nwd")
|
||||
refFile = path.join(nwRef, "gui", "1_1a6562590ef19.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwFuncTemp, "content", "0e17daca5f3e1.nwd")
|
||||
testFile = path.join(nwTempGUI, "1_0e17daca5f3e1.nwd")
|
||||
refFile = path.join(nwRef, "gui", "1_0e17daca5f3e1.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwFuncTemp, "content", "41cfc0d1f2d12.nwd")
|
||||
testFile = path.join(nwTempGUI, "1_41cfc0d1f2d12.nwd")
|
||||
refFile = path.join(nwRef, "gui", "1_41cfc0d1f2d12.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
nwGUI.closeMain()
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testProjectEditor(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testProjectEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -290,8 +314,8 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
|
||||
# Create new, save, open project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwTempGUI}, True)
|
||||
nwGUI.mainConf.backupPath = nwTempGUI
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
nwGUI.mainConf.backupPath = nwFuncTemp
|
||||
|
||||
projEdit = GuiProjectSettings(nwGUI, nwGUI.theProject)
|
||||
projEdit.show()
|
||||
@@ -369,15 +393,18 @@ def testProjectEditor(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwTempGUI, "nwProject.nwx")
|
||||
assert cmpFiles(projFile, path.join(nwRef, "gui", "2_nwProject.nwx"), [2, 8, 9, 10])
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "2_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "2_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testItemEditor(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testItemEditor(qtbot, nwFuncTemp, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -385,7 +412,7 @@ def testItemEditor(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
|
||||
# Create new, save, open project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwTempGUI}, True)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.openDocument("0e17daca5f3e1")
|
||||
|
||||
itemEdit = GuiItemEditor(nwGUI, nwGUI.theProject, "0e17daca5f3e1")
|
||||
@@ -425,24 +452,70 @@ def testItemEditor(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Check the files
|
||||
projFile = path.join(nwTempGUI, "nwProject.nwx")
|
||||
assert cmpFiles(projFile, path.join(nwRef, "gui", "3_nwProject.nwx"), [2, 6, 7, 8])
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempGUI, "3_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "gui", "3_nwProject.nwx")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
nwGUI.closeMain()
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testWritingStatsExport(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwTempGUI)
|
||||
# Create new, save, close project
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.newProject({"projPath": nwFuncTemp}, True)
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwTempGUI
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Add some text to the scene file
|
||||
assert nwGUI.openDocument("0e17daca5f3e1")
|
||||
assert nwGUI.docEditor.insertText(
|
||||
"# Scene One\n\n"
|
||||
"It was the best of times, it was the worst of times, it was the age of wisdom, it was "
|
||||
"the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it "
|
||||
"was the season of Light, it was the season of Darkness, it was the spring of hope, it "
|
||||
"was the winter of despair, we had everything before us, we had nothing before us, we "
|
||||
"were all going direct to Heaven, we were all going direct the other way – in short, the "
|
||||
"period was so far like the present period, that some of its noisiest authorities "
|
||||
"insisted on its being received, for good or for evil, in the superlative degree of "
|
||||
"comparison only.\n\n"
|
||||
)
|
||||
assert nwGUI.saveDocument()
|
||||
|
||||
# Add a note file with some text
|
||||
nwGUI.setFocus(1)
|
||||
nwGUI.treeView.clearSelection()
|
||||
nwGUI.treeView._getTreeItem("71ee45a3c0db9").setSelected(True)
|
||||
nwGUI.treeView.newTreeItem(nwItemType.FILE, None)
|
||||
assert nwGUI.openSelectedItem()
|
||||
assert nwGUI.docEditor.insertText(
|
||||
"# Jane Doe\n\n"
|
||||
"All about Jane.\n\n"
|
||||
)
|
||||
assert nwGUI.saveDocument()
|
||||
qtbot.wait(500) # Ensures that the session length is > 0
|
||||
|
||||
assert nwGUI.saveProject()
|
||||
assert nwGUI.closeProject()
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
# Open again, and check the stats
|
||||
assert nwGUI.openProject(nwFuncTemp)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwFuncTemp
|
||||
sessLog = GuiWritingStats(nwGUI, nwGUI.theProject)
|
||||
sessLog.show()
|
||||
qtbot.wait(stepDelay)
|
||||
@@ -452,15 +525,15 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwTempGUI, "sessionStats.json")
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 3
|
||||
assert jsonData[1]["length"] > 0
|
||||
assert jsonData[1]["newWords"] == 84
|
||||
assert jsonData[1]["novelWords"] == 63
|
||||
assert jsonData[1]["noteWords"] == 27
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[1]["length"] >= 0
|
||||
assert jsonData[1]["newWords"] == 126
|
||||
assert jsonData[1]["novelWords"] == 127
|
||||
assert jsonData[1]["noteWords"] == 5
|
||||
|
||||
# No Novel Files
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
@@ -468,15 +541,15 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwTempGUI, "sessionStats.json")
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[0]["length"] > 0
|
||||
assert jsonData[0]["newWords"] == 27
|
||||
assert jsonData[0]["novelWords"] == 63
|
||||
assert jsonData[0]["noteWords"] == 27
|
||||
assert len(jsonData) == 1
|
||||
assert jsonData[0]["length"] >= 0
|
||||
assert jsonData[0]["newWords"] == 5
|
||||
assert jsonData[0]["novelWords"] == 127
|
||||
assert jsonData[0]["noteWords"] == 5
|
||||
|
||||
# No Note Files
|
||||
qtbot.mouseClick(sessLog.incNovel, Qt.LeftButton)
|
||||
@@ -485,15 +558,15 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwTempGUI, "sessionStats.json")
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 3
|
||||
assert jsonData[1]["length"] > 0
|
||||
assert jsonData[1]["newWords"] == 57
|
||||
assert jsonData[1]["novelWords"] == 63
|
||||
assert jsonData[1]["noteWords"] == 27
|
||||
assert len(jsonData) == 2
|
||||
assert jsonData[1]["length"] >= 0
|
||||
assert jsonData[1]["newWords"] == 121
|
||||
assert jsonData[1]["novelWords"] == 127
|
||||
assert jsonData[1]["noteWords"] == 5
|
||||
|
||||
# No Negative Entries
|
||||
qtbot.mouseClick(sessLog.incNotes, Qt.LeftButton)
|
||||
@@ -502,7 +575,7 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwTempGUI, "sessionStats.json")
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
@@ -515,11 +588,11 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwTempGUI, "sessionStats.json")
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
assert len(jsonData) == 4
|
||||
assert len(jsonData) == 2
|
||||
|
||||
# Group by Day
|
||||
qtbot.mouseClick(sessLog.groupByDay, Qt.LeftButton)
|
||||
@@ -527,7 +600,7 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert sessLog._saveData(sessLog.FMT_JSON)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
jsonStats = path.join(nwTempGUI, "sessionStats.json")
|
||||
jsonStats = path.join(nwFuncTemp, "sessionStats.json")
|
||||
with open(jsonStats, mode="r", encoding="utf-8") as inFile:
|
||||
jsonData = json.loads(inFile.read())
|
||||
|
||||
@@ -541,8 +614,8 @@ def testWritingStatsExport(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testAboutBox(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testAboutBox(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -553,14 +626,13 @@ def testAboutBox(qtbot, nwTempGUI, nwRef, nwTemp):
|
||||
assert msgAbout.pageLicense.document().characterCount() > 100
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
|
||||
msgAbout._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempBuild, "--data=%s" % nwTemp])
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -568,7 +640,7 @@ def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
|
||||
nwGUI.mainConf.lastPath = nwTempBuild
|
||||
nwGUI.mainConf.lastPath = nwLipsum
|
||||
|
||||
nwBuild = GuiBuildNovel(nwGUI, nwGUI.theProject)
|
||||
|
||||
@@ -578,10 +650,17 @@ def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
refFile = path.join(nwTempBuild, "Lorem Ipsum.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "build", "1_LoremIpsum.nwd"), [])
|
||||
refFile = path.join(nwTempBuild, "Lorem Ipsum.htm")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "build", "1_LoremIpsum.htm"), [])
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "1_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "1_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "1_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "1_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Change Title Formats and Flip Switches
|
||||
nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%")
|
||||
@@ -610,10 +689,17 @@ def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
refFile = path.join(nwTempBuild, "Lorem Ipsum.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "build", "2_LoremIpsum.nwd"), [])
|
||||
refFile = path.join(nwTempBuild, "Lorem Ipsum.htm")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "build", "2_LoremIpsum.htm"), [])
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "2_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "2_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "2_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "2_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Putline Mode
|
||||
nwBuild.fmtChapter.setText(r"Chapter %chw%: %title%")
|
||||
@@ -637,19 +723,26 @@ def testBuildTool(qtbot, nwTempBuild, nwLipsum, nwRef, nwTemp):
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_NWD)
|
||||
assert nwBuild._saveDocument(nwBuild.FMT_HTM)
|
||||
|
||||
refFile = path.join(nwTempBuild, "Lorem Ipsum.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "build", "3_LoremIpsum.nwd"), [])
|
||||
refFile = path.join(nwTempBuild, "Lorem Ipsum.htm")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "build", "3_LoremIpsum.htm"), [])
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.nwd")
|
||||
testFile = path.join(nwTempBuild, "3_LoremIpsum.nwd")
|
||||
refFile = path.join(nwRef, "build", "3_LoremIpsum.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "Lorem Ipsum.htm")
|
||||
testFile = path.join(nwTempBuild, "3_LoremIpsum.htm")
|
||||
refFile = path.join(nwRef, "build", "3_LoremIpsum.htm")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwBuild._doClose()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testMergeTool(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
def testMergeSplitTools(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -670,24 +763,11 @@ def testMergeTool(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
assert nwGUI.theProject.projTree["73475cb40a568"] is not None
|
||||
|
||||
refFile = path.join(nwLipsum, "content", "73475cb40a568.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "4_73475cb40a568.nwd"))
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testSplitTool(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
nwGUI.theProject.projTree.setSeed(42)
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
qtbot.wait(stepDelay)
|
||||
projFile = path.join(nwLipsum, "content", "73475cb40a568.nwd")
|
||||
testFile = path.join(nwTempGUI, "4_73475cb40a568.nwd")
|
||||
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Split By Chapter
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
@@ -701,8 +781,11 @@ def testSplitTool(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
assert nwGUI.theProject.projTree["71ee45a3c0db9"] is not None
|
||||
|
||||
# This should give us back the file as it was before
|
||||
refFile = path.join(nwLipsum, "content", "71ee45a3c0db9.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "4_73475cb40a568.nwd"), [1])
|
||||
projFile = path.join(nwLipsum, "content", "71ee45a3c0db9.nwd")
|
||||
testFile = path.join(nwTempGUI, "4_71ee45a3c0db9.nwd")
|
||||
refFile = path.join(nwRef, "gui", "4_73475cb40a568.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [1])
|
||||
|
||||
# Split By Scene
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
@@ -718,12 +801,23 @@ def testSplitTool(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
assert nwGUI.theProject.projTree["31489056e0916"] is not None
|
||||
assert nwGUI.theProject.projTree["98010bd9270f9"] is not None
|
||||
|
||||
refFile = path.join(nwLipsum, "content", "25fc0e7096fc6.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd"))
|
||||
refFile = path.join(nwLipsum, "content", "31489056e0916.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_31489056e0916.nwd"))
|
||||
refFile = path.join(nwLipsum, "content", "98010bd9270f9.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_98010bd9270f9.nwd"))
|
||||
projFile = path.join(nwLipsum, "content", "25fc0e7096fc6.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "31489056e0916.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_31489056e0916.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_31489056e0916.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "98010bd9270f9.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_98010bd9270f9.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_98010bd9270f9.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# Split By Section
|
||||
assert nwGUI.treeView.setSelectedHandle("73475cb40a568")
|
||||
@@ -741,22 +835,41 @@ def testSplitTool(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
assert nwGUI.theProject.projTree["2858dcd1057d3"] is not None
|
||||
assert nwGUI.theProject.projTree["2fca346db6561"] is not None
|
||||
|
||||
refFile = path.join(nwLipsum, "content", "1a6562590ef19.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd"), [1])
|
||||
refFile = path.join(nwLipsum, "content", "031b4af5197ec.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_031b4af5197ec.nwd"))
|
||||
refFile = path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_41cfc0d1f2d12.nwd"))
|
||||
refFile = path.join(nwLipsum, "content", "2858dcd1057d3.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_2858dcd1057d3.nwd"))
|
||||
refFile = path.join(nwLipsum, "content", "2fca346db6561.nwd")
|
||||
assert cmpFiles(refFile, path.join(nwRef, "gui", "5_2fca346db6561.nwd"))
|
||||
projFile = path.join(nwLipsum, "content", "1a6562590ef19.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_25fc0e7096fc6.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_25fc0e7096fc6.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [1])
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "031b4af5197ec.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_031b4af5197ec.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_031b4af5197ec.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "41cfc0d1f2d12.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_41cfc0d1f2d12.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_41cfc0d1f2d12.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "2858dcd1057d3.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_2858dcd1057d3.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_2858dcd1057d3.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
projFile = path.join(nwLipsum, "content", "2fca346db6561.nwd")
|
||||
testFile = path.join(nwTempGUI, "5_2fca346db6561.nwd")
|
||||
refFile = path.join(nwRef, "gui", "5_2fca346db6561.nwd")
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile)
|
||||
|
||||
# qtbot.stopForInteraction()
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testNewProjectWizard(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
def testNewProjectWizard(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
from PyQt5.QtWidgets import QWizard
|
||||
from nw.gui.projwizard import (
|
||||
@@ -764,7 +877,7 @@ def testNewProjectWizard(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
ProjWizardCustomPage, ProjWizardFinalPage
|
||||
)
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -885,9 +998,9 @@ def testNewProjectWizard(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testDocAction(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
def testDocAction(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -1001,8 +1114,8 @@ def testDocAction(qtbot, nwTempGUI, nwLipsum, nwRef, nwTemp):
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testInsertMenu(qtbot, nwTempGUI, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testInsertMenu(qtbot, nwFuncTemp, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwFuncTemp, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
@@ -1049,6 +1162,10 @@ def testInsertMenu(qtbot, nwTempGUI, nwFuncTemp, nwTemp):
|
||||
assert nwGUI.docEditor.getText() == nwGUI.mainConf.fmtDoubleQuotes[1]
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsMSApos.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == nwUnicode.U_MAPOSS
|
||||
nwGUI.docEditor.clear()
|
||||
|
||||
nwGUI.mainMenu.aInsHardBreak.activate(QAction.Trigger)
|
||||
assert nwGUI.docEditor.getText() == " \n"
|
||||
nwGUI.docEditor.clear()
|
||||
@@ -1075,24 +1192,29 @@ def testInsertMenu(qtbot, nwTempGUI, nwFuncTemp, nwTemp):
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testLoadProject(qtbot, nwTempGUI, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempGUI, "--data=%s" % nwTemp])
|
||||
def testLoadProject(qtbot, nwMinimal, nwTemp):
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwMinimal, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwMinimal)
|
||||
assert nwGUI.closeProject()
|
||||
|
||||
nwLoad = GuiProjectLoad(nwGUI)
|
||||
nwLoad.show()
|
||||
|
||||
recentCount = nwLoad.listBox.topLevelItemCount()
|
||||
assert recentCount > 1
|
||||
assert recentCount > 0
|
||||
|
||||
selItem = nwLoad.listBox.topLevelItem(1)
|
||||
selItem = nwLoad.listBox.topLevelItem(0)
|
||||
selPath = selItem.data(nwLoad.C_NAME, Qt.UserRole)
|
||||
assert isinstance(selItem, QTreeWidgetItem)
|
||||
|
||||
nwLoad.selPath.setText("")
|
||||
nwLoad.listBox.setCurrentItem(selItem)
|
||||
nwLoad._doSelectRecent()
|
||||
assert nwLoad.selPath.text() == selPath
|
||||
|
||||
qtbot.mouseClick(nwLoad.buttonBox.button(QDialogButtonBox.Open), Qt.LeftButton)
|
||||
@@ -1121,16 +1243,16 @@ def testLoadProject(qtbot, nwTempGUI, nwTemp):
|
||||
nwGUI.closeMain()
|
||||
|
||||
@pytest.mark.gui
|
||||
def testOutline(qtbot, nwTempBuild, nwLipsum, nwTemp):
|
||||
def testOutline(qtbot, nwLipsum, nwTemp):
|
||||
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwTempBuild, "--data=%s" % nwTemp])
|
||||
nwGUI = nw.main(["--testmode", "--config=%s" % nwLipsum, "--data=%s" % nwTemp])
|
||||
qtbot.addWidget(nwGUI)
|
||||
nwGUI.show()
|
||||
qtbot.waitForWindowShown(nwGUI)
|
||||
qtbot.wait(stepDelay)
|
||||
|
||||
assert nwGUI.openProject(nwLipsum)
|
||||
nwGUI.mainConf.lastPath = nwTempBuild
|
||||
nwGUI.mainConf.lastPath = nwLipsum
|
||||
|
||||
nwGUI.rebuildIndex()
|
||||
nwGUI.tabWidget.setCurrentIndex(nwGUI.idxTabProj)
|
||||
|
||||
+48
-26
@@ -5,22 +5,15 @@
|
||||
import pytest
|
||||
|
||||
from lxml import etree
|
||||
from nwdummy import DummyMain
|
||||
|
||||
from nw.config import Config
|
||||
from nw.core.project import NWProject, NWItem
|
||||
from nw.constants import nwItemClass, nwItemType, nwItemLayout
|
||||
|
||||
theConf = Config()
|
||||
theMain = DummyMain()
|
||||
theMain.mainConf = theConf
|
||||
|
||||
theProject = NWProject(theMain)
|
||||
theItem = NWItem(theProject)
|
||||
nwXML = etree.Element("novelWriterXML")
|
||||
|
||||
@pytest.mark.project
|
||||
def testItemSettersSimple():
|
||||
def testItemSettersSimple(nwDummy):
|
||||
|
||||
theProject = NWProject(nwDummy)
|
||||
theItem = NWItem(theProject)
|
||||
|
||||
# Name
|
||||
theItem.setName("A Name")
|
||||
@@ -113,7 +106,10 @@ def testItemSettersSimple():
|
||||
assert theItem.cursorPos == 1
|
||||
|
||||
@pytest.mark.project
|
||||
def testItemClassSetter():
|
||||
def testItemClassSetter(nwDummy):
|
||||
|
||||
theProject = NWProject(nwDummy)
|
||||
theItem = NWItem(theProject)
|
||||
|
||||
# Class
|
||||
theItem.setClass(None)
|
||||
@@ -138,13 +134,18 @@ def testItemClassSetter():
|
||||
assert theItem.itemClass == nwItemClass.ENTITY
|
||||
theItem.setClass("CUSTOM")
|
||||
assert theItem.itemClass == nwItemClass.CUSTOM
|
||||
theItem.setClass("ARCHIVE")
|
||||
assert theItem.itemClass == nwItemClass.ARCHIVE
|
||||
theItem.setClass("TRASH")
|
||||
assert theItem.itemClass == nwItemClass.TRASH
|
||||
|
||||
@pytest.mark.project
|
||||
def testItemTypeSetter():
|
||||
def testItemTypeSetter(nwDummy):
|
||||
|
||||
# Class
|
||||
theProject = NWProject(nwDummy)
|
||||
theItem = NWItem(theProject)
|
||||
|
||||
# Type
|
||||
theItem.setType(None)
|
||||
assert theItem.itemType == nwItemType.NO_TYPE
|
||||
theItem.setType("NONSENSE")
|
||||
@@ -161,9 +162,12 @@ def testItemTypeSetter():
|
||||
assert theItem.itemType == nwItemType.TRASH
|
||||
|
||||
@pytest.mark.project
|
||||
def testItemLayoutSetter():
|
||||
def testItemLayoutSetter(nwDummy):
|
||||
|
||||
# Class
|
||||
theProject = NWProject(nwDummy)
|
||||
theItem = NWItem(theProject)
|
||||
|
||||
# Layout
|
||||
theItem.setLayout(None)
|
||||
assert theItem.itemLayout == nwItemLayout.NO_LAYOUT
|
||||
theItem.setLayout("NONSENSE")
|
||||
@@ -188,7 +192,25 @@ def testItemLayoutSetter():
|
||||
assert theItem.itemLayout == nwItemLayout.NOTE
|
||||
|
||||
@pytest.mark.project
|
||||
def testItemXMLPackUnpack():
|
||||
def testItemXMLPackUnpack(nwDummy):
|
||||
|
||||
theProject = NWProject(nwDummy)
|
||||
theItem = NWItem(theProject)
|
||||
nwXML = etree.Element("novelWriterXML")
|
||||
|
||||
theItem.setHandle("0123456789abc")
|
||||
theItem.setParent("0123456789abc")
|
||||
theItem.setOrder(1)
|
||||
theItem.setName("A Name")
|
||||
theItem.setClass("NOVEL")
|
||||
theItem.setType("FILE")
|
||||
theItem.setStatus("Main")
|
||||
theItem.setLayout("NOTE")
|
||||
theItem.setExpanded(True)
|
||||
theItem.setParaCount(3)
|
||||
theItem.setWordCount(5)
|
||||
theItem.setCharCount(7)
|
||||
theItem.setCursorPos(11)
|
||||
|
||||
# Pack
|
||||
xContent = etree.SubElement(nwXML, "content")
|
||||
@@ -196,9 +218,9 @@ def testItemXMLPackUnpack():
|
||||
assert etree.tostring(xContent, pretty_print=False, encoding="utf-8") == (
|
||||
b"<content>"
|
||||
b"<item handle=\"0123456789abc\" order=\"1\" parent=\"0123456789abc\">"
|
||||
b"<name>A Name</name><type>TRASH</type><class>TRASH</class>"
|
||||
b"<status>Main</status><expanded>True</expanded>"
|
||||
b"</item>"
|
||||
b"<name>A Name</name><type>FILE</type><class>NOVEL</class><status>New</status>"
|
||||
b"<exported>True</exported><layout>NOTE</layout><charCount>7</charCount>"
|
||||
b"<wordCount>5</wordCount><paraCount>3</paraCount><cursorPos>11</cursorPos></item>"
|
||||
b"</content>"
|
||||
)
|
||||
|
||||
@@ -208,10 +230,10 @@ def testItemXMLPackUnpack():
|
||||
assert theItem.parHandle == "0123456789abc"
|
||||
assert theItem.itemOrder == 1
|
||||
assert theItem.isExpanded
|
||||
assert theItem.charCount == 1
|
||||
assert theItem.wordCount == 1
|
||||
assert theItem.paraCount == 1
|
||||
assert theItem.cursorPos == 1
|
||||
assert theItem.itemClass == nwItemClass.TRASH
|
||||
assert theItem.itemType == nwItemType.TRASH
|
||||
assert theItem.paraCount == 3
|
||||
assert theItem.wordCount == 5
|
||||
assert theItem.charCount == 7
|
||||
assert theItem.cursorPos == 11
|
||||
assert theItem.itemClass == nwItemClass.NOVEL
|
||||
assert theItem.itemType == nwItemType.FILE
|
||||
assert theItem.itemLayout == nwItemLayout.NOTE
|
||||
|
||||
+100
-71
@@ -4,63 +4,66 @@
|
||||
|
||||
import pytest
|
||||
from os import path
|
||||
from shutil import copyfile
|
||||
|
||||
from nwtools import cmpFiles
|
||||
from nwdummy import DummyMain
|
||||
|
||||
from nw.config import Config
|
||||
from nw.core.project import NWProject
|
||||
from nw.core.index import NWIndex
|
||||
from nw.constants import nwItemClass
|
||||
|
||||
theConf = Config()
|
||||
theMain = DummyMain()
|
||||
theMain.mainConf = theConf
|
||||
|
||||
theProject = NWProject(theMain)
|
||||
theProject.projTree.setSeed(42)
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectNewMinimal(nwTempProj, nwRef, nwTemp):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy):
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempProj, "1_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "1_nwProject.nwx")
|
||||
assert theConf.initConfig(nwRef, nwTemp)
|
||||
assert theProject.newProject({"projPath": nwTempProj})
|
||||
assert theProject.setProjectPath(nwTempProj)
|
||||
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
|
||||
assert theProject.newProject({"projPath": nwFuncTemp})
|
||||
assert theProject.setProjectPath(nwFuncTemp)
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert cmpFiles(projFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectOpen(nwTempProj):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
# Check the new project
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
# Open again
|
||||
assert theProject.openProject(projFile)
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectSave(nwTempProj, nwRef):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "1_nwProject.nwx")
|
||||
# Save and close
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert cmpFiles(projFile, refFile, [2, 6, 7, 8])
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
assert not theProject.projChanged
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectOpenTwice(nwTempProj, nwRef):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "1_nwProject.nwx")
|
||||
# Open a second time
|
||||
assert theProject.openProject(projFile)
|
||||
assert not theProject.openProject(projFile)
|
||||
assert theProject.openProject(projFile, overrideLock=True)
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert cmpFiles(projFile, refFile, [2, 6, 7, 8])
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectNewRoot(nwTempProj, nwRef):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
def testProjectNewRoot(nwFuncTemp, nwTempProj, nwRef, nwDummy):
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempProj, "2_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "2_nwProject.nwx")
|
||||
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
|
||||
assert theProject.newProject({"projPath": nwFuncTemp})
|
||||
assert theProject.setProjectPath(nwFuncTemp)
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert theProject.openProject(projFile)
|
||||
|
||||
assert isinstance(theProject.newRoot("Novel", nwItemClass.NOVEL), type(None))
|
||||
assert isinstance(theProject.newRoot("Plot", nwItemClass.PLOT), type(None))
|
||||
assert isinstance(theProject.newRoot("Character", nwItemClass.CHARACTER), type(None))
|
||||
@@ -69,31 +72,48 @@ def testProjectNewRoot(nwTempProj, nwRef):
|
||||
assert isinstance(theProject.newRoot("Object", nwItemClass.OBJECT), str)
|
||||
assert isinstance(theProject.newRoot("Custom1", nwItemClass.CUSTOM), str)
|
||||
assert isinstance(theProject.newRoot("Custom2", nwItemClass.CUSTOM), str)
|
||||
|
||||
assert theProject.projChanged
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert cmpFiles(projFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
assert not theProject.projChanged
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectNewFile(nwTempProj, nwRef):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
def testProjectNewFile(nwFuncTemp, nwTempProj, nwRef, nwDummy):
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempProj, "3_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "3_nwProject.nwx")
|
||||
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
|
||||
assert theProject.newProject({"projPath": nwFuncTemp})
|
||||
assert theProject.setProjectPath(nwFuncTemp)
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert theProject.openProject(projFile)
|
||||
assert isinstance(theProject.newFile("Hello", nwItemClass.NOVEL, "73475cb40a568"), str)
|
||||
|
||||
assert isinstance(theProject.newFile("Hello", nwItemClass.NOVEL, "31489056e0916"), str)
|
||||
assert isinstance(theProject.newFile("Jane", nwItemClass.CHARACTER, "71ee45a3c0db9"), str)
|
||||
assert theProject.projChanged
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
assert cmpFiles(projFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
assert not theProject.projChanged
|
||||
|
||||
@pytest.mark.project
|
||||
def testIndexScanThis(nwTempProj):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
assert theProject.openProject(projFile)
|
||||
def testIndexScanThis(nwMinimal, nwDummy):
|
||||
|
||||
theIndex = NWIndex(theProject, theMain)
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
assert theProject.openProject(nwMinimal)
|
||||
|
||||
theIndex = NWIndex(theProject, nwDummy)
|
||||
|
||||
isValid, theBits, thePos = theIndex.scanThis("tag: this, and this")
|
||||
assert not isValid
|
||||
@@ -135,15 +155,17 @@ def testIndexScanThis(nwTempProj):
|
||||
assert theProject.closeProject()
|
||||
|
||||
@pytest.mark.project
|
||||
def testIndexCheckThese(nwTempProj):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
assert theProject.openProject(projFile)
|
||||
def testIndexCheckThese(nwMinimal, nwDummy):
|
||||
|
||||
theIndex = NWIndex(theProject, theMain)
|
||||
nHandle = "0e17daca5f3e1"
|
||||
nItem = theProject.projTree[nHandle]
|
||||
cHandle = "02d20bbd7e394"
|
||||
cItem = theProject.projTree[cHandle]
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
assert theProject.openProject(nwMinimal)
|
||||
|
||||
theIndex = NWIndex(theProject, nwDummy)
|
||||
nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c")
|
||||
cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER, "afb3043c7b2b3")
|
||||
nItem = theProject.projTree[nHandle]
|
||||
cItem = theProject.projTree[cHandle]
|
||||
|
||||
assert theIndex.scanText(cHandle, (
|
||||
"# Jane Smith\n"
|
||||
@@ -153,7 +175,7 @@ def testIndexCheckThese(nwTempProj):
|
||||
"# Hello World!\n"
|
||||
"@pov: Jane"
|
||||
))
|
||||
assert str(theIndex.tagIndex) == "{'Jane': [2, '02d20bbd7e394', 'CHARACTER', 'T000001']}"
|
||||
assert str(theIndex.tagIndex) == "{'Jane': [2, '%s', 'CHARACTER', 'T000001']}" % cHandle
|
||||
assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"
|
||||
|
||||
assert str(theIndex.checkThese(["@tag", "Jane"], cItem)) == "[True, True]"
|
||||
@@ -168,13 +190,15 @@ def testIndexCheckThese(nwTempProj):
|
||||
assert theProject.closeProject()
|
||||
|
||||
@pytest.mark.project
|
||||
def testIndexMeta(nwTempProj):
|
||||
projFile = path.join(nwTempProj, "nwProject.nwx")
|
||||
assert theProject.openProject(projFile)
|
||||
def testIndexMeta(nwMinimal, nwDummy):
|
||||
|
||||
theIndex = NWIndex(theProject, theMain)
|
||||
nHandle = "0e17daca5f3e1"
|
||||
cHandle = "02d20bbd7e394"
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
assert theProject.openProject(nwMinimal)
|
||||
|
||||
theIndex = NWIndex(theProject, nwDummy)
|
||||
nHandle = theProject.newFile("Hello", nwItemClass.NOVEL, "a508bb932959c")
|
||||
cHandle = theProject.newFile("Jane", nwItemClass.CHARACTER, "afb3043c7b2b3")
|
||||
|
||||
assert theIndex.scanText(cHandle, (
|
||||
"# Jane Smith\n"
|
||||
@@ -191,11 +215,11 @@ def testIndexMeta(nwTempProj):
|
||||
"\n"
|
||||
"Well, not really.\n"
|
||||
))
|
||||
assert str(theIndex.tagIndex) == "{'Jane': [2, '02d20bbd7e394', 'CHARACTER', 'T000001']}"
|
||||
assert str(theIndex.tagIndex) == "{'Jane': [2, '%s', 'CHARACTER', 'T000001']}" % cHandle
|
||||
assert theIndex.novelIndex[nHandle]["T000001"]["title"] == "Hello World!"
|
||||
|
||||
# The novel structure should contain the pointer to the novel file header
|
||||
assert str(theIndex.getNovelStructure()) == "['0e17daca5f3e1:T000001']"
|
||||
assert str(theIndex.getNovelStructure()) == "['%s:T000001']" % nHandle
|
||||
|
||||
# The novel file should have the correct counts
|
||||
cC, wC, pC = theIndex.getCounts(nHandle)
|
||||
@@ -210,21 +234,22 @@ def testIndexMeta(nwTempProj):
|
||||
|
||||
# The character file should have a record of the reference from the novel file
|
||||
theRefs = theIndex.getBackReferenceList(cHandle)
|
||||
assert str(theRefs) == "{'0e17daca5f3e1': 'T000001'}"
|
||||
assert str(theRefs) == "{'%s': 'T000001'}" % nHandle
|
||||
|
||||
assert theProject.closeProject()
|
||||
|
||||
# The two following tests must be at the end as they mess up the config object
|
||||
# and the handle seed. They go into their own folders, but use the same project
|
||||
# object as the test above.
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectNewCustom(nwTempCustom, nwRef, nwTemp):
|
||||
def testProjectNewCustom(nwFuncTemp, nwTempProj, nwRef, nwDummy):
|
||||
|
||||
projFile = path.join(nwFuncTemp, "nwProject.nwx")
|
||||
testFile = path.join(nwTempProj, "4_nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "4_nwProject.nwx")
|
||||
|
||||
projData = {
|
||||
"projName": "Test Custom",
|
||||
"projTitle": "Test Novel",
|
||||
"projAuthors": "Jane Doe\nJohn Doh\n",
|
||||
"projPath": nwTempCustom,
|
||||
"projPath": nwFuncTemp,
|
||||
"popSample": False,
|
||||
"popMinimal": False,
|
||||
"popCustom": True,
|
||||
@@ -240,29 +265,33 @@ def testProjectNewCustom(nwTempCustom, nwRef, nwTemp):
|
||||
"numScenes": 3,
|
||||
"chFolders": True,
|
||||
}
|
||||
theProject.mainConf = theConf
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
|
||||
assert theProject.newProject(projData)
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
projFile = path.join(nwTempCustom, "nwProject.nwx")
|
||||
refFile = path.join(nwRef, "proj", "4_nwProject.nwx")
|
||||
assert cmpFiles(projFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
copyfile(projFile, testFile)
|
||||
assert cmpFiles(testFile, refFile, [2, 6, 7, 8])
|
||||
|
||||
@pytest.mark.project
|
||||
def testProjectNewSample(nwTempSample, nwLipsum, nwRef, nwTemp):
|
||||
def testProjectNewSample(nwFuncTemp, nwRef, nwConf, nwDummy):
|
||||
projData = {
|
||||
"projName": "Test Sample",
|
||||
"projTitle": "Test Novel",
|
||||
"projAuthors": "Jane Doe\nJohn Doh\n",
|
||||
"projPath": nwTempSample,
|
||||
"projPath": nwFuncTemp,
|
||||
"popSample": True,
|
||||
"popMinimal": False,
|
||||
"popCustom": False,
|
||||
}
|
||||
theProject.mainConf = theConf
|
||||
theProject = NWProject(nwDummy)
|
||||
theProject.projTree.setSeed(42)
|
||||
theProject.mainConf = nwConf
|
||||
|
||||
assert theProject.newProject(projData)
|
||||
assert theProject.openProject(nwTempSample)
|
||||
assert theProject.openProject(nwFuncTemp)
|
||||
assert theProject.projName == "Sample Project"
|
||||
assert theProject.saveProject()
|
||||
assert theProject.closeProject()
|
||||
|
||||
Reference in New Issue
Block a user