Fix some minor issues (#1632)

This commit is contained in:
Veronica Berglyd Olsen
2023-11-29 21:59:36 +01:00
committed by GitHub
4 changed files with 74 additions and 59 deletions
+9 -4
View File
@@ -2012,20 +2012,25 @@ class GuiDocEditor(QPlainTextEdit):
cPos = cursor.position() cPos = cursor.position()
bPos = cursor.block().position() bPos = cursor.block().position()
bLen = cursor.block().length() bLen = cursor.block().length()
apos = nwUnicode.U_APOS + nwUnicode.U_RSQUO
# Scan backwards # Scan backward
sPos = cPos sPos = cPos
for i in range(cPos - bPos): for i in range(cPos - bPos):
sPos = cPos - i - 1 sPos = cPos - i - 1
if not self._qDocument.characterAt(sPos).isalnum(): cOne = self._qDocument.characterAt(sPos)
cTwo = self._qDocument.characterAt(sPos - 1)
if not (cOne.isalnum() or cOne in apos and cTwo.isalnum()):
sPos += 1 sPos += 1
break break
# Scan forwards # Scan forward
ePos = cPos ePos = cPos
for i in range(bPos + bLen - cPos): for i in range(bPos + bLen - cPos):
ePos = cPos + i ePos = cPos + i
if not self._qDocument.characterAt(ePos).isalnum(): cOne = self._qDocument.characterAt(ePos)
cTwo = self._qDocument.characterAt(ePos + 1)
if not (cOne.isalnum() or cOne in apos and cTwo.isalnum()):
break break
if ePos - sPos <= 0: if ePos - sPos <= 0:
+42 -52
View File
@@ -206,18 +206,18 @@ class GuiNovelToolBar(QWidget):
# Novel Selector # Novel Selector
selFont = self.font() selFont = self.font()
selFont.setWeight(QFont.Bold) selFont.setWeight(QFont.Weight.Bold)
self.novelPrefix = self.tr("Outline of {0}") self.novelPrefix = self.tr("Outline of {0}")
self.novelValue = NovelSelector(self) self.novelValue = NovelSelector(self)
self.novelValue.setFont(selFont) self.novelValue.setFont(selFont)
self.novelValue.setMinimumWidth(CONFIG.pxInt(150)) self.novelValue.setMinimumWidth(CONFIG.pxInt(150))
self.novelValue.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.novelValue.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot) self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
self.tbNovel = QToolButton(self) self.tbNovel = QToolButton(self)
self.tbNovel.setToolTip(self.tr("Novel Root")) self.tbNovel.setToolTip(self.tr("Novel Root"))
self.tbNovel.setIconSize(QSize(iPx, iPx)) self.tbNovel.setIconSize(QSize(iPx, iPx))
self.tbNovel.clicked.connect(self._openNovelSelector) self.tbNovel.clicked.connect(self.novelValue.showPopup)
# Refresh Button # Refresh Button
self.tbRefresh = QToolButton(self) self.tbRefresh = QToolButton(self)
@@ -244,7 +244,7 @@ class GuiNovelToolBar(QWidget):
self.tbMore.setToolTip(self.tr("More Options")) self.tbMore.setToolTip(self.tr("More Options"))
self.tbMore.setIconSize(QSize(iPx, iPx)) self.tbMore.setIconSize(QSize(iPx, iPx))
self.tbMore.setMenu(self.mMore) self.tbMore.setMenu(self.mMore)
self.tbMore.setPopupMode(QToolButton.InstantPopup) self.tbMore.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
# Assemble # Assemble
self.outerBox = QHBoxLayout() self.outerBox = QHBoxLayout()
@@ -275,7 +275,7 @@ class GuiNovelToolBar(QWidget):
self.tbMore.setIcon(SHARED.theme.getIcon("menu")) self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
qPalette = self.palette() qPalette = self.palette()
qPalette.setBrush(QPalette.Window, qPalette.base()) qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
self.setPalette(qPalette) self.setPalette(qPalette)
# StyleSheets # StyleSheets
@@ -327,12 +327,6 @@ class GuiNovelToolBar(QWidget):
# Private Slots # Private Slots
## ##
@pyqtSlot()
def _openNovelSelector(self) -> None:
"""Trigger the dropdown list of the novel selector."""
self.novelValue.showPopup()
return
@pyqtSlot() @pyqtSlot()
def _refreshNovelTree(self) -> None: def _refreshNovelTree(self) -> None:
"""Rebuild the current tree.""" """Rebuild the current tree."""
@@ -408,14 +402,14 @@ class GuiNovelTree(QTreeWidget):
cMg = CONFIG.pxInt(6) cMg = CONFIG.pxInt(6)
self.setIconSize(QSize(iPx, iPx)) self.setIconSize(QSize(iPx, iPx))
self.setFrameStyle(QFrame.NoFrame) self.setFrameStyle(QFrame.Shape.NoFrame)
self.setUniformRowHeights(True) self.setUniformRowHeights(True)
self.setAllColumnsShowFocus(True) self.setAllColumnsShowFocus(True)
self.setHeaderHidden(True) self.setHeaderHidden(True)
self.setIndentation(0) self.setIndentation(0)
self.setColumnCount(4) self.setColumnCount(4)
self.setSelectionBehavior(QAbstractItemView.SelectRows) self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
self.setSelectionMode(QAbstractItemView.SingleSelection) self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
self.setExpandsOnDoubleClick(False) self.setExpandsOnDoubleClick(False)
self.setDragEnabled(False) self.setDragEnabled(False)
@@ -423,10 +417,10 @@ class GuiNovelTree(QTreeWidget):
treeHeader = self.header() treeHeader = self.header()
treeHeader.setStretchLastSection(False) treeHeader.setStretchLastSection(False)
treeHeader.setMinimumSectionSize(iPx + cMg) treeHeader.setMinimumSectionSize(iPx + cMg)
treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.Stretch) treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.ResizeMode.Stretch)
treeHeader.setSectionResizeMode(self.C_WORDS, QHeaderView.ResizeToContents) treeHeader.setSectionResizeMode(self.C_WORDS, QHeaderView.ResizeMode.ResizeToContents)
treeHeader.setSectionResizeMode(self.C_EXTRA, QHeaderView.ResizeToContents) treeHeader.setSectionResizeMode(self.C_EXTRA, QHeaderView.ResizeMode.ResizeToContents)
treeHeader.setSectionResizeMode(self.C_MORE, QHeaderView.ResizeToContents) treeHeader.setSectionResizeMode(self.C_MORE, QHeaderView.ResizeMode.ResizeToContents)
# Pre-Generate Tree Formatting # Pre-Generate Tree Formatting
fH1 = self.font() fH1 = self.font()
@@ -455,14 +449,14 @@ class GuiNovelTree(QTreeWidget):
"""Set or update tree widget settings.""" """Set or update tree widget settings."""
# Scroll bars # Scroll bars
if CONFIG.hideVScroll: if CONFIG.hideVScroll:
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
else: else:
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
if CONFIG.hideHScroll: if CONFIG.hideHScroll:
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
else: else:
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
return return
@@ -522,21 +516,16 @@ class GuiNovelTree(QTreeWidget):
def refreshHandle(self, tHandle: str) -> None: def refreshHandle(self, tHandle: str) -> None:
"""Refresh the data for a given handle.""" """Refresh the data for a given handle."""
idxData = SHARED.project.index.getItemData(tHandle) if idxData := SHARED.project.index.getItemData(tHandle):
if idxData is None: logger.debug("Refreshing meta data for item '%s'", tHandle)
return for sTitle, tHeading in idxData.items():
sKey = f"{tHandle}:{sTitle}"
logger.debug("Refreshing meta data for item '%s'", tHandle) if trItem := self._treeMap.get(sKey, None):
for sTitle, tHeading in idxData.items(): self._updateTreeItemValues(trItem, tHeading, tHandle, sTitle)
sKey = f"{tHandle}:{sTitle}" else:
trItem = self._treeMap.get(sKey, None) logger.debug("Heading '%s' not in novel tree", sKey)
if trItem is None: self.refreshTree()
logger.debug("Heading '%s' not in novel tree", sKey) return
self.refreshTree()
return
self._updateTreeItemValues(trItem, tHeading, tHandle, sTitle)
return return
def getSelectedHandle(self) -> tuple[str | None, str | None]: def getSelectedHandle(self) -> tuple[str | None, str | None]:
@@ -567,27 +556,25 @@ class GuiNovelTree(QTreeWidget):
self._lastColSize = minmax(colSize, 15, 75)/100.0 self._lastColSize = minmax(colSize, 15, 75)/100.0
return return
def setActiveHandle(self, tHandle: str | None) -> None: def setActiveHandle(self, tHandle: str | None, doScroll: bool = False) -> None:
"""Highlight the rows associated with a given handle.""" """Highlight the rows associated with a given handle."""
tStart = time() didScroll = False
self._actHandle = tHandle self._actHandle = tHandle
for i in range(self.topLevelItemCount()): for i in range(self.topLevelItemCount()):
tItem = self.topLevelItem(i) if tItem := self.topLevelItem(i):
if tItem is not None:
if tItem.data(self.C_DATA, self.D_HANDLE) == tHandle: if tItem.data(self.C_DATA, self.D_HANDLE) == tHandle:
tItem.setBackground(self.C_TITLE, self.palette().alternateBase()) tItem.setBackground(self.C_TITLE, self.palette().alternateBase())
tItem.setBackground(self.C_WORDS, self.palette().alternateBase()) tItem.setBackground(self.C_WORDS, self.palette().alternateBase())
tItem.setBackground(self.C_EXTRA, self.palette().alternateBase()) tItem.setBackground(self.C_EXTRA, self.palette().alternateBase())
tItem.setBackground(self.C_MORE, self.palette().alternateBase()) tItem.setBackground(self.C_MORE, self.palette().alternateBase())
if doScroll and not didScroll:
self.scrollToItem(tItem, QAbstractItemView.ScrollHint.PositionAtCenter)
didScroll = True
else: else:
tItem.setBackground(self.C_TITLE, self.palette().base()) tItem.setBackground(self.C_TITLE, self.palette().base())
tItem.setBackground(self.C_WORDS, self.palette().base()) tItem.setBackground(self.C_WORDS, self.palette().base())
tItem.setBackground(self.C_EXTRA, self.palette().base()) tItem.setBackground(self.C_EXTRA, self.palette().base())
tItem.setBackground(self.C_MORE, self.palette().base()) tItem.setBackground(self.C_MORE, self.palette().base())
logger.debug("Highlighted Novel Tree in %.3f ms", (time() - tStart)*1000)
return return
## ##
@@ -601,12 +588,12 @@ class GuiNovelTree(QTreeWidget):
""" """
super().mousePressEvent(event) super().mousePressEvent(event)
if event.button() == Qt.LeftButton: if event.button() == Qt.MouseButton.LeftButton:
selItem = self.indexAt(event.pos()) selItem = self.indexAt(event.pos())
if not selItem.isValid(): if not selItem.isValid():
self.clearSelection() self.clearSelection()
elif event.button() == Qt.MiddleButton: elif event.button() == Qt.MouseButton.MiddleButton:
selItem = self.itemAt(event.pos()) selItem = self.itemAt(event.pos())
if not isinstance(selItem, QTreeWidgetItem): if not isinstance(selItem, QTreeWidgetItem):
return return
@@ -637,7 +624,10 @@ class GuiNovelTree(QTreeWidget):
trItem = self.topLevelItem(i) trItem = self.topLevelItem(i)
if isinstance(trItem, QTreeWidgetItem): if isinstance(trItem, QTreeWidgetItem):
lastText = trItem.data(self.C_DATA, self.D_EXTRA) lastText = trItem.data(self.C_DATA, self.D_EXTRA)
trItem.setText(self.C_EXTRA, fMetric.elidedText(lastText, Qt.ElideRight, eliW)) trItem.setText(
self.C_EXTRA,
fMetric.elidedText(lastText, Qt.TextElideMode.ElideRight, eliW)
)
return return
## ##
@@ -693,7 +683,7 @@ class GuiNovelTree(QTreeWidget):
newItem.setData(self.C_DATA, self.D_HANDLE, tHandle) newItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
newItem.setData(self.C_DATA, self.D_TITLE, sTitle) newItem.setData(self.C_DATA, self.D_TITLE, sTitle)
newItem.setData(self.C_DATA, self.D_KEY, tKey) newItem.setData(self.C_DATA, self.D_KEY, tKey)
newItem.setTextAlignment(self.C_WORDS, Qt.AlignRight) newItem.setTextAlignment(self.C_WORDS, Qt.AlignmentFlag.AlignRight)
self._updateTreeItemValues(newItem, novIdx, tHandle, sTitle) self._updateTreeItemValues(newItem, novIdx, tHandle, sTitle)
self._treeMap[tKey] = newItem self._treeMap[tKey] = newItem
@@ -712,16 +702,16 @@ class GuiNovelTree(QTreeWidget):
iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0) iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
hDec = SHARED.theme.getHeaderDecoration(iLevel) hDec = SHARED.theme.getHeaderDecoration(iLevel)
trItem.setData(self.C_TITLE, Qt.DecorationRole, hDec) trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
trItem.setText(self.C_TITLE, idxItem.title) trItem.setText(self.C_TITLE, idxItem.title)
trItem.setFont(self.C_TITLE, self._hFonts[iLevel]) trItem.setFont(self.C_TITLE, self._hFonts[iLevel])
trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}") trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}")
trItem.setData(self.C_MORE, Qt.DecorationRole, self._pMore) trItem.setData(self.C_MORE, Qt.ItemDataRole.DecorationRole, self._pMore)
# Custom column # Custom column
mW = int(self._lastColSize * self.viewport().width()) mW = int(self._lastColSize * self.viewport().width())
lastText, toolTip = self._getLastColumnText(tHandle, sTitle) lastText, toolTip = self._getLastColumnText(tHandle, sTitle)
elideText = self.fontMetrics().elidedText(lastText, Qt.ElideRight, mW) elideText = self.fontMetrics().elidedText(lastText, Qt.TextElideMode.ElideRight, mW)
trItem.setText(self.C_EXTRA, elideText) trItem.setText(self.C_EXTRA, elideText)
trItem.setData(self.C_DATA, self.D_EXTRA, lastText) trItem.setData(self.C_DATA, self.D_EXTRA, lastText)
trItem.setToolTip(self.C_EXTRA, toolTip) trItem.setToolTip(self.C_EXTRA, toolTip)
+1 -1
View File
@@ -606,7 +606,7 @@ class GuiMain(QMainWindow):
if self.docEditor.loadText(tHandle, tLine): if self.docEditor.loadText(tHandle, tLine):
SHARED.project.data.setLastHandle(tHandle, "editor") SHARED.project.data.setLastHandle(tHandle, "editor")
self.projView.setSelectedHandle(tHandle, doScroll=doScroll) self.projView.setSelectedHandle(tHandle, doScroll=doScroll)
self.novelView.setActiveHandle(tHandle) self.novelView.setActiveHandle(tHandle, doScroll=doScroll)
if changeFocus: if changeFocus:
self.docEditor.setFocus() self.docEditor.setFocus()
else: else:
+22 -2
View File
@@ -27,12 +27,12 @@ from pathlib import Path
from tools import C, buildTestProject from tools import C, buildTestProject
from PyQt5.QtGui import QFocusEvent from PyQt5.QtGui import QFocusEvent
from PyQt5.QtCore import Qt, QEvent from PyQt5.QtCore import QPoint, Qt, QEvent
from PyQt5.QtWidgets import QInputDialog, QToolTip from PyQt5.QtWidgets import QInputDialog, QToolTip
from novelwriter import CONFIG, SHARED from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwWidget, nwItemType from novelwriter.enum import nwWidget, nwItemType
from novelwriter.gui.noveltree import NovelTreeColumn from novelwriter.gui.noveltree import GuiNovelTree, NovelTreeColumn
from novelwriter.dialogs.editlabel import GuiEditLabel from novelwriter.dialogs.editlabel import GuiEditLabel
@@ -192,12 +192,32 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
mIndex = novelTree.model().index(2, novelTree.C_MORE) 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 = ""
novelTree._treeItemClicked(mIndex) novelTree._treeItemClicked(mIndex)
assert ttText == ( assert ttText == (
"<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 = ""
novelTree._popMetaBox(QPoint(1, 1), C.hInvalid, "T0001")
assert ttText == ""
# Set Default Root
# ================
SHARED.project.data.setLastHandle(C.hInvalid, "novelTree")
novelView.openProjectTasks()
assert novelBar.novelValue.handle == C.hNovelRoot
# Tree Focus
# ==========
with monkeypatch.context() as mp:
mp.setattr(GuiNovelTree, "hasFocus", lambda *a: False)
assert novelView.treeHasFocus() is False
mp.setattr(GuiNovelTree, "hasFocus", lambda *a: True)
assert novelView.treeHasFocus() is True
# Other Checks # Other Checks
# ============ # ============