Apply open document shortcuts to the tree that has focus (#945)

* Better handling of Enter/Return on GUI trees, resolves #913
* Update test
* Generalise open selected handle functions
* Improve test coverage
* Update docstring
This commit is contained in:
Veronica Berglyd Olsen
2021-12-31 19:51:26 +01:00
committed by GitHub
parent 7024254960
commit b0f939af32
7 changed files with 188 additions and 74 deletions
+8 -10
View File
@@ -135,7 +135,7 @@ class GuiNovelTree(QTreeWidget):
logger.verbose("Requesting refresh of the novel tree")
treeChanged = self.theParent.treeView.changedSince(self._lastBuild)
indexChanged = self.theIndex.novelChangedSince(self._lastBuild)
if not (treeChanged or indexChanged):
if not (treeChanged or indexChanged or overRide):
logger.verbose("No changes have been made to the novel index")
return
@@ -175,10 +175,13 @@ class GuiNovelTree(QTreeWidget):
selected, return the first.
"""
selItem = self.selectedItems()
tHandle = None
tLine = 0
if selItem:
return selItem[0].data(self.C_TITLE, Qt.UserRole)[0]
tHandle = selItem[0].data(self.C_TITLE, Qt.UserRole)[0]
tLine = checkInt(selItem[0].data(self.C_TITLE, Qt.UserRole)[1], 1) - 1
return None
return tHandle, tLine
##
# Events
@@ -201,7 +204,7 @@ class GuiNovelTree(QTreeWidget):
if not isinstance(selItem, QTreeWidgetItem):
return
tHandle = self.getSelectedHandle()
tHandle, _ = self.getSelectedHandle()
if tHandle is None:
return
@@ -218,13 +221,8 @@ class GuiNovelTree(QTreeWidget):
clicked, and send it to the main gui class for opening in the
document editor.
"""
theData = tItem.data(self.C_TITLE, Qt.UserRole)
tHandle = theData[0]
tLine = checkInt(theData[1], 1)
logger.verbose("User selected entry with handle '%s' on line %s", tHandle, tLine)
tHandle, tLine = self.getSelectedHandle()
self.theParent.openDocument(tHandle, tLine=tLine-1, doScroll=True)
return
def _itemSelected(self):
+15 -8
View File
@@ -34,6 +34,7 @@ from PyQt5.QtWidgets import (
)
from novelwriter.enum import nwItemLayout, nwItemType, nwOutline
from novelwriter.common import checkInt
from novelwriter.constants import trConst, nwKeyWords, nwLabels
logger = logging.getLogger(__name__)
@@ -196,6 +197,19 @@ class GuiOutline(QTreeWidget):
self._firstView = True
return
def getSelectedHandle(self):
"""Get the currently selected handle. If multiple items are
selected, return the first.
"""
selItem = self.selectedItems()
tHandle = None
tLine = 0
if selItem:
tHandle = selItem[0].data(self._colIdx[nwOutline.TITLE], Qt.UserRole)
tLine = checkInt(selItem[0].text(self._colIdx[nwOutline.LINE]), 1) - 1
return tHandle, tLine
##
# Slots
##
@@ -206,15 +220,8 @@ class GuiOutline(QTreeWidget):
clicked, and send it to the main gui class for opening in the
document editor.
"""
tHandle = tItem.data(self._colIdx[nwOutline.TITLE], Qt.UserRole)
try:
tLine = int(tItem.text(self._colIdx[nwOutline.LINE]))
except Exception:
tLine = 1
logger.verbose("User selected entry with handle '%s' on line %s", tHandle, tLine)
tHandle, tLine = self.getSelectedHandle()
self.theParent.openDocument(tHandle, tLine=tLine-1, doScroll=True)
return
@pyqtSlot()
+48 -46
View File
@@ -262,9 +262,13 @@ class GuiMain(QMainWindow):
# Shortcuts and Actions
self._connectMenuActions()
keyReturn = QShortcut(self.treeView)
keyReturn = QShortcut(self)
keyReturn.setKey(QKeySequence(Qt.Key_Return))
keyReturn.activated.connect(self._treeKeyPressReturn)
keyReturn.activated.connect(self._keyPressReturn)
keyEnter = QShortcut(self)
keyEnter.setKey(QKeySequence(Qt.Key_Enter))
keyEnter.activated.connect(self._keyPressReturn)
keyEscape = QShortcut(self)
keyEscape.setKey(QKeySequence(Qt.Key_Escape))
@@ -350,7 +354,7 @@ class GuiMain(QMainWindow):
##
def newProject(self, projData=None):
"""Create new project via the new project wizard.
"""Create a new project via the new project wizard.
"""
if self.hasProject:
if not self.closeProject():
@@ -396,9 +400,9 @@ class GuiMain(QMainWindow):
return True
def closeProject(self, isYes=False):
"""Closes the project if one is open. isYes is passed on from
the close application event so the user doesn't get prompted
twice to confirm.
"""Close the project if one is open. isYes is passed on from the
close application event so the user doesn't get prompted twice
to confirm.
"""
if not self.hasProject:
# There is no project loaded, everything OK
@@ -598,6 +602,10 @@ class GuiMain(QMainWindow):
logger.error("No project open")
return False
if not self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
logger.debug("Requested item '%s' is not a document", tHandle)
return False
self.closeDocument()
self.mainTabs.setCurrentWidget(self.splitDocs)
if self.docEditor.loadText(tHandle, tLine):
@@ -798,22 +806,28 @@ class GuiMain(QMainWindow):
##
def openSelectedItem(self):
"""Open the selected documents.
"""Open the selected item from the tree that is currently
active. It is not checked that the item is actually a document.
That should be handled by the openDocument function.
"""
if not self.hasProject:
logger.error("No project open")
return False
tHandle = self.treeView.getSelectedHandle()
if tHandle is None:
tHandle = None
tLine = None
if self.treeView.hasFocus():
tHandle = self.treeView.getSelectedHandle()
elif self.novelView.hasFocus():
tHandle, tLine = self.novelView.getSelectedHandle()
elif self.projView.hasFocus():
tHandle, tLine = self.projView.getSelectedHandle()
else:
logger.warning("No item selected")
return False
logger.verbose("Opening item '%s'", tHandle)
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
self.openDocument(tHandle, doScroll=False)
else:
logger.verbose("Requested item '%s' is not a file", tHandle)
if tHandle is not None:
self.openDocument(tHandle, tLine=tLine, changeFocus=False, doScroll=False)
return True
@@ -986,7 +1000,7 @@ class GuiMain(QMainWindow):
"""
if not self.hasProject:
logger.error("No project open")
return
return False
dlgProj = GuiProjectSettings(self)
dlgProj.exec_()
@@ -996,14 +1010,14 @@ class GuiMain(QMainWindow):
self.docEditor.setDictionaries()
self._updateWindowTitle(self.theProject.projName)
return
return True
def showProjectDetailsDialog(self):
"""Open the project details dialog.
"""
if not self.hasProject:
logger.error("No project open")
return
return False
self.treeView.flushTreeOrder()
@@ -1016,14 +1030,14 @@ class GuiMain(QMainWindow):
dlgDetails.raise_()
dlgDetails.updateValues()
return
return True
def showBuildProjectDialog(self):
"""Open the build project dialog.
"""
if not self.hasProject:
logger.error("No project open")
return
return False
dlgBuild = getGuiItem("GuiBuildNovel")
if dlgBuild is None:
@@ -1035,14 +1049,14 @@ class GuiMain(QMainWindow):
qApp.processEvents()
dlgBuild.viewCachedDoc()
return
return True
def showProjectWordListDialog(self):
"""Open the project word list dialog.
"""
if not self.hasProject:
logger.error("No project open")
return
return False
dlgWords = GuiWordList(self)
dlgWords.exec_()
@@ -1051,14 +1065,14 @@ class GuiMain(QMainWindow):
logger.debug("Reloading word list")
self.docEditor.setDictionaries()
return
return True
def showWritingStatsDialog(self):
"""Open the session stats dialog.
"""
if not self.hasProject:
logger.error("No project open")
return
return False
dlgStats = getGuiItem("GuiWritingStats")
if dlgStats is None:
@@ -1070,7 +1084,7 @@ class GuiMain(QMainWindow):
qApp.processEvents()
dlgStats.populateGUI()
return
return True
def showAboutNWDialog(self, showNotes=False):
"""Show the about dialog for novelWriter.
@@ -1555,9 +1569,9 @@ class GuiMain(QMainWindow):
"""Single click on a project tree item just updates the details
panel below the tree.
"""
sHandle = self.treeView.getSelectedHandle()
if sHandle is not None:
self.treeMeta.updateViewBox(sHandle)
tHandle = self.treeView.getSelectedHandle()
if tHandle is not None:
self.treeMeta.updateViewBox(tHandle)
return
@pyqtSlot("QTreeWidgetItem*", int)
@@ -1565,14 +1579,9 @@ class GuiMain(QMainWindow):
"""The user double-clicked an item in the tree. If it is a file,
we open it. Otherwise, we do nothing.
"""
tHandle = tItem.data(self.treeView.C_NAME, Qt.UserRole)
logger.verbose("User double clicked tree item with handle '%s'", tHandle)
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
tHandle = self.treeView.getSelectedHandle()
if tHandle is not None:
self.openDocument(tHandle, changeFocus=False, doScroll=False)
else:
logger.verbose("Requested item '%s' is a folder", tHandle)
return
@pyqtSlot()
@@ -1589,18 +1598,11 @@ class GuiMain(QMainWindow):
return
@pyqtSlot()
def _treeKeyPressReturn(self):
"""The user pressed return on an item in the tree. If it is a
file, we open it. Otherwise, we do nothing. Pressing return does
not change focus to the editor as double click does.
def _keyPressReturn(self):
"""Forward the return/enter keypress to the function that opens
the currently selected item.
"""
tHandle = self.treeView.getSelectedHandle()
logger.verbose("User pressed return on tree item with handle '%s'", tHandle)
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
self.openDocument(tHandle, changeFocus=False, doScroll=False)
else:
logger.verbose("Requested item '%s' is a folder", tHandle)
self.openSelectedItem()
return
@pyqtSlot()
@@ -1642,7 +1644,7 @@ class GuiMain(QMainWindow):
logger.verbose("Novel tree tab activated")
if self.hasProject:
self.novelView.refreshTree()
sHandle = self.novelView.getSelectedHandle()
sHandle, _ = self.novelView.getSelectedHandle()
self.treeMeta.updateViewBox(sHandle)