From 4da120633e394071621ba5cfb49c06ac228e453a Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 23 Feb 2025 22:34:53 +0100 Subject: [PATCH] Save handle and title key with other data in novel model --- novelwriter/core/novelmodel.py | 44 +++++++++++++++++++----------- novelwriter/extensions/modified.py | 7 +++-- novelwriter/gui/noveltree.py | 22 ++++++++------- 3 files changed, 45 insertions(+), 28 deletions(-) diff --git a/novelwriter/core/novelmodel.py b/novelwriter/core/novelmodel.py index 32f1c518..8d5a644f 100644 --- a/novelwriter/core/novelmodel.py +++ b/novelwriter/core/novelmodel.py @@ -37,21 +37,22 @@ logger = logging.getLogger(__name__) C_FACTOR = 0x0100 -R_TEXT = Qt.ItemDataRole.DisplayRole -R_ICON = Qt.ItemDataRole.DecorationRole -R_ALIGN = Qt.ItemDataRole.TextAlignmentRole -R_TIP = Qt.ItemDataRole.ToolTipRole +R_TEXT = Qt.ItemDataRole.DisplayRole +R_ICON = Qt.ItemDataRole.DecorationRole +R_ALIGN = Qt.ItemDataRole.TextAlignmentRole +R_TIP = Qt.ItemDataRole.ToolTipRole +R_HANDLE = 0xff01 +R_KEY = 0xff02 -T_NodeData = str | QIcon | QPixmap | Qt.AlignmentFlag | None +T_NodeData = str | tuple[str, str] | QIcon | QPixmap | Qt.AlignmentFlag | None class NovelModel(QAbstractTableModel): - __slots__ = ("_meta", "_rows", "_more", "_columns") + __slots__ = ("_rows", "_more", "_columns") def __init__(self) -> None: super().__init__() - self._meta: list[tuple[str, str]] = [] self._rows: list[dict[int, T_NodeData]] = [] self._more = SHARED.theme.getIcon("more_arrow") self._columns = 3 @@ -90,11 +91,21 @@ class NovelModel(QAbstractTableModel): print("NovelModel Debug: Oops!") return None - def keys(self, index: QModelIndex) -> tuple[str | None, str | None]: - """Return display data for a node.""" - if index.isValid() and (row := index.row()) < len(self._rows): - return self._meta[row] - return None, None + def handle(self, index: QModelIndex) -> str | None: + """Return item handle for the row.""" + try: + return self._rows[index.row()].get(R_HANDLE) # type: ignore + except Exception: + print("NovelModel Debug: Oops!") + return None + + def key(self, index: QModelIndex) -> str | None: + """Return item handle for the row.""" + try: + return self._rows[index.row()].get(R_KEY) # type: ignore + except Exception: + print("NovelModel Debug: Oops!") + return None ## # Data Methods @@ -113,11 +124,12 @@ class NovelModel(QAbstractTableModel): iLevel = nwStyles.H_LEVEL.get(head.level, 0) more = self._columns - 1 data = {} - data[C_FACTOR*0 | R_TEXT] = head.title - data[C_FACTOR*0 | R_ICON] = SHARED.theme.getHeaderDecoration(iLevel) - data[C_FACTOR*1 | R_TEXT] = f"{head.mainCount:n}" + data[C_FACTOR*0 | R_TEXT] = head.title + data[C_FACTOR*0 | R_ICON] = SHARED.theme.getHeaderDecoration(iLevel) + data[C_FACTOR*1 | R_TEXT] = f"{head.mainCount:n}" data[C_FACTOR*1 | R_ALIGN] = QtAlignRight data[C_FACTOR*more | R_ICON] = self._more - self._meta.append((handle, key)) + data[R_HANDLE] = handle + data[R_KEY] = key self._rows.append(data) return diff --git a/novelwriter/extensions/modified.py b/novelwriter/extensions/modified.py index ea0dc103..8d20912a 100644 --- a/novelwriter/extensions/modified.py +++ b/novelwriter/extensions/modified.py @@ -105,8 +105,11 @@ class NTreeView(QTreeView): def mousePressEvent(self, event: QMouseEvent | None) -> None: """Emit a signal on mouse middle click.""" - if event and event.button() == QtMouseMiddle: - self.middleClicked.emit(self.indexAt(event.pos())) + if ( + event and event.button() == QtMouseMiddle + and (index := self.indexAt(event.pos())).isValid() + ): + self.middleClicked.emit(index) return super().mousePressEvent(event) diff --git a/novelwriter/gui/noveltree.py b/novelwriter/gui/noveltree.py index c3f8a5fe..c6a53ad6 100644 --- a/novelwriter/gui/noveltree.py +++ b/novelwriter/gui/noveltree.py @@ -418,7 +418,8 @@ class GuiNovelTree(NTreeView): items are selected, return the first. """ if model := self._getModel(): - return model.keys(self.currentIndex()) + index = self.currentIndex() + return model.handle(index), model.key(index) return None, None ## @@ -452,7 +453,7 @@ class GuiNovelTree(NTreeView): def drawRow(self, painter: QPainter, opt: QStyleOptionViewItem, index: QModelIndex) -> None: """Draw a box on the active row.""" - if (model := self._getModel()) and model.keys(index)[0] == self._actHandle: + if (model := self._getModel()) and model.handle(index) == self._actHandle: painter.fillRect(opt.rect, self.palette().alternateBase()) super().drawRow(painter, opt, index) return @@ -465,8 +466,7 @@ class GuiNovelTree(NTreeView): def _onSingleClick(self, index: QModelIndex) -> None: """The user single-clicked an index.""" if index.isValid() and (model := self._getModel()): - keys = model.keys(index) - if (tHandle := keys[0]) and (sTitle := keys[1]): + if (tHandle := model.handle(index)) and (sTitle := model.key(index)): self.novelView.selectedItemChanged.emit(tHandle) if index.column() == model.columnCount(index) - 1: pos = self.mapToGlobal(self.visualRect(index).topRight()) @@ -477,20 +477,22 @@ class GuiNovelTree(NTreeView): def _onDoubleClick(self, index: QModelIndex) -> None: """The user double-clicked an index.""" if ( - (model := self._getModel()) and (keys := model.keys(index)) - and (tHandle := keys[0]) and (sTitle := keys[1]) + (model := self._getModel()) + and (tHandle := model.handle(index)) + and (sTitle := model.key(index)) ): - self.novelView.openDocumentRequest.emit(tHandle, nwDocMode.EDIT, sTitle or "", False) + self.novelView.openDocumentRequest.emit(tHandle, nwDocMode.EDIT, sTitle, False) return @pyqtSlot(QModelIndex) def _onMiddleClick(self, index: QModelIndex) -> None: """The user middle-clicked an index.""" if ( - (model := self._getModel()) and (keys := model.keys(index)) - and (tHandle := keys[0]) and (sTitle := keys[1]) + (model := self._getModel()) + and (tHandle := model.handle(index)) + and (sTitle := model.key(index)) ): - self.novelView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, sTitle or "", False) + self.novelView.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, sTitle, False) return ##