Update tests other than tree-related
This commit is contained in:
@@ -91,6 +91,10 @@ class ProjectNode:
|
||||
f"children={len(self._children)}>"
|
||||
)
|
||||
|
||||
def __bool__(self) -> bool:
|
||||
"""A node should always evaluate to True."""
|
||||
return True
|
||||
|
||||
##
|
||||
# Properties
|
||||
##
|
||||
@@ -190,10 +194,10 @@ class ProjectNode:
|
||||
self._updateRelationships(child)
|
||||
if 0 <= pos < len(self._children):
|
||||
self._children.insert(pos, child)
|
||||
self._refreshChildrenPos()
|
||||
else:
|
||||
child._row = len(self._children)
|
||||
self._children.append(child)
|
||||
self._refreshChildrenPos()
|
||||
return
|
||||
|
||||
def takeChild(self, pos: int) -> ProjectNode | None:
|
||||
@@ -229,6 +233,7 @@ class ProjectNode:
|
||||
"""Update the row value on all children."""
|
||||
for n, child in enumerate(self._children):
|
||||
child._row = n
|
||||
child.item.setOrder(n)
|
||||
return
|
||||
|
||||
def _updateRelationships(self, child: ProjectNode) -> None:
|
||||
|
||||
@@ -44,6 +44,7 @@ from novelwriter.core.options import OptionState
|
||||
from novelwriter.core.projectdata import NWProjectData
|
||||
from novelwriter.core.projectxml import ProjectXMLReader, ProjectXMLWriter, XMLReadState
|
||||
from novelwriter.core.sessions import NWSessionLog
|
||||
from novelwriter.core.status import T_StatusKinds, T_UpdateEntry
|
||||
from novelwriter.core.storage import NWStorage, NWStorageOpen
|
||||
from novelwriter.core.tree import NWTree
|
||||
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
||||
@@ -531,6 +532,18 @@ class NWProject:
|
||||
self._data.itemImport.increment(nwItem.itemImport)
|
||||
return
|
||||
|
||||
def updateStatus(self, kind: T_StatusKinds, update: T_UpdateEntry) -> None:
|
||||
"""Update status or import entries."""
|
||||
if kind == "s":
|
||||
self._data.itemStatus.update(update)
|
||||
SHARED.projectSignalProxy({"event": "statusLabels", "kind": kind})
|
||||
self._tree.refreshAllItems()
|
||||
elif kind == "i":
|
||||
self._data.itemImport.update(update)
|
||||
SHARED.projectSignalProxy({"event": "statusLabels", "kind": kind})
|
||||
self._tree.refreshAllItems()
|
||||
return
|
||||
|
||||
def localLookup(self, word: str | int) -> str:
|
||||
"""Look up a word or number in the translation map for the
|
||||
project and return it. The variable is cast to a string before
|
||||
|
||||
@@ -65,6 +65,9 @@ class StatusEntry:
|
||||
|
||||
NO_ENTRY = StatusEntry("", QColor(0, 0, 0), nwStatusShape.SQUARE, QIcon(), 0)
|
||||
|
||||
T_UpdateEntry = list[tuple[str | None, StatusEntry]]
|
||||
T_StatusKinds = Literal["s", "i"]
|
||||
|
||||
|
||||
class NWStatus:
|
||||
|
||||
@@ -73,7 +76,7 @@ class NWStatus:
|
||||
|
||||
__slots__ = ("_store", "_default", "_prefix", "_height")
|
||||
|
||||
def __init__(self, prefix: Literal["s", "i"]) -> None:
|
||||
def __init__(self, prefix: T_StatusKinds) -> None:
|
||||
self._store: dict[str, StatusEntry] = {}
|
||||
self._default = None
|
||||
self._prefix = prefix[:1]
|
||||
@@ -120,7 +123,7 @@ class NWStatus:
|
||||
|
||||
return key
|
||||
|
||||
def update(self, update: list[tuple[str | None, StatusEntry]]) -> None:
|
||||
def update(self, update: T_UpdateEntry) -> None:
|
||||
"""Update the list of statuses."""
|
||||
self._store.clear()
|
||||
for key, entry in update:
|
||||
@@ -130,10 +133,6 @@ class NWStatus:
|
||||
if self._default not in self._store:
|
||||
self._default = next(iter(self._store)) if self._store else None
|
||||
|
||||
# Emit the change signal and refresh tree
|
||||
SHARED.projectSignalProxy({"event": "statusLabels", "kind": self._prefix})
|
||||
SHARED.project.tree.refreshAllItems()
|
||||
|
||||
return
|
||||
|
||||
def check(self, value: str) -> str:
|
||||
|
||||
@@ -128,7 +128,7 @@ class NWTree:
|
||||
self._model.insertChild(node, index, pos)
|
||||
self._nodes[item.itemHandle] = node
|
||||
self._items[item.itemHandle] = item
|
||||
self._itemChange(item.itemHandle, nwChange.CREATE)
|
||||
self._itemChange(item, nwChange.CREATE)
|
||||
else:
|
||||
logger.error("Could not locate parent of '%s'", item.itemHandle)
|
||||
return False
|
||||
@@ -137,7 +137,7 @@ class NWTree:
|
||||
self._model.insertChild(node, QModelIndex(), pos)
|
||||
self._nodes[item.itemHandle] = node
|
||||
self._items[item.itemHandle] = item
|
||||
self._itemChange(item.itemHandle, nwChange.CREATE)
|
||||
self._itemChange(item, nwChange.CREATE)
|
||||
else:
|
||||
logger.error("Invalid project item '%s'", item.itemHandle)
|
||||
return False
|
||||
@@ -148,7 +148,7 @@ class NWTree:
|
||||
if (node := self._nodes.get(tHandle)) and tHandle in self._items:
|
||||
index = self._model.indexFromNode(node)
|
||||
if index.isValid() and self._model.removeChild(index.parent(), index.row()):
|
||||
self._itemChange(tHandle, nwChange.DELETE)
|
||||
self._itemChange(node.item, nwChange.DELETE)
|
||||
del self._nodes[tHandle]
|
||||
del self._items[tHandle]
|
||||
return True
|
||||
@@ -246,7 +246,7 @@ class NWTree:
|
||||
indexS = self._model.indexFromNode(node, 0)
|
||||
indexE = self._model.indexFromNode(node, 3)
|
||||
self._model.dataChanged.emit(indexS, indexE)
|
||||
self._itemChange(tHandle, nwChange.UPDATE)
|
||||
self._itemChange(node.item, nwChange.UPDATE)
|
||||
return
|
||||
|
||||
def refreshAllItems(self) -> None:
|
||||
@@ -464,11 +464,18 @@ class NWTree:
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _itemChange(self, tHandle: str, change: nwChange) -> None:
|
||||
def _itemChange(self, item: NWItem, change: nwChange) -> None:
|
||||
"""Signal item change and notify project."""
|
||||
tHandle = item.itemHandle
|
||||
logger.debug("Item change: %s -> %s", tHandle, change.name)
|
||||
self._project.setProjectChanged(True)
|
||||
SHARED.projectSignalProxy({"event": "itemChanged", "handle": tHandle, "change": change})
|
||||
SHARED.projectSignalProxy(
|
||||
{"event": "itemChanged", "handle": tHandle, "change": change}
|
||||
)
|
||||
if item.isRootType():
|
||||
SHARED.projectSignalProxy(
|
||||
{"event": "rootChanged", "handle": tHandle, "change": change}
|
||||
)
|
||||
return
|
||||
|
||||
def _getTrashNode(self) -> ProjectNode | None:
|
||||
|
||||
@@ -185,11 +185,11 @@ class GuiProjectSettings(NDialog):
|
||||
|
||||
if self.statusPage.changed:
|
||||
logger.debug("Updating status labels")
|
||||
project.data.itemStatus.update(self.statusPage.getNewList())
|
||||
project.updateStatus("s", self.statusPage.getNewList())
|
||||
|
||||
if self.importPage.changed:
|
||||
logger.debug("Updating importance labels")
|
||||
project.data.itemImport.update(self.importPage.getNewList())
|
||||
project.updateStatus("i", self.importPage.getNewList())
|
||||
|
||||
if self.replacePage.changed:
|
||||
logger.debug("Updating auto-replace settings")
|
||||
|
||||
@@ -41,7 +41,7 @@ from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import minmax, qtLambda
|
||||
from novelwriter.constants import nwKeyWords, nwLabels, nwStyles, trConst
|
||||
from novelwriter.core.index import IndexHeading
|
||||
from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
|
||||
from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwOutline
|
||||
from novelwriter.extensions.modified import NIconToolButton
|
||||
from novelwriter.extensions.novelselector import NovelSelector
|
||||
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
||||
@@ -174,8 +174,8 @@ class GuiNovelView(QWidget):
|
||||
self.novelTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("novelTree"))
|
||||
return
|
||||
|
||||
@pyqtSlot(str)
|
||||
def updateRootItem(self, tHandle: str) -> None:
|
||||
@pyqtSlot(str, Enum)
|
||||
def updateRootItem(self, tHandle: str, change: nwChange) -> None:
|
||||
"""If any root item changes, rebuild the novel root menu."""
|
||||
self.novelBar.buildNovelRootMenu()
|
||||
return
|
||||
|
||||
+10
-11
@@ -43,7 +43,7 @@ from PyQt5.QtWidgets import (
|
||||
from novelwriter import CONFIG, SHARED
|
||||
from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
|
||||
from novelwriter.constants import nwKeyWords, nwLabels, nwStats, nwStyles, trConst
|
||||
from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
||||
from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
||||
from novelwriter.error import logException
|
||||
from novelwriter.extensions.configlayout import NColourLabel
|
||||
from novelwriter.extensions.novelselector import NovelSelector
|
||||
@@ -165,8 +165,8 @@ class GuiOutlineView(QWidget):
|
||||
# Public Slots
|
||||
##
|
||||
|
||||
@pyqtSlot(str)
|
||||
def updateRootItem(self, tHandle: str) -> None:
|
||||
@pyqtSlot(str, Enum)
|
||||
def updateRootItem(self, tHandle: str, change: nwChange) -> None:
|
||||
"""Handle tasks whenever a root folders changes."""
|
||||
self.outlineBar.populateNovelList()
|
||||
self.outlineData.updateClasses()
|
||||
@@ -380,8 +380,8 @@ class GuiOutlineTree(QTreeWidget):
|
||||
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
||||
self.setExpandsOnDoubleClick(False)
|
||||
self.setDragEnabled(False)
|
||||
self.itemDoubleClicked.connect(self._treeDoubleClick)
|
||||
self.itemSelectionChanged.connect(self._itemSelected)
|
||||
self.itemDoubleClicked.connect(self._onItemDoubleClicked)
|
||||
self.itemSelectionChanged.connect(self._onItemSelectionChanged)
|
||||
|
||||
self.setIconSize(SHARED.theme.baseIconSize)
|
||||
self.setIndentation(0)
|
||||
@@ -563,7 +563,7 @@ class GuiOutlineTree(QTreeWidget):
|
||||
##
|
||||
|
||||
@pyqtSlot("QTreeWidgetItem*", int)
|
||||
def _treeDoubleClick(self, tItem: QTreeWidgetItem, tCol: int) -> None:
|
||||
def _onItemDoubleClicked(self, tItem: QTreeWidgetItem, tCol: int) -> None:
|
||||
"""Extract the handle and line number of the title double-
|
||||
clicked, and send it to the main gui class for opening in the
|
||||
document editor.
|
||||
@@ -574,14 +574,13 @@ class GuiOutlineTree(QTreeWidget):
|
||||
return
|
||||
|
||||
@pyqtSlot()
|
||||
def _itemSelected(self) -> None:
|
||||
def _onItemSelectionChanged(self) -> None:
|
||||
"""Extract the handle and line number of the currently selected
|
||||
title, and send it to the details panel.
|
||||
"""
|
||||
selItems = self.selectedItems()
|
||||
if selItems:
|
||||
tHandle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE)
|
||||
sTitle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
|
||||
if items := self.selectedItems():
|
||||
tHandle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE)
|
||||
sTitle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
|
||||
self.activeItemChanged.emit(tHandle, sTitle)
|
||||
return
|
||||
|
||||
|
||||
@@ -66,15 +66,9 @@ class GuiProjectView(QWidget):
|
||||
available are mapped through to the project tree class.
|
||||
"""
|
||||
|
||||
# Signals triggered when the meta data values of items change
|
||||
rootFolderChanged = pyqtSignal(str)
|
||||
|
||||
# Signals for user interaction with the project tree
|
||||
selectedItemChanged = pyqtSignal(str)
|
||||
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
||||
|
||||
# Requests for the main GUI
|
||||
projectSettingsRequest = pyqtSignal(int)
|
||||
selectedItemChanged = pyqtSignal(str)
|
||||
|
||||
def __init__(self, parent: QWidget) -> None:
|
||||
super().__init__(parent=parent)
|
||||
@@ -229,8 +223,8 @@ class GuiProjectView(QWidget):
|
||||
self.projTree.newTreeItem(nwItemType.FILE, copyDoc=tHandle)
|
||||
return
|
||||
|
||||
@pyqtSlot(str)
|
||||
def updateRootItem(self, tHandle: str) -> None:
|
||||
@pyqtSlot(str, Enum)
|
||||
def updateRootItem(self, tHandle: str, change: nwChange) -> None:
|
||||
"""Process root item changes."""
|
||||
self.projBar.buildQuickLinksMenu()
|
||||
return
|
||||
@@ -625,9 +619,8 @@ class GuiProjectTree(QTreeView):
|
||||
if root := SHARED.project.tree.nodes.get(itemRoot):
|
||||
pos = root.row() + 1
|
||||
|
||||
SHARED.project.newRoot(itemClass, pos)
|
||||
tHandle = SHARED.project.newRoot(itemClass, pos)
|
||||
self.restoreExpandedState()
|
||||
self.projView.rootFolderChanged.emit(tHandle)
|
||||
|
||||
elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
|
||||
|
||||
@@ -684,7 +677,10 @@ class GuiProjectTree(QTreeView):
|
||||
SHARED.project.index.reIndexHandle(tHandle)
|
||||
SHARED.project.tree.refreshItems([tHandle])
|
||||
else:
|
||||
SHARED.project.newFolder(newLabel, sHandle, pos)
|
||||
tHandle = SHARED.project.newFolder(newLabel, sHandle, pos)
|
||||
|
||||
# Select the new item automatically
|
||||
self.setSelectedHandle(tHandle)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -221,6 +221,9 @@ class GuiMain(QMainWindow):
|
||||
SHARED.projectItemChanged.connect(self.projView.onProjectItemChanged)
|
||||
SHARED.projectStatusChanged.connect(self.mainStatus.updateProjectStatus)
|
||||
SHARED.projectStatusMessage.connect(self.mainStatus.setStatusMessage)
|
||||
SHARED.rootFolderChanged.connect(self.novelView.updateRootItem)
|
||||
SHARED.rootFolderChanged.connect(self.outlineView.updateRootItem)
|
||||
SHARED.rootFolderChanged.connect(self.projView.updateRootItem)
|
||||
SHARED.spellLanguageChanged.connect(self.mainStatus.setLanguage)
|
||||
SHARED.statusLabelsChanged.connect(self.docViewerPanel.updateStatusLabels)
|
||||
|
||||
@@ -235,9 +238,6 @@ class GuiMain(QMainWindow):
|
||||
|
||||
self.projView.openDocumentRequest.connect(self._openDocument)
|
||||
self.projView.projectSettingsRequest.connect(self.showProjectSettingsDialog)
|
||||
self.projView.rootFolderChanged.connect(self.novelView.updateRootItem)
|
||||
self.projView.rootFolderChanged.connect(self.outlineView.updateRootItem)
|
||||
self.projView.rootFolderChanged.connect(self.projView.updateRootItem)
|
||||
self.projView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
|
||||
|
||||
self.novelView.openDocumentRequest.connect(self._openDocument)
|
||||
@@ -1083,6 +1083,9 @@ class GuiMain(QMainWindow):
|
||||
self.projView.initSettings()
|
||||
self.novelView.initSettings()
|
||||
self.outlineView.initSettings()
|
||||
|
||||
# Force update of word count
|
||||
self._lastTotalCount = 0
|
||||
self._updateStatusWordCount()
|
||||
|
||||
return
|
||||
|
||||
@@ -63,6 +63,7 @@ class SharedData(QObject):
|
||||
indexCleared = pyqtSignal()
|
||||
mainClockTick = pyqtSignal()
|
||||
projectItemChanged = pyqtSignal(str, Enum)
|
||||
rootFolderChanged = pyqtSignal(str, Enum)
|
||||
projectStatusChanged = pyqtSignal(bool)
|
||||
projectStatusMessage = pyqtSignal(str)
|
||||
spellLanguageChanged = pyqtSignal(str, str)
|
||||
@@ -338,6 +339,10 @@ class SharedData(QObject):
|
||||
self.projectItemChanged.emit(
|
||||
data.get("handle", ""), data.get("change", nwChange.UPDATE)
|
||||
)
|
||||
elif event == "rootChanged":
|
||||
self.rootFolderChanged.emit(
|
||||
data.get("handle", ""), data.get("change", nwChange.UPDATE)
|
||||
)
|
||||
return
|
||||
|
||||
##
|
||||
|
||||
Reference in New Issue
Block a user