Rewrite how project items are refreshed on the GUI

This commit is contained in:
Veronica Berglyd Olsen
2024-11-18 17:51:05 +01:00
parent 337f05f60e
commit df0244095f
5 changed files with 41 additions and 39 deletions
+10 -21
View File
@@ -55,7 +55,7 @@ class NWItem:
"_project", "_name", "_handle", "_parent", "_root", "_order",
"_type", "_class", "_layout", "_status", "_import", "_active",
"_expanded", "_heading", "_charCount", "_wordCount",
"_paraCount", "_cursorPos", "_initCount", "_blocked",
"_paraCount", "_cursorPos", "_initCount",
)
def __init__(self, project: NWProject, handle: str) -> None:
@@ -82,8 +82,6 @@ class NWItem:
self._cursorPos = 0 # Last cursor position
self._initCount = 0 # Initial word count
self._blocked = True
return
def __repr__(self) -> str:
@@ -259,7 +257,6 @@ class NWItem:
self._cursorPos = 0
self._initCount = self._wordCount
self._blocked = False
return True
@@ -284,9 +281,17 @@ class NWItem:
cls._paraCount = source._paraCount
cls._cursorPos = source._cursorPos
cls._initCount = source._initCount
cls._blocked = source._blocked
return cls
##
# Action Methods
##
def notifyToRefresh(self) -> None:
"""Notify GUI that item info needs to be refreshed."""
self._project.tree.refreshItems([self._handle])
return
##
# Lookup Methods
##
@@ -419,7 +424,6 @@ class NWItem:
self._name = simplified(name)
else:
self._name = ""
self._notifyChange()
return
def setParent(self, handle: Any) -> None:
@@ -560,18 +564,3 @@ class NWItem:
else:
self._cursorPos = 0
return
def saveInitialCount(self) -> None:
"""Save the initial word count."""
self._initCount = self._wordCount
return
##
# Internal Functions
##
def _notifyChange(self) -> None:
"""Notify project tree on user changes to the item."""
if not self._blocked:
self._project.tree.refreshNode(self._handle)
return
+15 -6
View File
@@ -26,7 +26,7 @@ from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any
from typing import TYPE_CHECKING
from PyQt5.QtCore import QAbstractItemModel, QModelIndex, Qt
from PyQt5.QtGui import QIcon
@@ -53,6 +53,8 @@ C_ACTIVE_TIP = 0x0200 | Qt.ItemDataRole.ToolTipRole
C_STATUS_ICON = 0x0300 | Qt.ItemDataRole.DecorationRole
C_STATUS_TIP = 0x0300 | Qt.ItemDataRole.ToolTipRole
T_NodeData = str | QIcon | Qt.AlignmentFlag | None
class ProjectNode:
@@ -125,7 +127,7 @@ class ProjectNode:
def childCount(self) -> int:
return len(self._children)
def data(self, column: int, role: Qt.ItemDataRole) -> str | QIcon | Qt.AlignmentFlag | None:
def data(self, column: int, role: Qt.ItemDataRole) -> T_NodeData:
""""""
return self._cache.get(COL_MASK*column | role)
@@ -168,7 +170,7 @@ class ProjectModel(QAbstractItemModel):
super().__init__(None)
logger.debug("Create: ProjectModel")
self._tree = tree
self._root = ProjectNode(NWItem(tree._project, ""))
self._root = ProjectNode(NWItem(tree._project, "invisibleRoot"))
return
def __del__(self) -> None:
@@ -177,6 +179,7 @@ class ProjectModel(QAbstractItemModel):
@property
def root(self) -> ProjectNode:
"""Return the model root item."""
return self._root
##
@@ -184,22 +187,26 @@ class ProjectModel(QAbstractItemModel):
##
def rowCount(self, index: QModelIndex) -> int:
"""Return the number of rows for an entry."""
if index.isValid():
return index.internalPointer().childCount()
return self._root.childCount()
def columnCount(self, index: QModelIndex) -> int:
"""Return the number of columns for an entry."""
return 4
def parent(self, index: QModelIndex) -> QModelIndex:
"""Get the parent model index of another index."""
if index.isValid():
if parent := index.internalPointer().parent():
return self.createIndex(parent.row(), 0, parent)
return QModelIndex()
def index(self, row: int, column: int, parent: QModelIndex = QModelIndex()) -> QModelIndex:
"""get the index of a child item of a parent."""
if parent.isValid():
item = parent.internalPointer()
item: ProjectNode = parent.internalPointer()
else:
item = self._root
@@ -211,10 +218,11 @@ class ProjectModel(QAbstractItemModel):
return QModelIndex()
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> Any:
def data(self, index: QModelIndex, role: Qt.ItemDataRole) -> T_NodeData:
"""Return display data for a project node."""
if not index.isValid():
return None
node = index.internalPointer()
node: ProjectNode = index.internalPointer()
return node.data(index.column(), role)
# def addChild(self, node: ProjectNode, parent: QModelIndex) -> None:
@@ -230,6 +238,7 @@ class ProjectModel(QAbstractItemModel):
##
def node(self, index: QModelIndex) -> ProjectNode | None:
"""Return the node for a given model index."""
if index.isValid():
return index.internalPointer()
return None
+15 -7
View File
@@ -225,13 +225,21 @@ class NWTree:
return
def refreshNode(self, tHandle: str) -> None:
"""Refresh node data on item change."""
if node := self._nodes.get(tHandle):
node.refresh()
index = self._model.indexFromNode(node)
SHARED.projectSignalProxy({"event": "projectItem", "handle": tHandle})
self._model.dataChanged.emit(index, index)
def refreshItems(self, items: list[str], isRange: bool = False) -> None:
"""Refresh these items on the GUI. If they are an ordered range,
also set the isRange flag to True.
"""
indices = []
for tHandle in items:
if node := self._nodes.get(tHandle):
node.refresh()
SHARED.projectSignalProxy({"event": "projectItem", "handle": tHandle})
indices.append(self._model.indexFromNode(node))
if isRange and len(indices) >= 2:
self._model.dataChanged.emit(indices[0], indices[-1])
else:
for index in indices:
self._model.dataChanged.emit(index, index)
return
def _buildTree(self, items: dict[str, NWItem]) -> dict[str, NWItem]:
+1
View File
@@ -198,6 +198,7 @@ class GuiProjectView(QWidget):
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=name or nwItem.itemName)
if dlgOk:
nwItem.setName(newLabel)
nwItem.notifyToRefresh()
return
@pyqtSlot(str, bool)
-5
View File
@@ -176,11 +176,6 @@ def testCoreItem_Setters(mockGUI, mockRnd, fncPath):
item.setCursorPos(1)
assert item.cursorPos == 1
# Initial Count
item.setWordCount(234)
item.saveInitialCount()
assert item.initCount == 234
@pytest.mark.core
def testCoreItem_Methods(mockGUI, mockRnd, fncPath):