Add project note briefs (#1618)
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Synopsis": "Synopsis",
|
"Synopsis": "Synopsis",
|
||||||
"Comment": "Comment",
|
"Comment": "Comment",
|
||||||
|
"Brief": "Brief",
|
||||||
"Notes": "Notes",
|
"Notes": "Notes",
|
||||||
"Tag": "Tag",
|
"Tag": "Tag",
|
||||||
"Point of View": "Point of View",
|
"Point of View": "Point of View",
|
||||||
|
|||||||
@@ -406,6 +406,7 @@ class ProjectBuilder:
|
|||||||
|
|
||||||
chSynop = self.tr("Summary of the chapter.")
|
chSynop = self.tr("Summary of the chapter.")
|
||||||
scSynop = self.tr("Summary of the scene.")
|
scSynop = self.tr("Summary of the scene.")
|
||||||
|
bfNote = self.tr("A brief description.")
|
||||||
|
|
||||||
# Create chapters
|
# Create chapters
|
||||||
if numChapters > 0:
|
if numChapters > 0:
|
||||||
@@ -446,7 +447,11 @@ class ProjectBuilder:
|
|||||||
aHandle = project.newFile(noteTitles[newRoot], rHandle)
|
aHandle = project.newFile(noteTitles[newRoot], rHandle)
|
||||||
ntTag = simplified(noteTitles[newRoot]).replace(" ", "")
|
ntTag = simplified(noteTitles[newRoot]).replace(" ", "")
|
||||||
aDoc = project.storage.getDocument(aHandle)
|
aDoc = project.storage.getDocument(aHandle)
|
||||||
aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n")
|
aDoc.writeDocument(
|
||||||
|
f"# {noteTitles[newRoot]}\n\n"
|
||||||
|
f"@tag: {ntTag}\n\n"
|
||||||
|
f"% Brief: {bfNote}\n\n"
|
||||||
|
)
|
||||||
|
|
||||||
# Also add the archive and trash folders
|
# Also add the archive and trash folders
|
||||||
project.newRoot(nwItemClass.ARCHIVE)
|
project.newRoot(nwItemClass.ARCHIVE)
|
||||||
|
|||||||
+22
-10
@@ -36,7 +36,7 @@ from typing import TYPE_CHECKING, ItemsView, Iterable, Iterator
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter import SHARED
|
from novelwriter import SHARED
|
||||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
from novelwriter.enum import nwComment, nwItemClass, nwItemType, nwItemLayout
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.common import checkInt, isHandle, isItemClass, isTitleTag, jsonEncode
|
from novelwriter.common import checkInt, isHandle, isItemClass, isTitleTag, jsonEncode
|
||||||
from novelwriter.constants import nwFiles, nwKeyWords, nwRegEx, nwUnicode, nwHeaders
|
from novelwriter.constants import nwFiles, nwKeyWords, nwRegEx, nwUnicode, nwHeaders
|
||||||
@@ -338,14 +338,9 @@ class NWIndex:
|
|||||||
|
|
||||||
elif line.startswith("%"):
|
elif line.startswith("%"):
|
||||||
if cTitle != TT_NONE:
|
if cTitle != TT_NONE:
|
||||||
toCheck = line[1:].lstrip()
|
cStyle, cText, _ = processComment(line)
|
||||||
synTag = toCheck[:9].lower()
|
if cStyle in (nwComment.BRIEF, nwComment.SYNOPSIS):
|
||||||
tLen = len(line)
|
self._itemIndex.setHeadingSynopsis(tHandle, cTitle, cText)
|
||||||
cLen = len(toCheck)
|
|
||||||
cOff = tLen - cLen
|
|
||||||
if synTag == "synopsis:":
|
|
||||||
sText = line[cOff+9:].strip()
|
|
||||||
self._itemIndex.setHeadingSynopsis(tHandle, cTitle, sText)
|
|
||||||
|
|
||||||
# Count words for remaining text after last heading
|
# Count words for remaining text after last heading
|
||||||
if pTitle != TT_NONE:
|
if pTitle != TT_NONE:
|
||||||
@@ -1269,9 +1264,26 @@ class IndexHeading:
|
|||||||
|
|
||||||
|
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
# Simple Word Counter
|
# Text Processing Functions
|
||||||
# =============================================================================================== #
|
# =============================================================================================== #
|
||||||
|
|
||||||
|
CLASSIFIERS = {
|
||||||
|
"brief": nwComment.BRIEF,
|
||||||
|
"synopsis": nwComment.SYNOPSIS,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def processComment(text: str) -> tuple[nwComment, str, int]:
|
||||||
|
"""Extract comment style and text. Should only be called on text
|
||||||
|
starting with a %.
|
||||||
|
"""
|
||||||
|
check = text[1:].lstrip()
|
||||||
|
classifier, _, content = check.partition(":")
|
||||||
|
if content and (clean := classifier.strip().lower()) in CLASSIFIERS:
|
||||||
|
return CLASSIFIERS[clean], content.strip(), text.find(":") + 1
|
||||||
|
return nwComment.PLAIN, check, 0
|
||||||
|
|
||||||
|
|
||||||
def countWords(text: str) -> tuple[int, int, int]:
|
def countWords(text: str) -> tuple[int, int, int]:
|
||||||
"""Count words in a piece of text, skipping special syntax and
|
"""Count words in a piece of text, skipping special syntax and
|
||||||
comments.
|
comments.
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ VALID_MAP = {
|
|||||||
"GuiManuscriptBuild": {
|
"GuiManuscriptBuild": {
|
||||||
"winWidth", "winHeight", "fmtWidth", "sumWidth",
|
"winWidth", "winHeight", "fmtWidth", "sumWidth",
|
||||||
},
|
},
|
||||||
|
"GuiDocViewerPanel": {
|
||||||
|
"colWidths",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,10 @@ class ToHtml(Tokenizer):
|
|||||||
para.append(stripEscape(tTemp.rstrip()))
|
para.append(stripEscape(tTemp.rstrip()))
|
||||||
|
|
||||||
elif tType == self.T_SYNOPSIS and self._doSynopsis:
|
elif tType == self.T_SYNOPSIS and self._doSynopsis:
|
||||||
lines.append(self._formatSynopsis(tText))
|
lines.append(self._formatSynopsis(tText, True))
|
||||||
|
|
||||||
|
elif tType == self.T_BRIEF and self._doSynopsis:
|
||||||
|
lines.append(self._formatSynopsis(tText, False))
|
||||||
|
|
||||||
elif tType == self.T_COMMENT and self._doComments:
|
elif tType == self.T_COMMENT and self._doComments:
|
||||||
lines.append(self._formatComments(tText))
|
lines.append(self._formatComments(tText))
|
||||||
@@ -454,9 +457,9 @@ class ToHtml(Tokenizer):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _formatSynopsis(self, text: str) -> str:
|
def _formatSynopsis(self, text: str, synopsis: bool) -> str:
|
||||||
"""Apply HTML formatting to synopsis."""
|
"""Apply HTML formatting to synopsis."""
|
||||||
sSynop = self._localLookup("Synopsis")
|
sSynop = self._localLookup("Synopsis") if synopsis else self._localLookup("Brief")
|
||||||
if self._genMode == self.M_PREVIEW:
|
if self._genMode == self.M_PREVIEW:
|
||||||
return f"<p class='comment'><span class='synopsis'>{sSynop}:</span> {text}</p>\n"
|
return f"<p class='comment'><span class='synopsis'>{sSynop}:</span> {text}</p>\n"
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ from pathlib import Path
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
||||||
|
from novelwriter.core.index import processComment
|
||||||
|
|
||||||
from novelwriter.enum import nwItemLayout
|
from novelwriter.enum import nwComment, nwItemLayout
|
||||||
from novelwriter.common import formatTimeStamp, numberToRoman, checkInt
|
from novelwriter.common import formatTimeStamp, numberToRoman, checkInt
|
||||||
from novelwriter.constants import nwHeadFmt, nwRegEx, nwShortcode, nwUnicode
|
from novelwriter.constants import nwHeadFmt, nwRegEx, nwShortcode, nwUnicode
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
@@ -79,17 +80,18 @@ class Tokenizer(ABC):
|
|||||||
# Block Type
|
# Block Type
|
||||||
T_EMPTY = 1 # Empty line (new paragraph)
|
T_EMPTY = 1 # Empty line (new paragraph)
|
||||||
T_SYNOPSIS = 2 # Synopsis comment
|
T_SYNOPSIS = 2 # Synopsis comment
|
||||||
T_COMMENT = 3 # Comment line
|
T_BRIEF = 3 # Brief comment
|
||||||
T_KEYWORD = 4 # Command line
|
T_COMMENT = 4 # Comment line
|
||||||
T_TITLE = 5 # Title
|
T_KEYWORD = 5 # Command line
|
||||||
T_UNNUM = 6 # Unnumbered
|
T_TITLE = 6 # Title
|
||||||
T_HEAD1 = 7 # Header 1
|
T_UNNUM = 7 # Unnumbered
|
||||||
T_HEAD2 = 8 # Header 2
|
T_HEAD1 = 8 # Header 1
|
||||||
T_HEAD3 = 9 # Header 3
|
T_HEAD2 = 9 # Header 2
|
||||||
T_HEAD4 = 10 # Header 4
|
T_HEAD3 = 10 # Header 3
|
||||||
T_TEXT = 11 # Text line
|
T_HEAD4 = 11 # Header 4
|
||||||
T_SEP = 12 # Scene separator
|
T_TEXT = 12 # Text line
|
||||||
T_SKIP = 13 # Paragraph break
|
T_SEP = 13 # Scene separator
|
||||||
|
T_SKIP = 14 # Paragraph break
|
||||||
|
|
||||||
# Block Style
|
# Block Style
|
||||||
A_NONE = 0x0000 # No special style
|
A_NONE = 0x0000 # No special style
|
||||||
@@ -461,17 +463,22 @@ class Tokenizer(ABC):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if aLine[0] == "%":
|
if aLine[0] == "%":
|
||||||
cLine = aLine[1:].lstrip()
|
cStyle, cText, _ = processComment(aLine)
|
||||||
synTag = cLine[:9].lower()
|
if cStyle == nwComment.SYNOPSIS:
|
||||||
if synTag == "synopsis:":
|
|
||||||
self._tokens.append((
|
self._tokens.append((
|
||||||
self.T_SYNOPSIS, nHead, cLine[9:].strip(), None, sAlign
|
self.T_SYNOPSIS, nHead, cText, None, sAlign
|
||||||
|
))
|
||||||
|
if self._doSynopsis and self._keepMarkdown:
|
||||||
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
elif cStyle == nwComment.BRIEF:
|
||||||
|
self._tokens.append((
|
||||||
|
self.T_BRIEF, nHead, cText, None, sAlign
|
||||||
))
|
))
|
||||||
if self._doSynopsis and self._keepMarkdown:
|
if self._doSynopsis and self._keepMarkdown:
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
else:
|
else:
|
||||||
self._tokens.append((
|
self._tokens.append((
|
||||||
self.T_COMMENT, nHead, aLine[1:].strip(), None, sAlign
|
self.T_COMMENT, nHead, cText, None, sAlign
|
||||||
))
|
))
|
||||||
if self._doComments and self._keepMarkdown:
|
if self._doComments and self._keepMarkdown:
|
||||||
tmpMarkdown.append("%s\n" % aLine)
|
tmpMarkdown.append("%s\n" % aLine)
|
||||||
|
|||||||
@@ -170,6 +170,10 @@ class ToMarkdown(Tokenizer):
|
|||||||
label = self._localLookup("Synopsis")
|
label = self._localLookup("Synopsis")
|
||||||
lines.append(f"**{label}:** {tText}\n\n")
|
lines.append(f"**{label}:** {tText}\n\n")
|
||||||
|
|
||||||
|
elif tType == self.T_BRIEF and self._doSynopsis:
|
||||||
|
label = self._localLookup("Brief")
|
||||||
|
lines.append(f"**{label}:** {tText}\n\n")
|
||||||
|
|
||||||
elif tType == self.T_COMMENT and self._doComments:
|
elif tType == self.T_COMMENT and self._doComments:
|
||||||
label = self._localLookup("Comment")
|
label = self._localLookup("Comment")
|
||||||
lines.append(f"**{label}:** {tText}\n\n")
|
lines.append(f"**{label}:** {tText}\n\n")
|
||||||
|
|||||||
@@ -481,7 +481,11 @@ class ToOdt(Tokenizer):
|
|||||||
pFmt.append(tFormat)
|
pFmt.append(tFormat)
|
||||||
|
|
||||||
elif tType == self.T_SYNOPSIS and self._doSynopsis:
|
elif tType == self.T_SYNOPSIS and self._doSynopsis:
|
||||||
tTemp, fTemp = self._formatSynopsis(tText)
|
tTemp, fTemp = self._formatSynopsis(tText, True)
|
||||||
|
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
|
||||||
|
|
||||||
|
elif tType == self.T_BRIEF and self._doSynopsis:
|
||||||
|
tTemp, fTemp = self._formatSynopsis(tText, False)
|
||||||
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
|
self._addTextPar("Text_20_Meta", oStyle, tTemp, tFmt=fTemp)
|
||||||
|
|
||||||
elif tType == self.T_COMMENT and self._doComments:
|
elif tType == self.T_COMMENT and self._doComments:
|
||||||
@@ -552,9 +556,9 @@ class ToOdt(Tokenizer):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _formatSynopsis(self, text: str) -> tuple[str, list[tuple[int, int]]]:
|
def _formatSynopsis(self, text: str, synopsis: bool) -> tuple[str, list[tuple[int, int]]]:
|
||||||
"""Apply formatting to synopsis lines."""
|
"""Apply formatting to synopsis lines."""
|
||||||
name = self._localLookup("Synopsis")
|
name = self._localLookup("Synopsis") if synopsis else self._localLookup("Brief")
|
||||||
rTxt = f"{name}: {text}"
|
rTxt = f"{name}: {text}"
|
||||||
rFmt = [(0, self.FMT_B_B), (len(name) + 1, self.FMT_B_E)]
|
rFmt = [(0, self.FMT_B_B), (len(name) + 1, self.FMT_B_E)]
|
||||||
return rTxt, rFmt
|
return rTxt, rFmt
|
||||||
|
|||||||
@@ -61,6 +61,15 @@ class nwItemLayout(Enum):
|
|||||||
# END Enum nwItemLayout
|
# END Enum nwItemLayout
|
||||||
|
|
||||||
|
|
||||||
|
class nwComment(Enum):
|
||||||
|
|
||||||
|
PLAIN = 0
|
||||||
|
SYNOPSIS = 1
|
||||||
|
BRIEF = 2
|
||||||
|
|
||||||
|
# END Enum nwComment
|
||||||
|
|
||||||
|
|
||||||
class nwTrinary(Enum):
|
class nwTrinary(Enum):
|
||||||
|
|
||||||
NEGATIVE = -1
|
NEGATIVE = -1
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ from PyQt5.QtGui import (
|
|||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.common import checkInt
|
from novelwriter.common import checkInt
|
||||||
from novelwriter.constants import nwRegEx, nwUnicode
|
from novelwriter.constants import nwRegEx, nwUnicode
|
||||||
|
from novelwriter.core.index import processComment
|
||||||
|
from novelwriter.enum import nwComment
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -352,16 +354,12 @@ class GuiDocHighlighter(QSyntaxHighlighter):
|
|||||||
|
|
||||||
elif text.startswith("%"): # Comments
|
elif text.startswith("%"): # Comments
|
||||||
self.setCurrentBlockState(self.BLOCK_TEXT)
|
self.setCurrentBlockState(self.BLOCK_TEXT)
|
||||||
toCheck = text[1:].lstrip()
|
cStyle, _, cPos = processComment(text)
|
||||||
synTag = toCheck[:9].lower()
|
if cStyle == nwComment.PLAIN:
|
||||||
tLen = len(text)
|
self.setFormat(0, len(text), self._hStyles["hidden"])
|
||||||
cLen = len(toCheck)
|
|
||||||
cOff = tLen - cLen
|
|
||||||
if synTag == "synopsis:":
|
|
||||||
self.setFormat(0, cOff+9, self._hStyles["modifier"])
|
|
||||||
self.setFormat(cOff+9, tLen, self._hStyles["hidden"])
|
|
||||||
else:
|
else:
|
||||||
self.setFormat(0, tLen, self._hStyles["hidden"])
|
self.setFormat(0, cPos, self._hStyles["modifier"])
|
||||||
|
self.setFormat(cPos, len(text), self._hStyles["hidden"])
|
||||||
|
|
||||||
else: # Text Paragraph
|
else: # Text Paragraph
|
||||||
|
|
||||||
|
|||||||
@@ -34,9 +34,10 @@ from PyQt5.QtWidgets import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
|
from novelwriter.enum import nwDocMode, nwItemClass
|
||||||
|
from novelwriter.common import checkInt
|
||||||
from novelwriter.constants import nwHeaders, nwLabels, nwLists, trConst
|
from novelwriter.constants import nwHeaders, nwLabels, nwLists, trConst
|
||||||
from novelwriter.core.index import IndexHeading, IndexItem
|
from novelwriter.core.index import IndexHeading, IndexItem
|
||||||
from novelwriter.enum import nwDocMode, nwItemClass
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -103,6 +104,23 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def openProjectTasks(self) -> None:
|
||||||
|
"""Run open project tasks."""
|
||||||
|
widths = SHARED.project.options.getValue("GuiDocViewerPanel", "colWidths", {})
|
||||||
|
if isinstance(widths, dict):
|
||||||
|
for key, value in widths.items():
|
||||||
|
if key in self.kwTabs and isinstance(value, list):
|
||||||
|
self.kwTabs[key].setColumnWidths(value)
|
||||||
|
return
|
||||||
|
|
||||||
|
def closeProjectTasks(self) -> None:
|
||||||
|
"""Run close project tasks."""
|
||||||
|
widths = {}
|
||||||
|
for key, tab in self.kwTabs.items():
|
||||||
|
widths[key] = tab.getColumnWidths()
|
||||||
|
SHARED.project.options.setValue("GuiDocViewerPanel", "colWidths", widths)
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Public Slots
|
# Public Slots
|
||||||
##
|
##
|
||||||
@@ -213,6 +231,7 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|||||||
|
|
||||||
# Signals
|
# Signals
|
||||||
self.clicked.connect(self._treeItemClicked)
|
self.clicked.connect(self._treeItemClicked)
|
||||||
|
self.doubleClicked.connect(self._treeItemDoubleClicked)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -253,6 +272,14 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|||||||
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot("QModelIndex")
|
||||||
|
def _treeItemDoubleClicked(self, index: QModelIndex) -> None:
|
||||||
|
"""Emit follow tag signal on user double click."""
|
||||||
|
tHandle = index.siblingAtColumn(self.C_DATA).data(self.D_HANDLE)
|
||||||
|
if index.column() == self.C_DOC:
|
||||||
|
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
@@ -295,6 +322,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
C_VIEW = 2
|
C_VIEW = 2
|
||||||
C_DOC = 3
|
C_DOC = 3
|
||||||
C_TITLE = 4
|
C_TITLE = 4
|
||||||
|
C_BRIEF = 5
|
||||||
|
|
||||||
D_TAG = Qt.ItemDataRole.UserRole
|
D_TAG = Qt.ItemDataRole.UserRole
|
||||||
|
|
||||||
@@ -307,11 +335,16 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
iPx = SHARED.theme.baseIconSize
|
iPx = SHARED.theme.baseIconSize
|
||||||
cMg = CONFIG.pxInt(6)
|
cMg = CONFIG.pxInt(6)
|
||||||
|
|
||||||
self.setHeaderLabels([self.tr("Tag"), "", "", self.tr("Document"), self.tr("Heading")])
|
self.setHeaderLabels([
|
||||||
|
self.tr("Tag"), "", "", self.tr("Document"),
|
||||||
|
self.tr("Heading"), self.tr("Brief")
|
||||||
|
])
|
||||||
self.setIndentation(0)
|
self.setIndentation(0)
|
||||||
self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
|
|
||||||
self.setIconSize(QSize(iPx, iPx))
|
self.setIconSize(QSize(iPx, iPx))
|
||||||
self.setFrameStyle(QFrame.Shape.NoFrame)
|
self.setFrameStyle(QFrame.Shape.NoFrame)
|
||||||
|
self.setSelectionMode(QAbstractItemView.SelectionMode.NoSelection)
|
||||||
|
self.setExpandsOnDoubleClick(False)
|
||||||
|
self.setDragEnabled(False)
|
||||||
self.setSortingEnabled(True)
|
self.setSortingEnabled(True)
|
||||||
self.sortByColumn(self.C_NAME, Qt.SortOrder.AscendingOrder)
|
self.sortByColumn(self.C_NAME, Qt.SortOrder.AscendingOrder)
|
||||||
|
|
||||||
@@ -321,9 +354,9 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.ResizeToContents)
|
treeHeader.setSectionResizeMode(self.C_NAME, QHeaderView.ResizeMode.ResizeToContents)
|
||||||
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
||||||
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
||||||
treeHeader.setSectionResizeMode(self.C_DOC, QHeaderView.ResizeMode.ResizeToContents)
|
|
||||||
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
||||||
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
||||||
|
treeHeader.setSectionsMovable(False)
|
||||||
|
|
||||||
# Cache Icons Locally
|
# Cache Icons Locally
|
||||||
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass])
|
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass])
|
||||||
@@ -332,6 +365,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
|
|
||||||
# Signals
|
# Signals
|
||||||
self.clicked.connect(self._treeItemClicked)
|
self.clicked.connect(self._treeItemClicked)
|
||||||
|
self.doubleClicked.connect(self._treeItemDoubleClicked)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -367,6 +401,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
trItem.setText(self.C_DOC, nwItem.itemName)
|
trItem.setText(self.C_DOC, nwItem.itemName)
|
||||||
trItem.setText(self.C_TITLE, hItem.title)
|
trItem.setText(self.C_TITLE, hItem.title)
|
||||||
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
||||||
|
trItem.setText(self.C_BRIEF, hItem.synopsis)
|
||||||
trItem.setData(self.C_DATA, self.D_TAG, tag)
|
trItem.setData(self.C_DATA, self.D_TAG, tag)
|
||||||
|
|
||||||
if tag not in self._treeMap:
|
if tag not in self._treeMap:
|
||||||
@@ -383,6 +418,20 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def setColumnWidths(self, widths: list[int]) -> None:
|
||||||
|
"""Set the column widths."""
|
||||||
|
if isinstance(widths, list) and len(widths) >= 2:
|
||||||
|
self.setColumnWidth(self.C_DOC, CONFIG.pxInt(checkInt(widths[0], 100)))
|
||||||
|
self.setColumnWidth(self.C_TITLE, CONFIG.pxInt(checkInt(widths[1], 100)))
|
||||||
|
return
|
||||||
|
|
||||||
|
def getColumnWidths(self) -> list[int]:
|
||||||
|
"""Get the widths of the user-adjustable columns."""
|
||||||
|
return [
|
||||||
|
CONFIG.rpxInt(self.columnWidth(self.C_DOC)),
|
||||||
|
CONFIG.rpxInt(self.columnWidth(self.C_TITLE)),
|
||||||
|
]
|
||||||
|
|
||||||
##
|
##
|
||||||
# Private Slots
|
# Private Slots
|
||||||
##
|
##
|
||||||
@@ -397,4 +446,12 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|||||||
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@pyqtSlot("QModelIndex")
|
||||||
|
def _treeItemDoubleClicked(self, index: QModelIndex) -> None:
|
||||||
|
"""Emit follow tag signal on user double click."""
|
||||||
|
tag = index.siblingAtColumn(self.C_DATA).data(self.D_TAG)
|
||||||
|
if index.column() == self.C_NAME:
|
||||||
|
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
||||||
|
return
|
||||||
|
|
||||||
# END Class _ViewPanelKeyWords
|
# END Class _ViewPanelKeyWords
|
||||||
|
|||||||
@@ -454,6 +454,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.docViewer.clearNavHistory()
|
self.docViewer.clearNavHistory()
|
||||||
self.closeDocViewer(byUser=False)
|
self.closeDocViewer(byUser=False)
|
||||||
|
|
||||||
|
self.docViewerPanel.closeProjectTasks()
|
||||||
self.outlineView.closeProjectTasks()
|
self.outlineView.closeProjectTasks()
|
||||||
self.novelView.closeProjectTasks()
|
self.novelView.closeProjectTasks()
|
||||||
self.projView.clearProjectView()
|
self.projView.clearProjectView()
|
||||||
@@ -527,6 +528,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.projView.openProjectTasks()
|
self.projView.openProjectTasks()
|
||||||
self.novelView.openProjectTasks()
|
self.novelView.openProjectTasks()
|
||||||
self.outlineView.openProjectTasks()
|
self.outlineView.openProjectTasks()
|
||||||
|
self.docViewerPanel.openProjectTasks()
|
||||||
self._updateStatusWordCount()
|
self._updateStatusWordCount()
|
||||||
|
|
||||||
# Restore previously open documents, if any
|
# Restore previously open documents, if any
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
%%~name: John Smith
|
%%~name: John Smith
|
||||||
%%~path: f7e2d9f330615/14298de4d9524
|
%%~path: f7e2d9f330615/14298de4d9524
|
||||||
%%~kind: CHARACTER/NOTE
|
%%~kind: CHARACTER/NOTE
|
||||||
%%~hash: 259eff30f10e101cf93e27e8764e851d356d54b8
|
%%~hash: fda91c416d874aa41a47fceaedb3d62f040c7e32
|
||||||
%%~date: Unknown/2023-08-25 16:52:03
|
%%~date: Unknown/2023-11-25 18:16:13
|
||||||
# John Smith
|
# John Smith
|
||||||
|
|
||||||
@tag: John
|
@tag: John
|
||||||
|
|
||||||
|
% Brief: The sidekick
|
||||||
|
|
||||||
He’s pretty cool. Not Brad Pitt though.
|
He’s pretty cool. Not Brad Pitt though.
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
%%~name: Jane Smith
|
%%~name: Jane Smith
|
||||||
%%~path: f7e2d9f330615/bb2c23b3c42cc
|
%%~path: f7e2d9f330615/bb2c23b3c42cc
|
||||||
%%~kind: CHARACTER/NOTE
|
%%~kind: CHARACTER/NOTE
|
||||||
%%~hash: a69e4ca6ceede2536c8d364f88e6b62ef0ec36c3
|
%%~hash: b7291713899bd0356617a36ae606b08e5fee1b65
|
||||||
%%~date: Unknown/2023-08-25 16:52:04
|
%%~date: Unknown/2023-11-25 18:16:07
|
||||||
# Jane Smith
|
# Jane Smith
|
||||||
|
|
||||||
@tag: Jane
|
@tag: Jane
|
||||||
|
|
||||||
|
% Brief: The heroine
|
||||||
|
|
||||||
She’s pretty cool. Not Angelina Jolie though.
|
She’s pretty cool. Not Angelina Jolie though.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<novelWriterXML appVersion="2.2-beta1" hexVersion="0x020200b1" fileVersion="1.5" fileRevision="1" timeStamp="2023-11-11 22:48:30">
|
<novelWriterXML appVersion="2.2-beta1" hexVersion="0x020200b1" fileVersion="1.5" fileRevision="1" timeStamp="2023-11-25 18:16:17">
|
||||||
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="1611" autoCount="255" editTime="81193">
|
<project id="e2be99af-f9bf-4403-857a-c3d1ac25abea" saveCount="1612" autoCount="256" editTime="81268">
|
||||||
<name>Sample Project</name>
|
<name>Sample Project</name>
|
||||||
<title>Sample Project</title>
|
<title>Sample Project</title>
|
||||||
<author>Jane Smith</author>
|
<author>Jane Smith</author>
|
||||||
@@ -102,11 +102,11 @@
|
|||||||
<name status="sf12341" import="ia857f0">Main Characters</name>
|
<name status="sf12341" import="ia857f0">Main Characters</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="14298de4d9524" parent="f7e2d9f330615" root="f6622b4617424" order="0" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="65" />
|
<meta expanded="no" heading="H1" charCount="49" wordCount="9" paraCount="1" cursorPos="48" />
|
||||||
<name status="sf12341" import="icfb3a5" active="yes">John Smith</name>
|
<name status="sf12341" import="icfb3a5" active="yes">John Smith</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
<item handle="bb2c23b3c42cc" parent="f7e2d9f330615" root="f6622b4617424" order="1" type="FILE" class="CHARACTER" layout="NOTE">
|
||||||
<meta expanded="no" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="71" />
|
<meta expanded="no" heading="H1" charCount="55" wordCount="9" paraCount="1" cursorPos="47" />
|
||||||
<name status="sf12341" import="i2d7a54" active="yes">Jane Smith</name>
|
<name status="sf12341" import="i2d7a54" active="yes">Jane Smith</name>
|
||||||
</item>
|
</item>
|
||||||
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
|
<item handle="15c4492bd5107" parent="None" root="15c4492bd5107" order="3" type="ROOT" class="WORLD">
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ from mocked import causeException
|
|||||||
from novelwriter.core.item import NWItem
|
from novelwriter.core.item import NWItem
|
||||||
from tools import C, buildTestProject, cmpFiles, writeFile
|
from tools import C, buildTestProject, cmpFiles, writeFile
|
||||||
|
|
||||||
from novelwriter.enum import nwItemClass, nwItemLayout
|
from novelwriter.enum import nwComment, nwItemClass, nwItemLayout
|
||||||
from novelwriter.constants import nwFiles
|
from novelwriter.constants import nwFiles
|
||||||
from novelwriter.core.index import IndexItem, NWIndex, countWords, TagsIndex
|
from novelwriter.core.index import IndexItem, NWIndex, countWords, TagsIndex, processComment
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
|
|
||||||
|
|
||||||
@@ -1264,7 +1264,34 @@ def testCoreIndex_ItemIndex(mockGUI, fncPath, mockRnd):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreIndex_CountWords():
|
def testCoreIndex_processComment():
|
||||||
|
"""Test the comment processing function."""
|
||||||
|
# Regular comment
|
||||||
|
assert processComment("%Hi") == (nwComment.PLAIN, "Hi", 0)
|
||||||
|
assert processComment("% Hi") == (nwComment.PLAIN, "Hi", 0)
|
||||||
|
assert processComment("% Hi:you") == (nwComment.PLAIN, "Hi:you", 0)
|
||||||
|
|
||||||
|
# Synopsis
|
||||||
|
assert processComment("%synopsis:") == (nwComment.PLAIN, "synopsis:", 0)
|
||||||
|
assert processComment("%synopsis: Hi") == (nwComment.SYNOPSIS, "Hi", 10)
|
||||||
|
assert processComment("% synopsis: Hi") == (nwComment.SYNOPSIS, "Hi", 11)
|
||||||
|
assert processComment("% synopsis : Hi") == (nwComment.SYNOPSIS, "Hi", 13)
|
||||||
|
assert processComment("% Synopsis : Hi") == (nwComment.SYNOPSIS, "Hi", 15)
|
||||||
|
assert processComment("% \t SYNOPSIS : Hi") == (nwComment.SYNOPSIS, "Hi", 16)
|
||||||
|
|
||||||
|
# Brief
|
||||||
|
assert processComment("%brief:") == (nwComment.PLAIN, "brief:", 0)
|
||||||
|
assert processComment("%brief: Hi") == (nwComment.BRIEF, "Hi", 7)
|
||||||
|
assert processComment("% brief: Hi") == (nwComment.BRIEF, "Hi", 8)
|
||||||
|
assert processComment("% brief : Hi") == (nwComment.BRIEF, "Hi", 10)
|
||||||
|
assert processComment("% Brief : Hi") == (nwComment.BRIEF, "Hi", 12)
|
||||||
|
assert processComment("% \t BRIEF : Hi") == (nwComment.BRIEF, "Hi", 13)
|
||||||
|
|
||||||
|
# END Test testCoreIndex_processComment
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.core
|
||||||
|
def testCoreIndex_countWords():
|
||||||
"""Test the word counter and the exclusion filers."""
|
"""Test the word counter and the exclusion filers."""
|
||||||
# Non-Text
|
# Non-Text
|
||||||
assert countWords(None) == (0, 0, 0) # type: ignore
|
assert countWords(None) == (0, 0, 0) # type: ignore
|
||||||
@@ -1362,4 +1389,4 @@ def testCoreIndex_CountWords():
|
|||||||
assert wC == 14
|
assert wC == 14
|
||||||
assert pC == 2
|
assert pC == 2
|
||||||
|
|
||||||
# END Test testCoreIndex_CountWords
|
# END Test testCoreIndex_countWords
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ def testCoreToHtml_ConvertFormat(mockGUI):
|
|||||||
"<p class='break'>Line one<br/>Line two<br/>Line three</p>\n"
|
"<p class='break'>Line one<br/>Line two<br/>Line three</p>\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Synopsis
|
# Synopsis, Brief
|
||||||
html._text = "%synopsis: The synopsis ...\n"
|
html._text = "%synopsis: The synopsis ...\n"
|
||||||
html.tokenizeText()
|
html.tokenizeText()
|
||||||
html.doConvert()
|
html.doConvert()
|
||||||
@@ -163,6 +163,14 @@ def testCoreToHtml_ConvertFormat(mockGUI):
|
|||||||
"<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n"
|
"<p class='synopsis'><strong>Synopsis:</strong> The synopsis ...</p>\n"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
html.setSynopsis(True)
|
||||||
|
html._text = "%brief: A description ...\n"
|
||||||
|
html.tokenizeText()
|
||||||
|
html.doConvert()
|
||||||
|
assert html.theResult == (
|
||||||
|
"<p class='synopsis'><strong>Brief:</strong> A description ...</p>\n"
|
||||||
|
)
|
||||||
|
|
||||||
# Comment
|
# Comment
|
||||||
html._text = "% A comment ...\n"
|
html._text = "% A comment ...\n"
|
||||||
html.tokenizeText()
|
html.tokenizeText()
|
||||||
@@ -610,9 +618,12 @@ def testCoreToHtml_Format(mockGUI):
|
|||||||
# Export Mode
|
# Export Mode
|
||||||
# ===========
|
# ===========
|
||||||
|
|
||||||
assert html._formatSynopsis("synopsis text") == (
|
assert html._formatSynopsis("synopsis text", True) == (
|
||||||
"<p class='synopsis'><strong>Synopsis:</strong> synopsis text</p>\n"
|
"<p class='synopsis'><strong>Synopsis:</strong> synopsis text</p>\n"
|
||||||
)
|
)
|
||||||
|
assert html._formatSynopsis("brief text", False) == (
|
||||||
|
"<p class='synopsis'><strong>Brief:</strong> brief text</p>\n"
|
||||||
|
)
|
||||||
assert html._formatComments("comment text") == (
|
assert html._formatComments("comment text") == (
|
||||||
"<p class='comment'><strong>Comment:</strong> comment text</p>\n"
|
"<p class='comment'><strong>Comment:</strong> comment text</p>\n"
|
||||||
)
|
)
|
||||||
@@ -632,9 +643,12 @@ def testCoreToHtml_Format(mockGUI):
|
|||||||
|
|
||||||
html.setPreview(True, True)
|
html.setPreview(True, True)
|
||||||
|
|
||||||
assert html._formatSynopsis("synopsis text") == (
|
assert html._formatSynopsis("synopsis text", True) == (
|
||||||
"<p class='comment'><span class='synopsis'>Synopsis:</span> synopsis text</p>\n"
|
"<p class='comment'><span class='synopsis'>Synopsis:</span> synopsis text</p>\n"
|
||||||
)
|
)
|
||||||
|
assert html._formatSynopsis("brief text", False) == (
|
||||||
|
"<p class='comment'><span class='synopsis'>Brief:</span> brief text</p>\n"
|
||||||
|
)
|
||||||
assert html._formatComments("comment text") == (
|
assert html._formatComments("comment text") == (
|
||||||
"<p class='comment'>comment text</p>\n"
|
"<p class='comment'>comment text</p>\n"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -471,6 +471,20 @@ def testCoreToken_MetaFormat(mockGUI):
|
|||||||
tokens.tokenizeText()
|
tokens.tokenizeText()
|
||||||
assert tokens.theMarkdown[-1] == "% synopsis: The synopsis\n\n"
|
assert tokens.theMarkdown[-1] == "% synopsis: The synopsis\n\n"
|
||||||
|
|
||||||
|
# Brief
|
||||||
|
tokens.setSynopsis(False)
|
||||||
|
tokens._text = "% brief: A description\n"
|
||||||
|
tokens.tokenizeText()
|
||||||
|
assert tokens._tokens == [
|
||||||
|
(Tokenizer.T_BRIEF, 0, "A description", None, Tokenizer.A_NONE),
|
||||||
|
(Tokenizer.T_EMPTY, 0, "", None, Tokenizer.A_NONE),
|
||||||
|
]
|
||||||
|
assert tokens.theMarkdown[-1] == "\n"
|
||||||
|
|
||||||
|
tokens.setSynopsis(True)
|
||||||
|
tokens.tokenizeText()
|
||||||
|
assert tokens.theMarkdown[-1] == "% brief: A description\n\n"
|
||||||
|
|
||||||
# Keyword
|
# Keyword
|
||||||
tokens._text = "@char: Bod\n"
|
tokens._text = "@char: Bod\n"
|
||||||
tokens.tokenizeText()
|
tokens.tokenizeText()
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ def testCoreToMarkdown_ConvertFormat(mockGUI):
|
|||||||
theMD.doConvert()
|
theMD.doConvert()
|
||||||
assert theMD.theResult == "Line one \nLine two \nLine three\n\n"
|
assert theMD.theResult == "Line one \nLine two \nLine three\n\n"
|
||||||
|
|
||||||
# Synopsis
|
# Synopsis, Brief
|
||||||
theMD._text = "%synopsis: The synopsis ...\n"
|
theMD._text = "%synopsis: The synopsis ...\n"
|
||||||
theMD.tokenizeText()
|
theMD.tokenizeText()
|
||||||
theMD.doConvert()
|
theMD.doConvert()
|
||||||
@@ -118,6 +118,12 @@ def testCoreToMarkdown_ConvertFormat(mockGUI):
|
|||||||
theMD.doConvert()
|
theMD.doConvert()
|
||||||
assert theMD.theResult == "**Synopsis:** The synopsis ...\n\n"
|
assert theMD.theResult == "**Synopsis:** The synopsis ...\n\n"
|
||||||
|
|
||||||
|
theMD.setSynopsis(True)
|
||||||
|
theMD._text = "%brief: A description ...\n"
|
||||||
|
theMD.tokenizeText()
|
||||||
|
theMD.doConvert()
|
||||||
|
assert theMD.theResult == "**Brief:** A description ...\n\n"
|
||||||
|
|
||||||
# Comment
|
# Comment
|
||||||
theMD._text = "% A comment ...\n"
|
theMD._text = "% A comment ...\n"
|
||||||
theMD.tokenizeText()
|
theMD.tokenizeText()
|
||||||
|
|||||||
@@ -447,12 +447,13 @@ def testCoreToOdt_Convert(mockGUI):
|
|||||||
'</office:text>'
|
'</office:text>'
|
||||||
)
|
)
|
||||||
|
|
||||||
# Synopsis, Comment, Keywords
|
# Synopsis, Brief, Comment, Keywords
|
||||||
odt._text = (
|
odt._text = (
|
||||||
"### Scene\n\n"
|
"### Scene\n\n"
|
||||||
"@pov: Jane\n\n"
|
"@pov: Jane\n\n"
|
||||||
"% synopsis: So it begins\n\n"
|
"% synopsis: So it begins\n\n"
|
||||||
"% a plain comment\n\n"
|
"% brief: Then what\n\n"
|
||||||
|
"% A plain comment\n\n"
|
||||||
)
|
)
|
||||||
odt.setSynopsis(True)
|
odt.setSynopsis(True)
|
||||||
odt.setComments(True)
|
odt.setComments(True)
|
||||||
@@ -470,7 +471,9 @@ def testCoreToOdt_Convert(mockGUI):
|
|||||||
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
||||||
'Synopsis:</text:span> So it begins</text:p>'
|
'Synopsis:</text:span> So it begins</text:p>'
|
||||||
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
||||||
'Comment:</text:span> a plain comment</text:p>'
|
'Brief:</text:span> Then what</text:p>'
|
||||||
|
'<text:p text:style-name="Text_20_Meta"><text:span text:style-name="T7">'
|
||||||
|
'Comment:</text:span> A plain comment</text:p>'
|
||||||
'</office:text>'
|
'</office:text>'
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -804,9 +807,12 @@ def testCoreToOdt_Format(mockGUI):
|
|||||||
project = NWProject()
|
project = NWProject()
|
||||||
odt = ToOdt(project, isFlat=True)
|
odt = ToOdt(project, isFlat=True)
|
||||||
|
|
||||||
assert odt._formatSynopsis("synopsis text") == (
|
assert odt._formatSynopsis("synopsis text", True) == (
|
||||||
"Synopsis: synopsis text", [(0, ToOdt.FMT_B_B), (9, ToOdt.FMT_B_E)]
|
"Synopsis: synopsis text", [(0, ToOdt.FMT_B_B), (9, ToOdt.FMT_B_E)]
|
||||||
)
|
)
|
||||||
|
assert odt._formatSynopsis("brief text", False) == (
|
||||||
|
"Brief: brief text", [(0, ToOdt.FMT_B_B), (6, ToOdt.FMT_B_E)]
|
||||||
|
)
|
||||||
assert odt._formatComments("comment text") == (
|
assert odt._formatComments("comment text") == (
|
||||||
"Comment: comment text", [(0, ToOdt.FMT_B_B), (8, ToOdt.FMT_B_E)]
|
"Comment: comment text", [(0, ToOdt.FMT_B_B), (8, ToOdt.FMT_B_E)]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -102,6 +102,12 @@ def testGuiViewerPanel_BackRefs(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
|||||||
tabBackRefs._treeItemClicked(tabBackRefs.model().index(0, tabBackRefs.C_VIEW))
|
tabBackRefs._treeItemClicked(tabBackRefs.model().index(0, tabBackRefs.C_VIEW))
|
||||||
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||||
|
|
||||||
|
# Double-Click
|
||||||
|
nwGUI.viewDocument(hJane)
|
||||||
|
assert nwGUI.docViewer.docHandle == hJane
|
||||||
|
tabBackRefs._treeItemDoubleClicked(tabBackRefs.model().index(0, tabBackRefs.C_DOC))
|
||||||
|
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||||
|
|
||||||
# qtbot.stop()
|
# qtbot.stop()
|
||||||
|
|
||||||
# END Test testGuiViewerPanel_BackRefs
|
# END Test testGuiViewerPanel_BackRefs
|
||||||
@@ -189,6 +195,8 @@ def testGuiViewerPanel_Tags(qtbot, monkeypatch, caplog, nwGUI, projPath, mockRnd
|
|||||||
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||||
charTab._treeItemClicked(charTab.model().index(1, charTab.C_VIEW))
|
charTab._treeItemClicked(charTab.model().index(1, charTab.C_VIEW))
|
||||||
assert nwGUI.docViewer.docHandle == hJohn
|
assert nwGUI.docViewer.docHandle == hJohn
|
||||||
|
charTab._treeItemDoubleClicked(charTab.model().index(0, charTab.C_NAME))
|
||||||
|
assert nwGUI.docViewer.docHandle == hJane
|
||||||
|
|
||||||
# qtbot.stop()
|
# qtbot.stop()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user