Add support for mentions references (#2064)
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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):
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user