Add support for mentions references (#2064)

This commit is contained in:
Veronica Berglyd Olsen
2024-10-25 23:17:36 +02:00
committed by GitHub
13 changed files with 190 additions and 131 deletions
+3
View File
@@ -118,6 +118,9 @@ The root folders are closely tied to the tags and reference system. Each folder
the categories of tags that can be used to reference them. For more information about the tags
listed, see :ref:`a_references_references`.
There is also a ``@mention`` keyword that can be used to reference any tag.
See :ref:`a_references_references` for more details.
.. note::
You can rename root folders to whatever you want. However, this doesn't change the reference
keyword or what they do.
+6
View File
@@ -162,6 +162,12 @@ reference keywords allow multiple values.
Custom references in the current section. The target must be a note tag in a **Custom** type
root folder. The custom folder are for any other category of notes you may want to use.
``@mention``
Anything mentioned, but not present in the current section. It is intended for those cases where
you reveal details about a character or place in a scene without it being otherwise a part of
it. This can be useful when checking for consistency later. Any tag in any root note folder can
be listed under mentions.
The syntax highlighter will alert the user that the tags and references are used correctly, and
that the tags referenced exist.
+1
View File
@@ -165,6 +165,7 @@ a key or key combination for the inserted content.
":kbd:`Ctrl+K`, :kbd:`G`", "Insert a ``@tag`` keyword"
":kbd:`Ctrl+K`, :kbd:`H`", "Insert a short description comment"
":kbd:`Ctrl+K`, :kbd:`L`", "Insert a ``@location`` keyword"
":kbd:`Ctrl+K`, :kbd:`M`", "Insert a ``@mention`` keyword"
":kbd:`Ctrl+K`, :kbd:`O`", "Insert an ``@object`` keyword"
":kbd:`Ctrl+K`, :kbd:`P`", "Insert a ``@plot`` keyword"
":kbd:`Ctrl+K`, :kbd:`S`", "Insert a synopsis comment"
+50 -47
View File
@@ -145,34 +145,35 @@ class nwFiles:
class nwKeyWords:
TAG_KEY = "@tag"
POV_KEY = "@pov"
FOCUS_KEY = "@focus"
CHAR_KEY = "@char"
PLOT_KEY = "@plot"
TIME_KEY = "@time"
WORLD_KEY = "@location"
OBJECT_KEY = "@object"
ENTITY_KEY = "@entity"
CUSTOM_KEY = "@custom"
TAG_KEY = "@tag"
POV_KEY = "@pov"
FOCUS_KEY = "@focus"
CHAR_KEY = "@char"
PLOT_KEY = "@plot"
TIME_KEY = "@time"
WORLD_KEY = "@location"
OBJECT_KEY = "@object"
ENTITY_KEY = "@entity"
CUSTOM_KEY = "@custom"
MENTION_KEY = "@mention"
# Set of Valid Keys
VALID_KEYS = {
TAG_KEY, POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY,
WORLD_KEY, OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY
WORLD_KEY, OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, MENTION_KEY
}
# Map from Keys to Item Class
KEY_CLASS = {
POV_KEY: nwItemClass.CHARACTER,
FOCUS_KEY: nwItemClass.CHARACTER,
CHAR_KEY: nwItemClass.CHARACTER,
PLOT_KEY: nwItemClass.PLOT,
TIME_KEY: nwItemClass.TIMELINE,
WORLD_KEY: nwItemClass.WORLD,
OBJECT_KEY: nwItemClass.OBJECT,
ENTITY_KEY: nwItemClass.ENTITY,
CUSTOM_KEY: nwItemClass.CUSTOM,
POV_KEY: nwItemClass.CHARACTER,
FOCUS_KEY: nwItemClass.CHARACTER,
CHAR_KEY: nwItemClass.CHARACTER,
PLOT_KEY: nwItemClass.PLOT,
TIME_KEY: nwItemClass.TIMELINE,
WORLD_KEY: nwItemClass.WORLD,
OBJECT_KEY: nwItemClass.OBJECT,
ENTITY_KEY: nwItemClass.ENTITY,
CUSTOM_KEY: nwItemClass.CUSTOM,
}
@@ -236,35 +237,37 @@ class nwLabels:
"note": QT_TRANSLATE_NOOP("Constant", "Project Note"),
}
KEY_NAME = {
nwKeyWords.TAG_KEY: QT_TRANSLATE_NOOP("Constant", "Tag"),
nwKeyWords.POV_KEY: QT_TRANSLATE_NOOP("Constant", "Point of View"),
nwKeyWords.FOCUS_KEY: QT_TRANSLATE_NOOP("Constant", "Focus"),
nwKeyWords.CHAR_KEY: QT_TRANSLATE_NOOP("Constant", "Characters"),
nwKeyWords.PLOT_KEY: QT_TRANSLATE_NOOP("Constant", "Plot"),
nwKeyWords.TIME_KEY: QT_TRANSLATE_NOOP("Constant", "Timeline"),
nwKeyWords.WORLD_KEY: QT_TRANSLATE_NOOP("Constant", "Locations"),
nwKeyWords.OBJECT_KEY: QT_TRANSLATE_NOOP("Constant", "Objects"),
nwKeyWords.ENTITY_KEY: QT_TRANSLATE_NOOP("Constant", "Entities"),
nwKeyWords.CUSTOM_KEY: QT_TRANSLATE_NOOP("Constant", "Custom"),
nwKeyWords.TAG_KEY: QT_TRANSLATE_NOOP("Constant", "Tag"),
nwKeyWords.POV_KEY: QT_TRANSLATE_NOOP("Constant", "Point of View"),
nwKeyWords.FOCUS_KEY: QT_TRANSLATE_NOOP("Constant", "Focus"),
nwKeyWords.CHAR_KEY: QT_TRANSLATE_NOOP("Constant", "Characters"),
nwKeyWords.PLOT_KEY: QT_TRANSLATE_NOOP("Constant", "Plot"),
nwKeyWords.TIME_KEY: QT_TRANSLATE_NOOP("Constant", "Timeline"),
nwKeyWords.WORLD_KEY: QT_TRANSLATE_NOOP("Constant", "Locations"),
nwKeyWords.OBJECT_KEY: QT_TRANSLATE_NOOP("Constant", "Objects"),
nwKeyWords.ENTITY_KEY: QT_TRANSLATE_NOOP("Constant", "Entities"),
nwKeyWords.CUSTOM_KEY: QT_TRANSLATE_NOOP("Constant", "Custom"),
nwKeyWords.MENTION_KEY: QT_TRANSLATE_NOOP("Constant", "Mentions"),
}
OUTLINE_COLS = {
nwOutline.TITLE: QT_TRANSLATE_NOOP("Constant", "Title"),
nwOutline.LEVEL: QT_TRANSLATE_NOOP("Constant", "Level"),
nwOutline.LABEL: QT_TRANSLATE_NOOP("Constant", "Document"),
nwOutline.LINE: QT_TRANSLATE_NOOP("Constant", "Line"),
nwOutline.CCOUNT: QT_TRANSLATE_NOOP("Constant", "Chars"),
nwOutline.WCOUNT: QT_TRANSLATE_NOOP("Constant", "Words"),
nwOutline.PCOUNT: QT_TRANSLATE_NOOP("Constant", "Pars"),
nwOutline.POV: QT_TRANSLATE_NOOP("Constant", "POV"),
nwOutline.FOCUS: QT_TRANSLATE_NOOP("Constant", "Focus"),
nwOutline.CHAR: KEY_NAME[nwKeyWords.CHAR_KEY],
nwOutline.PLOT: KEY_NAME[nwKeyWords.PLOT_KEY],
nwOutline.WORLD: KEY_NAME[nwKeyWords.WORLD_KEY],
nwOutline.TIME: KEY_NAME[nwKeyWords.TIME_KEY],
nwOutline.OBJECT: KEY_NAME[nwKeyWords.OBJECT_KEY],
nwOutline.ENTITY: KEY_NAME[nwKeyWords.ENTITY_KEY],
nwOutline.CUSTOM: KEY_NAME[nwKeyWords.CUSTOM_KEY],
nwOutline.SYNOP: QT_TRANSLATE_NOOP("Constant", "Synopsis"),
nwOutline.TITLE: QT_TRANSLATE_NOOP("Constant", "Title"),
nwOutline.LEVEL: QT_TRANSLATE_NOOP("Constant", "Level"),
nwOutline.LABEL: QT_TRANSLATE_NOOP("Constant", "Document"),
nwOutline.LINE: QT_TRANSLATE_NOOP("Constant", "Line"),
nwOutline.CCOUNT: QT_TRANSLATE_NOOP("Constant", "Chars"),
nwOutline.WCOUNT: QT_TRANSLATE_NOOP("Constant", "Words"),
nwOutline.PCOUNT: QT_TRANSLATE_NOOP("Constant", "Pars"),
nwOutline.POV: QT_TRANSLATE_NOOP("Constant", "POV"),
nwOutline.FOCUS: QT_TRANSLATE_NOOP("Constant", "Focus"),
nwOutline.CHAR: KEY_NAME[nwKeyWords.CHAR_KEY],
nwOutline.PLOT: KEY_NAME[nwKeyWords.PLOT_KEY],
nwOutline.WORLD: KEY_NAME[nwKeyWords.WORLD_KEY],
nwOutline.TIME: KEY_NAME[nwKeyWords.TIME_KEY],
nwOutline.OBJECT: KEY_NAME[nwKeyWords.OBJECT_KEY],
nwOutline.ENTITY: KEY_NAME[nwKeyWords.ENTITY_KEY],
nwOutline.CUSTOM: KEY_NAME[nwKeyWords.CUSTOM_KEY],
nwOutline.MENTION: KEY_NAME[nwKeyWords.MENTION_KEY],
nwOutline.SYNOP: QT_TRANSLATE_NOOP("Constant", "Synopsis"),
}
BUILD_FMT = {
nwBuildFmt.ODT: QT_TRANSLATE_NOOP("Constant", "Open Document (.odt)"),
+24 -13
View File
@@ -487,13 +487,14 @@ class NWIndex:
if nBits == 0:
return []
# Check that the key is valid
isGood[0] = tBits[0] in nwKeyWords.VALID_KEYS
# Check that the keyword is valid
kBit = tBits[0]
isGood[0] = kBit in nwKeyWords.VALID_KEYS
if not isGood[0] or nBits == 1:
return isGood
# For a tag, only the first value is accepted, the rest are ignored
if tBits[0] == nwKeyWords.TAG_KEY and nBits > 1:
if kBit == nwKeyWords.TAG_KEY and nBits > 1:
check, _ = self.parseValue(tBits[1])
if check in self._tagsIndex:
isGood[1] = self._tagsIndex.tagHandle(check) == tHandle
@@ -501,12 +502,16 @@ class NWIndex:
isGood[1] = True
return isGood
if kBit == nwKeyWords.MENTION_KEY and nBits > 1:
isGood[1:nBits] = [aBit in self._tagsIndex for aBit in tBits[1:nBits]]
return isGood
# If we're still here, we check that the references exist
# Class references cannot have the | symbol in them
refKey = nwKeyWords.KEY_CLASS[tBits[0]].name
for n in range(1, nBits):
if (aBit := tBits[n]) in self._tagsIndex:
isGood[n] = self._tagsIndex.tagClass(aBit) == refKey and "|" not in aBit
if rClass := nwKeyWords.KEY_CLASS.get(kBit):
for n in range(1, nBits):
if (aBit := tBits[n]) in self._tagsIndex:
isGood[n] = self._tagsIndex.tagClass(aBit) == rClass.name and "|" not in aBit
return isGood
@@ -681,9 +686,10 @@ class NWIndex:
"""Return all tags used by a specific document."""
return self._itemIndex.allItemTags(tHandle) if tHandle else []
def getClassTags(self, itemClass: nwItemClass) -> list[str]:
def getClassTags(self, itemClass: nwItemClass | None) -> list[str]:
"""Return all tags based on itemClass."""
return self._tagsIndex.filterTagNames(itemClass.name)
name = None if itemClass is None else itemClass.name
return self._tagsIndex.filterTagNames(name)
def getTagsData(
self, activeOnly: bool = True
@@ -780,11 +786,16 @@ class TagsIndex:
"""Get the class of a given tag."""
return self._tags.get(tagKey.lower(), {}).get("class", None)
def filterTagNames(self, className: str) -> list[str]:
def filterTagNames(self, className: str | None) -> list[str]:
"""Get a list of tag names for a given class."""
return [
x.get("name", "") for x in self._tags.values() if x.get("class", "") == className
]
if className is None:
return [
x.get("name", "") for x in self._tags.values()
]
else:
return [
x.get("name", "") for x in self._tags.values() if x.get("class", "") == className
]
##
# Pack/Unpack
+18 -17
View File
@@ -158,23 +158,24 @@ class nwFocus(Enum):
class nwOutline(Enum):
TITLE = 0
LEVEL = 1
LABEL = 2
LINE = 3
CCOUNT = 4
WCOUNT = 5
PCOUNT = 6
POV = 7
FOCUS = 8
CHAR = 9
PLOT = 10
TIME = 11
WORLD = 12
OBJECT = 13
ENTITY = 14
CUSTOM = 15
SYNOP = 16
TITLE = 0
LEVEL = 1
LABEL = 2
LINE = 3
CCOUNT = 4
WCOUNT = 5
PCOUNT = 6
POV = 7
FOCUS = 8
CHAR = 9
PLOT = 10
TIME = 11
WORLD = 12
OBJECT = 13
ENTITY = 14
CUSTOM = 15
MENTION = 16
SYNOP = 17
class nwBuildFmt(Enum):
+1 -1
View File
@@ -2176,7 +2176,7 @@ class MetaCompleter(QMenu):
suffix = ""
options = list(filter(
lambda x: lookup in x.lower(), SHARED.project.index.getClassTags(
nwKeyWords.KEY_CLASS.get(kw.strip(), nwItemClass.NO_CLASS)
nwKeyWords.KEY_CLASS.get(kw.strip())
)
))[:15]
+11 -10
View File
@@ -535,16 +535,17 @@ class GuiMainMenu(QMenuBar):
# Insert > Tags and References
self.mInsKeywords = self.insMenu.addMenu(self.tr("Tags and References"))
self.mInsKWItems = {}
self.mInsKWItems[nwKeyWords.TAG_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, G")
self.mInsKWItems[nwKeyWords.POV_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, V")
self.mInsKWItems[nwKeyWords.FOCUS_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, F")
self.mInsKWItems[nwKeyWords.CHAR_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, C")
self.mInsKWItems[nwKeyWords.PLOT_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, P")
self.mInsKWItems[nwKeyWords.TIME_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, T")
self.mInsKWItems[nwKeyWords.WORLD_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, L")
self.mInsKWItems[nwKeyWords.OBJECT_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, O")
self.mInsKWItems[nwKeyWords.ENTITY_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, E")
self.mInsKWItems[nwKeyWords.CUSTOM_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, X")
self.mInsKWItems[nwKeyWords.TAG_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, G")
self.mInsKWItems[nwKeyWords.POV_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, V")
self.mInsKWItems[nwKeyWords.FOCUS_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, F")
self.mInsKWItems[nwKeyWords.CHAR_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, C")
self.mInsKWItems[nwKeyWords.PLOT_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, P")
self.mInsKWItems[nwKeyWords.TIME_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, T")
self.mInsKWItems[nwKeyWords.WORLD_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, L")
self.mInsKWItems[nwKeyWords.OBJECT_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, O")
self.mInsKWItems[nwKeyWords.ENTITY_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, E")
self.mInsKWItems[nwKeyWords.CUSTOM_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, X")
self.mInsKWItems[nwKeyWords.MENTION_KEY] = (QAction(self.mInsKeywords), "Ctrl+K, M")
for n, keyWord in enumerate(self.mInsKWItems):
self.mInsKWItems[keyWord][0].setText(trConst(nwLabels.KEY_NAME[keyWord]))
self.mInsKWItems[keyWord][0].setShortcut(self.mInsKWItems[keyWord][1])
+36 -34
View File
@@ -312,43 +312,45 @@ class GuiOutlineToolBar(QToolBar):
class GuiOutlineTree(QTreeWidget):
DEF_WIDTH = {
nwOutline.TITLE: 200,
nwOutline.LEVEL: 40,
nwOutline.LABEL: 150,
nwOutline.LINE: 40,
nwOutline.CCOUNT: 50,
nwOutline.WCOUNT: 50,
nwOutline.PCOUNT: 50,
nwOutline.POV: 100,
nwOutline.FOCUS: 100,
nwOutline.CHAR: 100,
nwOutline.PLOT: 100,
nwOutline.TIME: 100,
nwOutline.WORLD: 100,
nwOutline.OBJECT: 100,
nwOutline.ENTITY: 100,
nwOutline.CUSTOM: 100,
nwOutline.SYNOP: 200,
nwOutline.TITLE: 200,
nwOutline.LEVEL: 40,
nwOutline.LABEL: 150,
nwOutline.LINE: 40,
nwOutline.CCOUNT: 50,
nwOutline.WCOUNT: 50,
nwOutline.PCOUNT: 50,
nwOutline.POV: 100,
nwOutline.FOCUS: 100,
nwOutline.CHAR: 100,
nwOutline.PLOT: 100,
nwOutline.TIME: 100,
nwOutline.WORLD: 100,
nwOutline.OBJECT: 100,
nwOutline.ENTITY: 100,
nwOutline.CUSTOM: 100,
nwOutline.MENTION: 100,
nwOutline.SYNOP: 200,
}
DEF_HIDDEN = {
nwOutline.TITLE: False,
nwOutline.LEVEL: True,
nwOutline.LABEL: False,
nwOutline.LINE: True,
nwOutline.CCOUNT: True,
nwOutline.WCOUNT: False,
nwOutline.PCOUNT: False,
nwOutline.POV: False,
nwOutline.FOCUS: True,
nwOutline.CHAR: False,
nwOutline.PLOT: False,
nwOutline.TIME: True,
nwOutline.WORLD: False,
nwOutline.OBJECT: True,
nwOutline.ENTITY: True,
nwOutline.CUSTOM: True,
nwOutline.SYNOP: False,
nwOutline.TITLE: False,
nwOutline.LEVEL: True,
nwOutline.LABEL: False,
nwOutline.LINE: True,
nwOutline.CCOUNT: True,
nwOutline.WCOUNT: False,
nwOutline.PCOUNT: False,
nwOutline.POV: False,
nwOutline.FOCUS: True,
nwOutline.CHAR: False,
nwOutline.PLOT: False,
nwOutline.TIME: True,
nwOutline.WORLD: False,
nwOutline.OBJECT: True,
nwOutline.ENTITY: True,
nwOutline.CUSTOM: True,
nwOutline.MENTION: True,
nwOutline.SYNOP: False,
}
D_HANDLE = QtUserRole
+3 -2
View File
@@ -1,13 +1,14 @@
%%~name: Making a Scene
%%~path: 6a2d6d5f4f401/636b6aa9b697b
%%~kind: NOVEL/DOCUMENT
%%~hash: c7e664867218b3a9aac5c12119ef0ec63da2e5cc
%%~date: Unknown/2024-04-18 17:56:30
%%~hash: 349d9ce3d59ad241d63b01380c53a7fb26ce9f19
%%~date: Unknown/2024-10-24 23:44:27
### Making a Scene
@pov: Jane
@char: John, Jane
@location: Earth
@mention: Bob, Space
A scene is defined by a level three heading, like the one at the top of this page. The scene will be assigned to the chapter preceding it in the project tree. The scene document can be sorted after the chapter document, or as a child of the chapter. Both result in the same output in the end, so it is a matter of preference.
+4 -4
View File
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='utf-8'?>
<novelWriterXML appVersion="2.6a2" hexVersion="0x020600a2" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-24 16:26:12">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2077" autoCount="279" editTime="93511">
<novelWriterXML appVersion="2.6a2" hexVersion="0x020600a2" fileVersion="1.5" fileRevision="4" timeStamp="2024-10-24 23:58:23">
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="2088" autoCount="280" editTime="93793">
<name>Sample Project</name>
<author>Jane Smith</author>
</project>
@@ -58,11 +58,11 @@
<name status="sf24ce6" import="ia857f0" active="yes">Chapter One</name>
</item>
<item handle="636b6aa9b697b" parent="6a2d6d5f4f401" root="7031beac91f75" order="0" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="2937" wordCount="520" paraCount="15" cursorPos="4" />
<meta expanded="no" heading="H3" charCount="2937" wordCount="520" paraCount="15" cursorPos="19" />
<name status="s90e6c9" import="ia857f0" active="yes">Making a Scene</name>
</item>
<item handle="bc0cbd2a407f3" parent="6a2d6d5f4f401" root="7031beac91f75" order="1" type="FILE" class="NOVEL" layout="DOCUMENT">
<meta expanded="no" heading="H3" charCount="563" wordCount="108" paraCount="3" cursorPos="691" />
<meta expanded="no" heading="H3" charCount="548" wordCount="108" paraCount="3" cursorPos="650" />
<name status="s90e6c9" import="ia857f0" active="yes">Another Scene</name>
</item>
<item handle="ba8a28a246524" parent="7031beac91f75" root="7031beac91f75" order="4" type="FILE" class="NOVEL" layout="DOCUMENT">
+31 -1
View File
@@ -224,13 +224,17 @@ def testCoreIndex_CheckThese(mockGUI, fncPath, mockRnd):
nHandle = project.newFile("Hello", C.hNovelRoot)
cHandle = project.newFile("Jane", C.hCharRoot)
wHandle = project.newFile("Earth", C.hWorldRoot)
assert isinstance(nHandle, str)
assert isinstance(cHandle, str)
assert isinstance(wHandle, str)
nItem = project.tree[nHandle]
cItem = project.tree[cHandle]
wItem = project.tree[wHandle]
assert isinstance(nItem, NWItem)
assert isinstance(cItem, NWItem)
assert isinstance(wItem, NWItem)
assert index.rootChangedSince(C.hNovelRoot, 0) is False
assert index.rootChangedSince(None, 0) is False
@@ -242,21 +246,31 @@ def testCoreIndex_CheckThese(mockGUI, fncPath, mockRnd):
"@tag:\n"
"@:\n"
))
assert index.scanText(wHandle, (
"# Earth\n"
"@tag: Earth\n"
))
assert index.scanText(nHandle, (
"# Hello World!\n"
"@pov: Jane\n"
"@location: Earth\n"
"@invalid: John\n" # Checks for issue #688
))
assert index._tagsIndex.tagHandle("Earth") == wHandle
assert index._tagsIndex.tagHeading("Earth") == "T0001"
assert index._tagsIndex.tagClass("Earth") == "WORLD"
assert index._tagsIndex.tagHandle("Jane") == cHandle
assert index._tagsIndex.tagHeading("Jane") == "T0001"
assert index._tagsIndex.tagClass("Jane") == "CHARACTER"
assert index.getItemHeading(nHandle, "T0001").title == "Hello World!" # type: ignore
assert index.getReferences(nHandle, "T0001") == {
"@char": [],
"@custom": [],
"@entity": [],
"@focus": [],
"@location": [],
"@location": ["Earth"],
"@object": [],
"@plot": [],
"@pov": ["Jane"],
@@ -283,13 +297,29 @@ def testCoreIndex_CheckThese(mockGUI, fncPath, mockRnd):
assert index.checkThese(["@tag", "John"], nHandle) == [True, True]
assert index.checkThese(["@pov", "John"], nHandle) == [True, False]
assert index.checkThese(["@pov", "Jane"], nHandle) == [True, True]
assert index.checkThese(["@mention", "Jane"], nHandle) == [True, True]
assert index.checkThese(["@ pov", "Jane"], nHandle) == [False, False]
assert index.checkThese(["@what", "Jane"], nHandle) == [False, False]
# Two w/Class Check
assert index.checkThese(["@pov", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@focus", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@char", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@plot", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@time", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@location", "Earth"], nHandle) == [True, True]
assert index.checkThese(["@object", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@entity", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@custom", "Earth"], nHandle) == [True, False]
assert index.checkThese(["@mention", "Earth"], nHandle) == [True, True]
# Three Items
assert index.checkThese(["@tag", "Jane", "John"], cHandle) == [True, True, False]
assert index.checkThese(["@who", "Jane", "John"], cHandle) == [False, False, False]
assert index.checkThese(["@pov", "Jane", "John"], nHandle) == [True, True, False]
assert index.checkThese(["@pov", "Jane", "Earth"], nHandle) == [True, True, False]
assert index.checkThese(["@mention", "Jane", "Earth"], nHandle) == [True, True, True]
assert index.checkThese(["@mention", "Jane", "Stuff"], nHandle) == [True, True, False]
# Parse a Checked Value
assert index.parseValue("Jane | Jane Smith") == ("Jane", "Jane Smith")
+2 -2
View File
@@ -165,12 +165,12 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, projPath):
# Current Order
order = [outlineTree._colIdx[col] for col in outlineTree._treeOrder]
assert order == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
assert order == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
# Move 3 to 0
outlineTree._columnMoved(0, 3, 0)
order = [outlineTree._colIdx[col] for col in outlineTree._treeOrder]
assert order == [3, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
assert order == [3, 0, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
# qtbot.stop()