Add novel view test coverage
This commit is contained in:
@@ -26,6 +26,7 @@ from __future__ import annotations
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
from PyQt6.QtCore import pyqtSignal, pyqtSlot
|
||||||
|
from PyQt6.QtGui import QPalette
|
||||||
from PyQt6.QtWidgets import QComboBox, QWidget
|
from PyQt6.QtWidgets import QComboBox, QWidget
|
||||||
|
|
||||||
from novelwriter import SHARED
|
from novelwriter import SHARED
|
||||||
@@ -46,6 +47,7 @@ class NovelSelector(QComboBox):
|
|||||||
self._includeAll = False
|
self._includeAll = False
|
||||||
self._listFormat = None
|
self._listFormat = None
|
||||||
self.currentIndexChanged.connect(self._indexChanged)
|
self.currentIndexChanged.connect(self._indexChanged)
|
||||||
|
self.updateTheme()
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -86,6 +88,14 @@ class NovelSelector(QComboBox):
|
|||||||
self._listFormat = value
|
self._listFormat = value
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def updateTheme(self) -> None:
|
||||||
|
"""Update theme colours."""
|
||||||
|
palette = self.palette()
|
||||||
|
palette.setBrush(QPalette.ColorGroup.Disabled, QPalette.ColorRole.Text, palette.text())
|
||||||
|
self.setPalette(palette)
|
||||||
|
self.refreshNovelList()
|
||||||
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
# Public Slots
|
# Public Slots
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ class GuiDocEditor(QPlainTextEdit):
|
|||||||
editedStatusChanged = pyqtSignal(bool)
|
editedStatusChanged = pyqtSignal(bool)
|
||||||
itemHandleChanged = pyqtSignal(str)
|
itemHandleChanged = pyqtSignal(str)
|
||||||
loadDocumentTagRequest = pyqtSignal(str, Enum)
|
loadDocumentTagRequest = pyqtSignal(str, Enum)
|
||||||
novelStructureChanged = pyqtSignal()
|
|
||||||
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
||||||
requestNewNoteCreation = pyqtSignal(str, nwItemClass)
|
requestNewNoteCreation = pyqtSignal(str, nwItemClass)
|
||||||
requestNextDocument = pyqtSignal(str, bool)
|
requestNextDocument = pyqtSignal(str, bool)
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ novelWriter – GUI Novel Tree
|
|||||||
============================
|
============================
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2020-12-20 [1.1rc1] GuiNovelTree
|
Created: 2020-12-20 [1.1rc1] GuiNovelTree
|
||||||
Created: 2022-06-12 [2.0rc1] GuiNovelView
|
Created: 2022-06-12 [2.0rc1] GuiNovelView
|
||||||
Created: 2022-06-12 [2.0rc1] GuiNovelToolBar
|
Created: 2022-06-12 [2.0rc1] GuiNovelToolBar
|
||||||
|
Rewritten: 2025-02-22 [2.7b1] GuiNovelView
|
||||||
|
Rewritten: 2025-02-22 [2.7b1] GuiNovelToolBar
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
Copyright (C) 2020 Veronica Berglyd Olsen and novelWriter contributors
|
||||||
@@ -40,7 +42,7 @@ from novelwriter import CONFIG, SHARED
|
|||||||
from novelwriter.common import minmax, qtAddAction, qtAddMenu, qtLambda
|
from novelwriter.common import minmax, qtAddAction, qtAddMenu, qtLambda
|
||||||
from novelwriter.constants import nwKeyWords, nwLabels, trConst
|
from novelwriter.constants import nwKeyWords, nwLabels, trConst
|
||||||
from novelwriter.core.novelmodel import NovelModel
|
from novelwriter.core.novelmodel import NovelModel
|
||||||
from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwNovelExtra, nwOutline
|
from novelwriter.enum import nwChange, nwDocMode, nwNovelExtra, nwOutline
|
||||||
from novelwriter.extensions.modified import NIconToolButton, NTreeView
|
from novelwriter.extensions.modified import NIconToolButton, NTreeView
|
||||||
from novelwriter.extensions.novelselector import NovelSelector
|
from novelwriter.extensions.novelselector import NovelSelector
|
||||||
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
||||||
@@ -105,9 +107,6 @@ class GuiNovelView(QWidget):
|
|||||||
def openProjectTasks(self) -> None:
|
def openProjectTasks(self) -> None:
|
||||||
"""Run open project tasks."""
|
"""Run open project tasks."""
|
||||||
lastNovel = SHARED.project.data.getLastHandle("novel")
|
lastNovel = SHARED.project.data.getLastHandle("novel")
|
||||||
if lastNovel and lastNovel not in SHARED.project.tree:
|
|
||||||
lastNovel = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
|
||||||
|
|
||||||
logger.debug("Setting novel tree to root item '%s'", lastNovel)
|
logger.debug("Setting novel tree to root item '%s'", lastNovel)
|
||||||
|
|
||||||
lastCol = SHARED.project.options.getEnum(
|
lastCol = SHARED.project.options.getEnum(
|
||||||
@@ -129,13 +128,17 @@ class GuiNovelView(QWidget):
|
|||||||
|
|
||||||
def closeProjectTasks(self) -> None:
|
def closeProjectTasks(self) -> None:
|
||||||
"""Run closing project tasks."""
|
"""Run closing project tasks."""
|
||||||
|
logger.debug("Saving State: GuiNovelView")
|
||||||
|
|
||||||
lastColType = self.novelTree.lastColType
|
lastColType = self.novelTree.lastColType
|
||||||
lastColSize = self.novelTree.lastColSize
|
lastColSize = self.novelTree.lastColSize
|
||||||
logger.debug("Saving State: GuiNovelView")
|
|
||||||
options = SHARED.project.options
|
options = SHARED.project.options
|
||||||
options.setValue("GuiNovelView", "lastCol", lastColType)
|
options.setValue("GuiNovelView", "lastCol", lastColType)
|
||||||
options.setValue("GuiNovelView", "lastColSize", lastColSize)
|
options.setValue("GuiNovelView", "lastColSize", lastColSize)
|
||||||
|
|
||||||
self.clearNovelView()
|
self.clearNovelView()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def setTreeFocus(self) -> None:
|
def setTreeFocus(self) -> None:
|
||||||
@@ -154,9 +157,7 @@ class GuiNovelView(QWidget):
|
|||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def setCurrentNovel(self, rootHandle: str | None) -> None:
|
def setCurrentNovel(self, rootHandle: str | None) -> None:
|
||||||
"""Set the current novel to display."""
|
"""Set the current novel to display."""
|
||||||
if rootHandle and (model := SHARED.project.index.getNovelModel(rootHandle)):
|
self.novelTree.setNovelModel(rootHandle)
|
||||||
self.novelTree.setModel(model)
|
|
||||||
self.novelTree.resizeColumns()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
@@ -270,7 +271,7 @@ class GuiNovelToolBar(QWidget):
|
|||||||
"QComboBox {border-style: none; padding-left: 0;} "
|
"QComboBox {border-style: none; padding-left: 0;} "
|
||||||
"QComboBox::drop-down {border-style: none}"
|
"QComboBox::drop-down {border-style: none}"
|
||||||
)
|
)
|
||||||
self.novelValue.refreshNovelList()
|
self.novelValue.updateTheme()
|
||||||
self.tbNovel.setVisible(self.novelValue.count() > 1)
|
self.tbNovel.setVisible(self.novelValue.count() > 1)
|
||||||
|
|
||||||
self._forceRefreshNovelTree()
|
self._forceRefreshNovelTree()
|
||||||
@@ -286,12 +287,13 @@ class GuiNovelToolBar(QWidget):
|
|||||||
def buildNovelRootMenu(self) -> None:
|
def buildNovelRootMenu(self) -> None:
|
||||||
"""Build the novel root menu."""
|
"""Build the novel root menu."""
|
||||||
self.novelValue.refreshNovelList()
|
self.novelValue.refreshNovelList()
|
||||||
|
self.novelView.setCurrentNovel(self.novelValue.handle)
|
||||||
self.tbNovel.setVisible(self.novelValue.count() > 1)
|
self.tbNovel.setVisible(self.novelValue.count() > 1)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setCurrentRoot(self, rootHandle: str | None) -> None:
|
def setCurrentRoot(self, rootHandle: str | None) -> None:
|
||||||
"""Set the current active root handle."""
|
"""Set the current active root handle."""
|
||||||
if rootHandle is None:
|
if rootHandle is None or rootHandle not in SHARED.project.tree:
|
||||||
rootHandle = self.novelValue.firstHandle
|
rootHandle = self.novelValue.firstHandle
|
||||||
self.novelValue.setHandle(rootHandle)
|
self.novelValue.setHandle(rootHandle)
|
||||||
SHARED.project.data.setLastHandle(rootHandle, "novel")
|
SHARED.project.data.setLastHandle(rootHandle, "novel")
|
||||||
@@ -328,6 +330,7 @@ class GuiNovelToolBar(QWidget):
|
|||||||
def _forceRefreshNovelTree(self) -> None:
|
def _forceRefreshNovelTree(self) -> None:
|
||||||
"""Rebuild the current tree."""
|
"""Rebuild the current tree."""
|
||||||
if tHandle := self.novelValue.handle:
|
if tHandle := self.novelValue.handle:
|
||||||
|
self.novelView.setCurrentNovel(tHandle)
|
||||||
SHARED.project.index.refreshNovelModel(tHandle)
|
SHARED.project.index.refreshNovelModel(tHandle)
|
||||||
self._refresh[tHandle] = False
|
self._refresh[tHandle] = False
|
||||||
return
|
return
|
||||||
@@ -441,8 +444,7 @@ class GuiNovelTree(NTreeView):
|
|||||||
"""Get the currently selected or active handle. If multiple
|
"""Get the currently selected or active handle. If multiple
|
||||||
items are selected, return the first.
|
items are selected, return the first.
|
||||||
"""
|
"""
|
||||||
if model := self._getModel():
|
if (model := self._getModel()) and (index := self.currentIndex()).isValid():
|
||||||
index = self.currentIndex()
|
|
||||||
return model.handle(index), model.key(index)
|
return model.handle(index), model.key(index)
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
@@ -450,6 +452,16 @@ class GuiNovelTree(NTreeView):
|
|||||||
# Setters
|
# Setters
|
||||||
##
|
##
|
||||||
|
|
||||||
|
def setNovelModel(self, tHandle: str | None) -> None:
|
||||||
|
"""Set the current novel model."""
|
||||||
|
if tHandle and (model := SHARED.project.index.getNovelModel(tHandle)):
|
||||||
|
if model is not self.model():
|
||||||
|
self.setModel(model)
|
||||||
|
self.resizeColumns()
|
||||||
|
else:
|
||||||
|
self.clearContent()
|
||||||
|
return
|
||||||
|
|
||||||
def setActiveHandle(self, tHandle: str | None) -> None:
|
def setActiveHandle(self, tHandle: str | None) -> None:
|
||||||
"""Set the handle to be highlighted."""
|
"""Set the handle to be highlighted."""
|
||||||
self._actHandle = tHandle
|
self._actHandle = tHandle
|
||||||
@@ -560,18 +572,18 @@ class GuiNovelTree(NTreeView):
|
|||||||
|
|
||||||
def _popMetaBox(self, qPos: QPoint, tHandle: str, sTitle: str) -> None:
|
def _popMetaBox(self, qPos: QPoint, tHandle: str, sTitle: str) -> None:
|
||||||
"""Show the novel meta data box."""
|
"""Show the novel meta data box."""
|
||||||
|
def appendTags(refs: dict, key: str, lines: list[str]) -> None:
|
||||||
|
"""Generate a reference list for a given reference key."""
|
||||||
|
if tags := ", ".join(refs.get(key, [])):
|
||||||
|
lines.append(f"<b>{trConst(nwLabels.KEY_NAME[key])}:</b> {tags}")
|
||||||
|
return
|
||||||
|
|
||||||
if head := SHARED.project.index.getItemHeading(tHandle, sTitle):
|
if head := SHARED.project.index.getItemHeading(tHandle, sTitle):
|
||||||
logger.debug("Generating meta data tooltip for '%s:%s'", tHandle, sTitle)
|
logger.debug("Generating meta data tooltip for '%s:%s'", tHandle, sTitle)
|
||||||
if synopsis := head.synopsis:
|
if synopsis := head.synopsis:
|
||||||
label = trConst(nwLabels.OUTLINE_COLS[nwOutline.SYNOP])
|
label = trConst(nwLabels.OUTLINE_COLS[nwOutline.SYNOP])
|
||||||
synopsis = f"<p><b>{label}:</b> {synopsis}</p>"
|
synopsis = f"<p><b>{label}:</b> {synopsis}</p>"
|
||||||
|
|
||||||
def appendTags(refs: dict, key: str, lines: list[str]) -> None:
|
|
||||||
"""Generate a reference list for a given reference key."""
|
|
||||||
if tags := ", ".join(refs.get(key, [])):
|
|
||||||
lines.append(f"<b>{trConst(nwLabels.KEY_NAME[key])}:</b> {tags}")
|
|
||||||
return
|
|
||||||
|
|
||||||
lines = []
|
lines = []
|
||||||
if head := SHARED.project.index.getItemHeading(tHandle, sTitle):
|
if head := SHARED.project.index.getItemHeading(tHandle, sTitle):
|
||||||
tags = head.getReferences()
|
tags = head.getReferences()
|
||||||
|
|||||||
@@ -24,22 +24,19 @@ from pathlib import Path
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PyQt6.QtCore import QEvent, QPoint, Qt
|
from PyQt6.QtCore import QModelIndex, QPoint, Qt
|
||||||
from PyQt6.QtGui import QFocusEvent
|
|
||||||
from PyQt6.QtWidgets import QInputDialog, QToolTip
|
from PyQt6.QtWidgets import QInputDialog, QToolTip
|
||||||
|
|
||||||
from novelwriter import CONFIG, SHARED
|
from novelwriter import CONFIG, SHARED
|
||||||
|
from novelwriter.core.novelmodel import NovelModel
|
||||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
from novelwriter.enum import nwFocus, nwItemType, nwNovelExtra
|
from novelwriter.enum import nwFocus, nwItemType, nwNovelExtra, nwView
|
||||||
from novelwriter.gui.noveltree import GuiNovelTree
|
|
||||||
from novelwriter.types import QtMouseLeft, QtMouseMiddle
|
|
||||||
|
|
||||||
from tests.tools import C, buildTestProject
|
from tests.tools import C, buildTestProject
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gui
|
@pytest.mark.gui
|
||||||
@pytest.mark.skip
|
def testGuiNovelView_Content(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||||
def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
|
||||||
"""Test navigating the novel tree."""
|
"""Test navigating the novel tree."""
|
||||||
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
|
||||||
|
|
||||||
@@ -52,20 +49,22 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
|||||||
|
|
||||||
contentPath = SHARED.project.storage.contentPath
|
contentPath = SHARED.project.storage.contentPath
|
||||||
assert isinstance(contentPath, Path)
|
assert isinstance(contentPath, Path)
|
||||||
|
cHandle = "0000000000010"
|
||||||
|
|
||||||
(contentPath / "0000000000010.nwd").write_text(
|
(contentPath / f"{cHandle}.nwd").write_text(
|
||||||
"# Jane Doe\n\n@tag: Jane\n\n", encoding="utf-8"
|
"# Jane Doe\n\n@tag: Jane\n\n", encoding="utf-8"
|
||||||
)
|
)
|
||||||
(contentPath / "000000000000f.nwd").write_text((
|
(contentPath / f"{C.hSceneDoc}.nwd").write_text((
|
||||||
"### Scene One\n\n"
|
"### Scene One\n\n"
|
||||||
"@pov: Jane\n"
|
"@pov: Jane\n"
|
||||||
"@focus: Jane\n\n"
|
"@focus: Jane\n\n"
|
||||||
"% Synopsis: This is a scene."
|
"% Synopsis: This is a scene.\n\n"
|
||||||
|
"This is some text in the edited scene."
|
||||||
), encoding="utf-8")
|
), encoding="utf-8")
|
||||||
|
|
||||||
novelView = nwGUI.novelView
|
novelView = nwGUI.novelView
|
||||||
novelTree = novelView.novelTree
|
novelTree = nwGUI.novelView.novelTree
|
||||||
novelBar = novelView.novelBar
|
novelBar = nwGUI.novelView.novelBar
|
||||||
|
|
||||||
# Show/Hide Scrollbars
|
# Show/Hide Scrollbars
|
||||||
# ====================
|
# ====================
|
||||||
@@ -84,153 +83,101 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
|||||||
|
|
||||||
# Populate Tree
|
# Populate Tree
|
||||||
# =============
|
# =============
|
||||||
|
root = QModelIndex()
|
||||||
|
|
||||||
novelView.setTreeFocus()
|
novelView.setTreeFocus()
|
||||||
|
nwGUI._changeView(nwView.NOVEL)
|
||||||
|
|
||||||
nwGUI.projStack.setCurrentWidget(nwGUI.novelView)
|
# Clear tree
|
||||||
nwGUI.rebuildIndex()
|
novelView.setCurrentNovel(None)
|
||||||
novelTree._populateTree(rootHandle=None)
|
assert novelTree._getModel() is None
|
||||||
assert novelTree.topLevelItemCount() == 3
|
|
||||||
|
|
||||||
# Rebuild should preserve selection
|
# Reload
|
||||||
topItem = novelTree.topLevelItem(0)
|
novelBar._forceRefreshNovelTree()
|
||||||
assert not topItem.isSelected()
|
model = novelTree._getModel()
|
||||||
topItem.setSelected(True)
|
assert isinstance(model, NovelModel)
|
||||||
assert novelTree.selectedItems()[0] == topItem
|
|
||||||
assert novelView.getSelectedHandle() == (C.hTitlePage, "T0001")
|
|
||||||
|
|
||||||
# Refresh using the slot for the button
|
# Check the items
|
||||||
novelBar._refreshNovelTree()
|
assert model.rowCount(root) == 3
|
||||||
assert novelTree.topLevelItem(0).isSelected()
|
assert model.columnCount(root) == 3
|
||||||
|
assert model.data(model.createIndex(2, 1), Qt.ItemDataRole.DisplayRole) == "2" # Word Count
|
||||||
|
|
||||||
|
nwGUI.rebuildIndex() # This should update the word count to the edited scene
|
||||||
|
assert model.data(model.createIndex(2, 1), Qt.ItemDataRole.DisplayRole) == "10" # Word Count
|
||||||
|
|
||||||
|
# Extra Column
|
||||||
|
# ============
|
||||||
|
novelBar.setLastColType(nwNovelExtra.POV)
|
||||||
|
assert model.rowCount(root) == 3
|
||||||
|
assert model.columnCount(root) == 4
|
||||||
|
|
||||||
|
# Scene column should contain the POV character
|
||||||
|
assert model.data(model.createIndex(2, 2), Qt.ItemDataRole.DisplayRole) == "Jane"
|
||||||
|
|
||||||
|
# Resize the last column
|
||||||
|
assert novelTree.lastColSize == 25
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(QInputDialog, "getInt", lambda *a, **k: (40, True))
|
||||||
|
novelBar._selectLastColumnSize()
|
||||||
|
assert novelTree.lastColSize == 40
|
||||||
|
|
||||||
# Open Items
|
# Open Items
|
||||||
# ==========
|
# ==========
|
||||||
|
|
||||||
# Clear selection
|
# Clear selection
|
||||||
novelTree.clearSelection()
|
novelTree.clearSelection()
|
||||||
scItem = novelTree.topLevelItem(2)
|
assert novelView.getSelectedHandle() == (None, None)
|
||||||
scItem.setSelected(True)
|
|
||||||
assert scItem.isSelected()
|
|
||||||
|
|
||||||
# Clear selection with mouse
|
# Select scene
|
||||||
vPort = novelTree.viewport()
|
novelTree.setCurrentIndex(model.createIndex(2, 0))
|
||||||
qtbot.mouseClick(vPort, QtMouseLeft, pos=vPort.rect().center(), delay=10)
|
assert novelView.getSelectedHandle() == (C.hSceneDoc, "T0001")
|
||||||
assert not scItem.isSelected()
|
|
||||||
|
|
||||||
# Double-click item
|
# Double-click item
|
||||||
scItem.setSelected(True)
|
novelTree._onDoubleClick(model.createIndex(2, 0))
|
||||||
assert scItem.isSelected()
|
|
||||||
assert nwGUI.docEditor.docHandle is None
|
|
||||||
novelTree._treeDoubleClick(scItem, 0)
|
|
||||||
assert nwGUI.docEditor.docHandle == C.hSceneDoc
|
assert nwGUI.docEditor.docHandle == C.hSceneDoc
|
||||||
|
|
||||||
# Open item with middle mouse button
|
# Middle-click item
|
||||||
scItem.setSelected(True)
|
novelTree._onMiddleClick(model.createIndex(2, 0))
|
||||||
assert scItem.isSelected()
|
|
||||||
assert nwGUI.docViewer.docHandle is None
|
|
||||||
qtbot.mouseClick(vPort, QtMouseMiddle, pos=vPort.rect().center(), delay=10)
|
|
||||||
assert nwGUI.docViewer.docHandle is None
|
|
||||||
|
|
||||||
scRect = novelTree.visualItemRect(scItem)
|
|
||||||
oldData = scItem.data(novelTree.C_TITLE, novelTree.D_HANDLE)
|
|
||||||
scItem.setData(novelTree.C_TITLE, novelTree.D_HANDLE, None)
|
|
||||||
qtbot.mouseClick(vPort, QtMouseMiddle, pos=scRect.center(), delay=10)
|
|
||||||
assert nwGUI.docViewer.docHandle is None
|
|
||||||
|
|
||||||
scItem.setData(novelTree.C_TITLE, novelTree.D_HANDLE, oldData)
|
|
||||||
qtbot.mouseClick(vPort, QtMouseMiddle, pos=scRect.center(), delay=10)
|
|
||||||
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
assert nwGUI.docViewer.docHandle == C.hSceneDoc
|
||||||
|
|
||||||
# Last Column
|
|
||||||
# ===========
|
|
||||||
|
|
||||||
novelBar.setLastColType(nwNovelExtra.HIDDEN)
|
|
||||||
assert novelTree.isColumnHidden(novelTree.C_EXTRA) is True
|
|
||||||
assert novelTree.lastColType == nwNovelExtra.HIDDEN
|
|
||||||
assert novelTree._getLastColumnText(C.hSceneDoc, "T0001") == ("", "")
|
|
||||||
|
|
||||||
novelBar.setLastColType(nwNovelExtra.PLOT)
|
|
||||||
assert novelTree.isColumnHidden(novelTree.C_EXTRA) is False
|
|
||||||
assert novelTree.lastColType == nwNovelExtra.PLOT
|
|
||||||
assert novelTree._getLastColumnText(C.hSceneDoc, "T0001") == (
|
|
||||||
"", ""
|
|
||||||
)
|
|
||||||
|
|
||||||
novelBar.setLastColType(nwNovelExtra.FOCUS)
|
|
||||||
assert novelTree.isColumnHidden(novelTree.C_EXTRA) is False
|
|
||||||
assert novelTree.lastColType == nwNovelExtra.FOCUS
|
|
||||||
assert novelTree._getLastColumnText(C.hSceneDoc, "T0001") == (
|
|
||||||
"Jane", "Focus: Jane"
|
|
||||||
)
|
|
||||||
|
|
||||||
novelBar.setLastColType(nwNovelExtra.POV)
|
|
||||||
assert novelTree.isColumnHidden(novelTree.C_EXTRA) is False
|
|
||||||
assert novelTree.lastColType == nwNovelExtra.POV
|
|
||||||
assert novelTree._getLastColumnText(C.hSceneDoc, "T0001") == (
|
|
||||||
"Jane", "Point of View: Jane"
|
|
||||||
)
|
|
||||||
|
|
||||||
novelTree._lastCol = None
|
|
||||||
assert novelTree._getLastColumnText("0000000000000", "T0000") == ("", "")
|
|
||||||
|
|
||||||
# This forces the resizeEvent function to process labels
|
|
||||||
spSize = nwGUI.splitMain.sizes()
|
|
||||||
nwGUI.splitMain.setSizes([spSize[0] + 10, spSize[1] - 10])
|
|
||||||
|
|
||||||
# Resize the last column
|
|
||||||
with monkeypatch.context() as mp:
|
|
||||||
mp.setattr(QInputDialog, "getInt", lambda *a, **k: (40, True))
|
|
||||||
novelBar._selectLastColumnSize()
|
|
||||||
|
|
||||||
# Item Meta
|
# Item Meta
|
||||||
# =========
|
# =========
|
||||||
|
|
||||||
ttText = ""
|
toolTip = ""
|
||||||
|
|
||||||
def showText(pos, text):
|
def showText(pos, text):
|
||||||
nonlocal ttText
|
nonlocal toolTip
|
||||||
ttText = text
|
toolTip = text
|
||||||
|
|
||||||
mIndex = novelTree.model().index(2, novelTree.C_MORE)
|
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr(QToolTip, "showText", showText)
|
mp.setattr(QToolTip, "showText", showText)
|
||||||
|
|
||||||
ttText = ""
|
toolTip = ""
|
||||||
novelTree._treeItemClicked(mIndex)
|
novelTree._onSingleClick(model.createIndex(2, 3))
|
||||||
assert ttText == (
|
assert toolTip == (
|
||||||
"<p><b>Point of View</b>: Jane<br><b>Focus</b>: Jane</p>"
|
"<p><b>Point of View:</b> Jane<br><b>Focus:</b> Jane</p>"
|
||||||
"<p><b>Synopsis</b>: This is a scene.</p>"
|
"<p><b>Synopsis:</b> This is a scene.</p>"
|
||||||
)
|
)
|
||||||
|
|
||||||
ttText = ""
|
toolTip = ""
|
||||||
novelTree._popMetaBox(QPoint(1, 1), C.hInvalid, "T0001")
|
novelTree._popMetaBox(QPoint(1, 1), C.hInvalid, "T0001")
|
||||||
assert ttText == ""
|
assert toolTip == ""
|
||||||
|
|
||||||
# Set Default Root
|
# Active Status
|
||||||
# ================
|
# =============
|
||||||
SHARED.project.data.setLastHandle(C.hInvalid, "novel")
|
assert novelBar._refresh == {C.hNovelRoot: False}
|
||||||
novelView.openProjectTasks()
|
|
||||||
assert novelBar.novelValue.handle == C.hNovelRoot
|
|
||||||
|
|
||||||
# Tree Focus
|
# Add a document while tree in focus
|
||||||
# ==========
|
nwGUI._changeView(nwView.PROJECT)
|
||||||
with monkeypatch.context() as mp:
|
assert novelBar._active is False
|
||||||
mp.setattr(GuiNovelTree, "hasFocus", lambda *a: False)
|
nwGUI.projView.projTree.setSelectedHandle(C.hChapterDir)
|
||||||
assert novelView.treeHasFocus() is False
|
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=3)
|
||||||
mp.setattr(GuiNovelTree, "hasFocus", lambda *a: True)
|
assert novelBar._refresh == {C.hNovelRoot: True}
|
||||||
assert novelView.treeHasFocus() is True
|
|
||||||
|
|
||||||
# Other Checks
|
# Switch back and check that the refresh status is reset
|
||||||
# ============
|
nwGUI._changeView(nwView.NOVEL)
|
||||||
|
assert novelBar._refresh == {C.hNovelRoot: False}
|
||||||
scItem = novelTree.topLevelItem(2)
|
|
||||||
scItem.setSelected(True)
|
|
||||||
assert scItem.isSelected()
|
|
||||||
novelTree.focusOutEvent(QFocusEvent(QEvent.Type.None_, Qt.FocusReason.MouseFocusReason))
|
|
||||||
assert not scItem.isSelected()
|
|
||||||
|
|
||||||
# Close
|
# Close
|
||||||
# =====
|
|
||||||
|
|
||||||
# qtbot.stop()
|
# qtbot.stop()
|
||||||
nwGUI.closeProject()
|
nwGUI.closeProject()
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ def buildTestProject(obj: object, projPath: Path) -> None:
|
|||||||
project.setProjectChanged(True)
|
project.setProjectChanged(True)
|
||||||
project.saveProject(autoSave=True)
|
project.saveProject(autoSave=True)
|
||||||
project._valid = True
|
project._valid = True
|
||||||
|
project._tree._ready = True
|
||||||
|
|
||||||
if nwGUI is not None:
|
if nwGUI is not None:
|
||||||
nwGUI.projView.openProjectTasks()
|
nwGUI.projView.openProjectTasks()
|
||||||
|
|||||||
Reference in New Issue
Block a user