Add inactive tags filter to viewer panel (#1654)
This commit is contained in:
+15
-12
@@ -517,28 +517,28 @@ class NWIndex:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def novelStructure(
|
def novelStructure(
|
||||||
self, rootHandle: str | None = None, skipExcl: bool = True
|
self, rootHandle: str | None = None, activeOnly: bool = True
|
||||||
) -> Iterator[tuple[str, str, str, IndexHeading]]:
|
) -> Iterator[tuple[str, str, str, IndexHeading]]:
|
||||||
"""Iterate over all titles in the novel, in the correct order as
|
"""Iterate over all titles in the novel, in the correct order as
|
||||||
they appear in the tree view and in the respective document
|
they appear in the tree view and in the respective document
|
||||||
files, but skipping all note files.
|
files, but skipping all note files.
|
||||||
"""
|
"""
|
||||||
structure = self._itemIndex.iterNovelStructure(rHandle=rootHandle, skipExcl=skipExcl)
|
structure = self._itemIndex.iterNovelStructure(rHandle=rootHandle, activeOnly=activeOnly)
|
||||||
for tHandle, sTitle, hItem in structure:
|
for tHandle, sTitle, hItem in structure:
|
||||||
yield f"{tHandle}:{sTitle}", tHandle, sTitle, hItem
|
yield f"{tHandle}:{sTitle}", tHandle, sTitle, hItem
|
||||||
return
|
return
|
||||||
|
|
||||||
def getNovelWordCount(self, skipExcl: bool = True) -> int:
|
def getNovelWordCount(self, activeOnly: bool = True) -> int:
|
||||||
"""Count the number of words in the novel project."""
|
"""Count the number of words in the novel project."""
|
||||||
wCount = 0
|
wCount = 0
|
||||||
for _, _, hItem in self._itemIndex.iterNovelStructure(skipExcl=skipExcl):
|
for _, _, hItem in self._itemIndex.iterNovelStructure(activeOnly=activeOnly):
|
||||||
wCount += hItem.wordCount
|
wCount += hItem.wordCount
|
||||||
return wCount
|
return wCount
|
||||||
|
|
||||||
def getNovelTitleCounts(self, skipExcl: bool = True) -> list[int]:
|
def getNovelTitleCounts(self, activeOnly: bool = True) -> list[int]:
|
||||||
"""Count the number of titles in the novel project."""
|
"""Count the number of titles in the novel project."""
|
||||||
hCount = [0, 0, 0, 0, 0]
|
hCount = [0, 0, 0, 0, 0]
|
||||||
for _, _, hItem in self._itemIndex.iterNovelStructure(skipExcl=skipExcl):
|
for _, _, hItem in self._itemIndex.iterNovelStructure(activeOnly=activeOnly):
|
||||||
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0)
|
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0)
|
||||||
hCount[iLevel] += 1
|
hCount[iLevel] += 1
|
||||||
return hCount
|
return hCount
|
||||||
@@ -551,14 +551,14 @@ class NWIndex:
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
def getTableOfContents(
|
def getTableOfContents(
|
||||||
self, rHandle: str | None, maxDepth: int, skipExcl: bool = True
|
self, rHandle: str | None, maxDepth: int, activeOnly: bool = True
|
||||||
) -> list[tuple[str, int, str, int]]:
|
) -> list[tuple[str, int, str, int]]:
|
||||||
"""Generate a table of contents up to a maximum depth."""
|
"""Generate a table of contents up to a maximum depth."""
|
||||||
tOrder = []
|
tOrder = []
|
||||||
tData = {}
|
tData = {}
|
||||||
pKey = None
|
pKey = None
|
||||||
for tHandle, sTitle, hItem in self._itemIndex.iterNovelStructure(
|
for tHandle, sTitle, hItem in self._itemIndex.iterNovelStructure(
|
||||||
rHandle=rHandle, skipExcl=skipExcl
|
rHandle=rHandle, activeOnly=activeOnly
|
||||||
):
|
):
|
||||||
tKey = f"{tHandle}:{sTitle}"
|
tKey = f"{tHandle}:{sTitle}"
|
||||||
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0)
|
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0)
|
||||||
@@ -646,12 +646,15 @@ class NWIndex:
|
|||||||
"""Return all tags based on itemClass."""
|
"""Return all tags based on itemClass."""
|
||||||
return self._tagsIndex.filterTagNames(itemClass.name)
|
return self._tagsIndex.filterTagNames(itemClass.name)
|
||||||
|
|
||||||
def getTagsData(self) -> Iterator[tuple[str, str, str, IndexItem | None, IndexHeading | None]]:
|
def getTagsData(
|
||||||
|
self, activeOnly: bool = True
|
||||||
|
) -> Iterator[tuple[str, str, str, IndexItem | None, IndexHeading | None]]:
|
||||||
"""Return all known tags."""
|
"""Return all known tags."""
|
||||||
for tag, data in self._tagsIndex.items():
|
for tag, data in self._tagsIndex.items():
|
||||||
iItem = self._itemIndex[data.get("handle")]
|
iItem = self._itemIndex[data.get("handle")]
|
||||||
hItem = None if iItem is None else iItem[data.get("heading")]
|
hItem = None if iItem is None else iItem[data.get("heading")]
|
||||||
yield tag, data.get("name", ""), data.get("class", ""), iItem, hItem
|
if not activeOnly or (iItem and iItem.item.isActive):
|
||||||
|
yield tag, data.get("name", ""), data.get("class", ""), iItem, hItem
|
||||||
return
|
return
|
||||||
|
|
||||||
def getSingleTag(self, tagKey: str) -> tuple[str, str, IndexItem | None, IndexHeading | None]:
|
def getSingleTag(self, tagKey: str) -> tuple[str, str, IndexItem | None, IndexHeading | None]:
|
||||||
@@ -848,7 +851,7 @@ class ItemIndex:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def iterNovelStructure(
|
def iterNovelStructure(
|
||||||
self, rHandle: str | None = None, skipExcl: bool = False
|
self, rHandle: str | None = None, activeOnly: bool = False
|
||||||
) -> Iterable[tuple[str, str, IndexHeading]]:
|
) -> Iterable[tuple[str, str, IndexHeading]]:
|
||||||
"""Iterate over all items and headers in the novel structure for
|
"""Iterate over all items and headers in the novel structure for
|
||||||
a given root handle, or for all if root handle is None.
|
a given root handle, or for all if root handle is None.
|
||||||
@@ -856,7 +859,7 @@ class ItemIndex:
|
|||||||
for tItem in self._project.tree:
|
for tItem in self._project.tree:
|
||||||
if tItem.isNoteLayout():
|
if tItem.isNoteLayout():
|
||||||
continue
|
continue
|
||||||
if skipExcl and not tItem.isActive:
|
if activeOnly and not tItem.isActive:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tHandle = tItem.itemHandle
|
tHandle = tItem.itemHandle
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ VALID_MAP: dict[str, set[str]] = {
|
|||||||
"winWidth", "winHeight", "fmtWidth", "sumWidth",
|
"winWidth", "winHeight", "fmtWidth", "sumWidth",
|
||||||
},
|
},
|
||||||
"GuiDocViewerPanel": {
|
"GuiDocViewerPanel": {
|
||||||
"colWidths",
|
"colWidths", "hideInactive",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ from enum import Enum
|
|||||||
|
|
||||||
from PyQt5.QtCore import QModelIndex, QSize, Qt, pyqtSignal, pyqtSlot
|
from PyQt5.QtCore import QModelIndex, QSize, Qt, pyqtSignal, pyqtSlot
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractItemView, QFrame, QHeaderView, QTabWidget, QTreeWidget,
|
QAbstractItemView, QFrame, QHeaderView, QMenu, QTabWidget, QToolButton,
|
||||||
QTreeWidgetItem, QVBoxLayout, QWidget
|
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
@@ -54,10 +54,24 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
|
|
||||||
self._lastHandle = None
|
self._lastHandle = None
|
||||||
|
|
||||||
|
iPx = int(1.0*SHARED.theme.baseIconSize)
|
||||||
|
|
||||||
self.tabBackRefs = _ViewPanelBackRefs(self)
|
self.tabBackRefs = _ViewPanelBackRefs(self)
|
||||||
|
|
||||||
|
self.optsMenu = QMenu(self)
|
||||||
|
|
||||||
|
self.aInactive = self.optsMenu.addAction(self.tr("Hide Inactive Tags"))
|
||||||
|
self.aInactive.setCheckable(True)
|
||||||
|
self.aInactive.toggled.connect(self._toggleHideInactive)
|
||||||
|
|
||||||
|
self.optsButton = QToolButton(self)
|
||||||
|
self.optsButton.setIconSize(QSize(iPx, iPx))
|
||||||
|
self.optsButton.setMenu(self.optsMenu)
|
||||||
|
self.optsButton.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
||||||
|
|
||||||
self.mainTabs = QTabWidget(self)
|
self.mainTabs = QTabWidget(self)
|
||||||
self.mainTabs.addTab(self.tabBackRefs, self.tr("References"))
|
self.mainTabs.addTab(self.tabBackRefs, self.tr("References"))
|
||||||
|
self.mainTabs.setCornerWidget(self.optsButton, Qt.Corner.TopLeftCorner)
|
||||||
|
|
||||||
self.kwTabs: dict[str, _ViewPanelKeyWords] = {}
|
self.kwTabs: dict[str, _ViewPanelKeyWords] = {}
|
||||||
self.idTabs: dict[str, int] = {}
|
self.idTabs: dict[str, int] = {}
|
||||||
@@ -85,20 +99,27 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
|
|
||||||
def updateTheme(self, updateTabs: bool = True) -> None:
|
def updateTheme(self, updateTabs: bool = True) -> None:
|
||||||
"""Update theme elements."""
|
"""Update theme elements."""
|
||||||
|
qPalette = self.palette()
|
||||||
|
mPx = CONFIG.pxInt(2)
|
||||||
vPx = CONFIG.pxInt(4)
|
vPx = CONFIG.pxInt(4)
|
||||||
lPx = CONFIG.pxInt(2)
|
hPx = CONFIG.pxInt(8)
|
||||||
rPx = CONFIG.pxInt(14)
|
hCol = qPalette.highlight().color()
|
||||||
hCol = self.palette().highlight().color()
|
fCol = qPalette.text().color()
|
||||||
|
|
||||||
|
buttonStyle = (
|
||||||
|
"QToolButton {{padding: {0}px; margin: 0 0 {1}px 0; border: none; "
|
||||||
|
"background: transparent;}} "
|
||||||
|
"QToolButton:hover {{border: none; background: rgba({2}, {3}, {4}, 0.2);}} "
|
||||||
|
"QToolButton::menu-indicator {{image: none;}} "
|
||||||
|
).format(mPx, mPx, fCol.red(), fCol.green(), fCol.blue())
|
||||||
|
self.optsButton.setIcon(SHARED.theme.getIcon("menu"))
|
||||||
|
self.optsButton.setStyleSheet(buttonStyle)
|
||||||
|
|
||||||
styleSheet = (
|
styleSheet = (
|
||||||
"QTabWidget::pane {border: 0;} "
|
"QTabWidget::pane {{border: 0;}} "
|
||||||
"QTabWidget QTabBar::tab {"
|
"QTabWidget QTabBar::tab {{border: 0; padding: {0}px {1}px;}} "
|
||||||
f"border: 0; padding: {vPx}px {rPx}px {vPx}px {lPx}px;"
|
"QTabWidget QTabBar::tab:selected {{color: rgb({2}, {3}, {4});}} "
|
||||||
"} "
|
).format(vPx, hPx, hCol.red(), hCol.green(), hCol.blue())
|
||||||
"QTabWidget QTabBar::tab:selected {"
|
|
||||||
f"color: rgb({hCol.red()}, {hCol.green()}, {hCol.blue()});"
|
|
||||||
"} "
|
|
||||||
)
|
|
||||||
self.mainTabs.setStyleSheet(styleSheet)
|
self.mainTabs.setStyleSheet(styleSheet)
|
||||||
self.updateHandle(self._lastHandle)
|
self.updateHandle(self._lastHandle)
|
||||||
|
|
||||||
@@ -111,20 +132,22 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
|
|
||||||
def openProjectTasks(self) -> None:
|
def openProjectTasks(self) -> None:
|
||||||
"""Run open project tasks."""
|
"""Run open project tasks."""
|
||||||
widths = SHARED.project.options.getValue("GuiDocViewerPanel", "colWidths", {})
|
colWidths = SHARED.project.options.getValue("GuiDocViewerPanel", "colWidths", {})
|
||||||
if isinstance(widths, dict):
|
hideInactive = SHARED.project.options.getBool("GuiDocViewerPanel", "hideInactive", False)
|
||||||
for key, value in widths.items():
|
self.aInactive.setChecked(hideInactive)
|
||||||
|
if isinstance(colWidths, dict):
|
||||||
|
for key, value in colWidths.items():
|
||||||
if key in self.kwTabs and isinstance(value, list):
|
if key in self.kwTabs and isinstance(value, list):
|
||||||
self.kwTabs[key].setColumnWidths(value)
|
self.kwTabs[key].setColumnWidths(value)
|
||||||
return
|
return
|
||||||
|
|
||||||
def closeProjectTasks(self) -> None:
|
def closeProjectTasks(self) -> None:
|
||||||
"""Run close project tasks."""
|
"""Run close project tasks."""
|
||||||
widths = {}
|
|
||||||
for key, tab in self.kwTabs.items():
|
|
||||||
widths[key] = tab.getColumnWidths()
|
|
||||||
logger.debug("Saving State: GuiDocViewerPanel")
|
logger.debug("Saving State: GuiDocViewerPanel")
|
||||||
SHARED.project.options.setValue("GuiDocViewerPanel", "colWidths", widths)
|
colWidths = {k: t.getColumnWidths() for k, t in self.kwTabs.items()}
|
||||||
|
hideInactive = self.aInactive.isChecked()
|
||||||
|
SHARED.project.options.setValue("GuiDocViewerPanel", "colWidths", colWidths)
|
||||||
|
SHARED.project.options.setValue("GuiDocViewerPanel", "hideInactive", hideInactive)
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -142,9 +165,7 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def indexHasAppeared(self) -> None:
|
def indexHasAppeared(self) -> None:
|
||||||
"""Handle event when the index has appeared."""
|
"""Handle event when the index has appeared."""
|
||||||
for key, name, tClass, iItem, hItem in SHARED.project.index.getTagsData():
|
self._loadAllTags()
|
||||||
if tClass in self.kwTabs and iItem and hItem:
|
|
||||||
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
|
|
||||||
self._updateTabVisibility()
|
self._updateTabVisibility()
|
||||||
self.updateHandle(self._lastHandle)
|
self.updateHandle(self._lastHandle)
|
||||||
return
|
return
|
||||||
@@ -153,10 +174,15 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
def projectItemChanged(self, tHandle: str) -> None:
|
def projectItemChanged(self, tHandle: str) -> None:
|
||||||
"""Update meta data for project item."""
|
"""Update meta data for project item."""
|
||||||
self.tabBackRefs.refreshDocument(tHandle)
|
self.tabBackRefs.refreshDocument(tHandle)
|
||||||
|
activeOnly = self.aInactive.isChecked()
|
||||||
for key in SHARED.project.index.getDocumentTags(tHandle):
|
for key in SHARED.project.index.getDocumentTags(tHandle):
|
||||||
name, tClass, iItem, hItem = SHARED.project.index.getSingleTag(key)
|
name, tClass, iItem, hItem = SHARED.project.index.getSingleTag(key)
|
||||||
if tClass in self.kwTabs and iItem and hItem:
|
if tClass in self.kwTabs and iItem and hItem:
|
||||||
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
|
if not activeOnly or (iItem and iItem.item.isActive):
|
||||||
|
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
|
||||||
|
else:
|
||||||
|
self.kwTabs[tClass].removeEntry(key)
|
||||||
|
self._updateTabVisibility()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
@@ -182,6 +208,20 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
self._updateTabVisibility()
|
self._updateTabVisibility()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Private Slots
|
||||||
|
##
|
||||||
|
|
||||||
|
@pyqtSlot(bool)
|
||||||
|
def _toggleHideInactive(self, state: bool) -> None:
|
||||||
|
"""Process toggling of active/inactive visibility."""
|
||||||
|
logger.debug("Setting inactive items to %s", "hidden" if state else "visible")
|
||||||
|
for cTab in self.kwTabs.values():
|
||||||
|
cTab.clearContent()
|
||||||
|
self._loadAllTags()
|
||||||
|
self._updateTabVisibility()
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
@@ -193,6 +233,14 @@ class GuiDocViewerPanel(QWidget):
|
|||||||
self.mainTabs.setTabVisible(self.idTabs[tClass], cTab.countEntries() > 0)
|
self.mainTabs.setTabVisible(self.idTabs[tClass], cTab.countEntries() > 0)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def _loadAllTags(self) -> None:
|
||||||
|
"""Load all tags into the tabs."""
|
||||||
|
data = SHARED.project.index.getTagsData(activeOnly=self.aInactive.isChecked())
|
||||||
|
for key, name, tClass, iItem, hItem in data:
|
||||||
|
if tClass in self.kwTabs and iItem and hItem:
|
||||||
|
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
|
||||||
|
return
|
||||||
|
|
||||||
# END Class GuiDocViewerPanel
|
# END Class GuiDocViewerPanel
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
tStart = time()
|
tStart = time()
|
||||||
logger.debug("Building novel tree for root item '%s'", rootHandle)
|
logger.debug("Building novel tree for root item '%s'", rootHandle)
|
||||||
|
|
||||||
novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, skipExcl=True)
|
novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, activeOnly=True)
|
||||||
for tKey, tHandle, sTitle, novIdx in novStruct:
|
for tKey, tHandle, sTitle, novIdx in novStruct:
|
||||||
if novIdx.level == "H0":
|
if novIdx.level == "H0":
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -646,7 +646,7 @@ class GuiOutlineTree(QTreeWidget):
|
|||||||
headItem.setTextAlignment(
|
headItem.setTextAlignment(
|
||||||
self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
|
self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
|
||||||
|
|
||||||
novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, skipExcl=True)
|
novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, activeOnly=True)
|
||||||
for _, tHandle, sTitle, novIdx in novStruct:
|
for _, tHandle, sTitle, novIdx in novStruct:
|
||||||
|
|
||||||
iLevel = nwHeaders.H_LEVEL.get(novIdx.level, 0)
|
iLevel = nwHeaders.H_LEVEL.get(novIdx.level, 0)
|
||||||
|
|||||||
@@ -579,7 +579,7 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
project.tree[nHandle].setActive(False) # type: ignore
|
project.tree[nHandle].setActive(False) # type: ignore
|
||||||
|
|
||||||
keys = []
|
keys = []
|
||||||
for aKey, _, _, _ in index.novelStructure(skipExcl=False):
|
for aKey, _, _, _ in index.novelStructure(activeOnly=False):
|
||||||
keys.append(aKey)
|
keys.append(aKey)
|
||||||
|
|
||||||
assert keys == [
|
assert keys == [
|
||||||
@@ -590,7 +590,7 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
]
|
]
|
||||||
|
|
||||||
keys = []
|
keys = []
|
||||||
for aKey, _, _, _ in index.novelStructure(skipExcl=True):
|
for aKey, _, _, _ in index.novelStructure(activeOnly=True):
|
||||||
keys.append(aKey)
|
keys.append(aKey)
|
||||||
|
|
||||||
assert keys == [
|
assert keys == [
|
||||||
@@ -761,7 +761,7 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
assert index.scanText(sHandle, "### Scene One\n\n") # type: ignore
|
assert index.scanText(sHandle, "### Scene One\n\n") # type: ignore
|
||||||
assert index.scanText(tHandle, "### Scene Two\n\n") # type: ignore
|
assert index.scanText(tHandle, "### Scene Two\n\n") # type: ignore
|
||||||
|
|
||||||
assert [(h, t) for h, t, _ in index._itemIndex.iterNovelStructure(skipExcl=False)] == [
|
assert [(h, t) for h, t, _ in index._itemIndex.iterNovelStructure(activeOnly=False)] == [
|
||||||
(C.hTitlePage, "T0001"),
|
(C.hTitlePage, "T0001"),
|
||||||
(C.hChapterDoc, "T0001"),
|
(C.hChapterDoc, "T0001"),
|
||||||
(C.hSceneDoc, "T0001"),
|
(C.hSceneDoc, "T0001"),
|
||||||
@@ -772,7 +772,7 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
(tHandle, "T0001"),
|
(tHandle, "T0001"),
|
||||||
]
|
]
|
||||||
|
|
||||||
assert [(h, t) for h, t, _ in index._itemIndex.iterNovelStructure(skipExcl=True)] == [
|
assert [(h, t) for h, t, _ in index._itemIndex.iterNovelStructure(activeOnly=True)] == [
|
||||||
(C.hTitlePage, "T0001"),
|
(C.hTitlePage, "T0001"),
|
||||||
(C.hChapterDoc, "T0001"),
|
(C.hChapterDoc, "T0001"),
|
||||||
(C.hSceneDoc, "T0001"),
|
(C.hSceneDoc, "T0001"),
|
||||||
@@ -783,7 +783,7 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
|
|
||||||
# Add a fake handle to the tree and check that it's ignored
|
# Add a fake handle to the tree and check that it's ignored
|
||||||
project.tree._order.append("0000000000000")
|
project.tree._order.append("0000000000000")
|
||||||
assert [(h, t) for h, t, _ in index._itemIndex.iterNovelStructure(skipExcl=False)] == [
|
assert [(h, t) for h, t, _ in index._itemIndex.iterNovelStructure(activeOnly=False)] == [
|
||||||
(C.hTitlePage, "T0001"),
|
(C.hTitlePage, "T0001"),
|
||||||
(C.hChapterDoc, "T0001"),
|
(C.hChapterDoc, "T0001"),
|
||||||
(C.hSceneDoc, "T0001"),
|
(C.hSceneDoc, "T0001"),
|
||||||
@@ -796,22 +796,22 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
project.tree._order.remove("0000000000000")
|
project.tree._order.remove("0000000000000")
|
||||||
|
|
||||||
# Extract stats
|
# Extract stats
|
||||||
assert index.getNovelWordCount(skipExcl=False) == 43
|
assert index.getNovelWordCount(activeOnly=False) == 43
|
||||||
assert index.getNovelWordCount(skipExcl=True) == 15
|
assert index.getNovelWordCount(activeOnly=True) == 15
|
||||||
assert index.getNovelTitleCounts(skipExcl=False) == [0, 3, 2, 3, 0]
|
assert index.getNovelTitleCounts(activeOnly=False) == [0, 3, 2, 3, 0]
|
||||||
assert index.getNovelTitleCounts(skipExcl=True) == [0, 1, 2, 3, 0]
|
assert index.getNovelTitleCounts(activeOnly=True) == [0, 1, 2, 3, 0]
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
assert index.getTableOfContents(C.hNovelRoot, 0, skipExcl=True) == []
|
assert index.getTableOfContents(C.hNovelRoot, 0, activeOnly=True) == []
|
||||||
assert index.getTableOfContents(C.hNovelRoot, 1, skipExcl=True) == [
|
assert index.getTableOfContents(C.hNovelRoot, 1, activeOnly=True) == [
|
||||||
(f"{C.hTitlePage}:T0001", 1, "New Novel", 15),
|
(f"{C.hTitlePage}:T0001", 1, "New Novel", 15),
|
||||||
]
|
]
|
||||||
assert index.getTableOfContents(C.hNovelRoot, 2, skipExcl=True) == [
|
assert index.getTableOfContents(C.hNovelRoot, 2, activeOnly=True) == [
|
||||||
(f"{C.hTitlePage}:T0001", 1, "New Novel", 5),
|
(f"{C.hTitlePage}:T0001", 1, "New Novel", 5),
|
||||||
(f"{C.hChapterDoc}:T0001", 2, "New Chapter", 4),
|
(f"{C.hChapterDoc}:T0001", 2, "New Chapter", 4),
|
||||||
(f"{hHandle}:T0001", 2, "Chapter One", 6),
|
(f"{hHandle}:T0001", 2, "Chapter One", 6),
|
||||||
]
|
]
|
||||||
assert index.getTableOfContents(C.hNovelRoot, 3, skipExcl=True) == [
|
assert index.getTableOfContents(C.hNovelRoot, 3, activeOnly=True) == [
|
||||||
(f"{C.hTitlePage}:T0001", 1, "New Novel", 5),
|
(f"{C.hTitlePage}:T0001", 1, "New Novel", 5),
|
||||||
(f"{C.hChapterDoc}:T0001", 2, "New Chapter", 2),
|
(f"{C.hChapterDoc}:T0001", 2, "New Chapter", 2),
|
||||||
(f"{C.hSceneDoc}:T0001", 3, "New Scene", 2),
|
(f"{C.hSceneDoc}:T0001", 3, "New Scene", 2),
|
||||||
@@ -820,8 +820,8 @@ def testCoreIndex_ExtractData(mockGUI, fncPath, mockRnd):
|
|||||||
(f"{tHandle}:T0001", 3, "Scene Two", 2),
|
(f"{tHandle}:T0001", 3, "Scene Two", 2),
|
||||||
]
|
]
|
||||||
|
|
||||||
assert index.getTableOfContents(C.hNovelRoot, 0, skipExcl=False) == []
|
assert index.getTableOfContents(C.hNovelRoot, 0, activeOnly=False) == []
|
||||||
assert index.getTableOfContents(C.hNovelRoot, 1, skipExcl=False) == [
|
assert index.getTableOfContents(C.hNovelRoot, 1, activeOnly=False) == [
|
||||||
(f"{C.hTitlePage}:T0001", 1, "New Novel", 9),
|
(f"{C.hTitlePage}:T0001", 1, "New Novel", 9),
|
||||||
(f"{nHandle}:T0001", 1, "Hello World!", 12),
|
(f"{nHandle}:T0001", 1, "Hello World!", 12),
|
||||||
(f"{nHandle}:T0002", 1, "Hello World!", 22),
|
(f"{nHandle}:T0002", 1, "Hello World!", 22),
|
||||||
@@ -1173,7 +1173,7 @@ def testCoreIndex_ItemIndex(mockGUI, fncPath, mockRnd):
|
|||||||
|
|
||||||
# Skip excluded
|
# Skip excluded
|
||||||
project.tree[sHandle].setActive(False) # type: ignore
|
project.tree[sHandle].setActive(False) # type: ignore
|
||||||
nStruct = list(itemIndex.iterNovelStructure(skipExcl=True))
|
nStruct = list(itemIndex.iterNovelStructure(activeOnly=True))
|
||||||
assert len(nStruct) == 3
|
assert len(nStruct) == 3
|
||||||
assert nStruct[0][0] == nHandle
|
assert nStruct[0][0] == nHandle
|
||||||
assert nStruct[1][0] == cHandle
|
assert nStruct[1][0] == cHandle
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ from PyQt5.QtGui import QIcon
|
|||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
from novelwriter.constants import nwLists
|
from novelwriter.constants import nwLists
|
||||||
|
from novelwriter.core.item import NWItem
|
||||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
|
|
||||||
|
|
||||||
@@ -216,6 +217,17 @@ def testGuiViewerPanel_Tags(qtbot, monkeypatch, caplog, nwGUI, projPath, mockRnd
|
|||||||
charTab._treeItemDoubleClicked(charTab.model().index(0, charTab.C_NAME))
|
charTab._treeItemDoubleClicked(charTab.model().index(0, charTab.C_NAME))
|
||||||
assert nwGUI.docViewer.docHandle == hJane
|
assert nwGUI.docViewer.docHandle == hJane
|
||||||
|
|
||||||
|
# Hide Inactive Tags
|
||||||
|
viewPanel.aInactive.setChecked(True)
|
||||||
|
assert charTab.topLevelItemCount() == 2
|
||||||
|
|
||||||
|
nwJohn = SHARED.project.tree[hJohn]
|
||||||
|
assert isinstance(nwJohn, NWItem)
|
||||||
|
nwJohn.setActive(False)
|
||||||
|
projTree.setTreeItemValues(hJohn)
|
||||||
|
projTree._alertTreeChange(hJohn, flush=False)
|
||||||
|
assert charTab.topLevelItemCount() == 1
|
||||||
|
|
||||||
# qtbot.stop()
|
# qtbot.stop()
|
||||||
|
|
||||||
# END Test testGuiViewerPanel_Tags
|
# END Test testGuiViewerPanel_Tags
|
||||||
|
|||||||
Reference in New Issue
Block a user