Handle actions in the project tree internally in the class

This commit is contained in:
Veronica Berglyd Olsen
2022-06-06 13:46:54 +02:00
parent 3ff5dfce33
commit 669eabc7e8
2 changed files with 99 additions and 82 deletions
+64 -34
View File
@@ -27,6 +27,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
import logging import logging
import novelwriter import novelwriter
from enum import Enum
from time import time from time import time
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
@@ -37,7 +38,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter.core import NWDoc from novelwriter.core import NWDoc
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.common import minmax from novelwriter.common import minmax
from novelwriter.dialogs.itemeditor import GuiItemEditor from novelwriter.dialogs.itemeditor import GuiItemEditor
@@ -51,11 +52,16 @@ class GuiProjectTree(QTreeWidget):
C_EXPORT = 2 C_EXPORT = 2
C_STATUS = 3 C_STATUS = 3
# Signals triggered when the meta data values of items change
treeItemChanged = pyqtSignal(str) treeItemChanged = pyqtSignal(str)
novelItemChanged = pyqtSignal(str) novelItemChanged = pyqtSignal(str)
rootFolderChanged = pyqtSignal(str) rootFolderChanged = pyqtSignal(str)
wordCountsChanged = pyqtSignal() wordCountsChanged = pyqtSignal()
# Signals for user interaction with the project tree
selectedItemChanged = pyqtSignal(str)
openDocumentRequest = pyqtSignal(str, Enum)
def __init__(self, theParent): def __init__(self, theParent):
QTreeWidget.__init__(self, theParent) QTreeWidget.__init__(self, theParent)
@@ -127,6 +133,10 @@ class GuiProjectTree(QTreeWidget):
# The last column should just auto-scale # The last column should just auto-scale
self.resizeColumnToContents(self.C_STATUS) self.resizeColumnToContents(self.C_STATUS)
# Connect signals
self.itemDoubleClicked.connect(self._treeDoubleClick)
self.itemSelectionChanged.connect(self._treeSelectionChange)
# Set custom settings # Set custom settings
self.initTree() self.initTree()
@@ -223,9 +233,9 @@ class GuiProjectTree(QTreeWidget):
if tHandle is None: # pragma: no cover if tHandle is None: # pragma: no cover
return True return True
# Add the new item to the tree # Add the new item to the tree and open the editor dialog
self.revealNewTreeItem(tHandle, nHandle) self.revealNewTreeItem(tHandle, nHandle)
self.theParent.editItem(tHandle) self.editTreeItem(tHandle)
# Handle new file creation # Handle new file creation
nwItem = self.theProject.tree[tHandle] nwItem = self.theProject.tree[tHandle]
@@ -249,10 +259,7 @@ class GuiProjectTree(QTreeWidget):
pIndex.scanText(tHandle, newText) pIndex.scanText(tHandle, newText)
# Get Word Counts # Get Word Counts
cC, wC, pC = pIndex.getCounts(tHandle) _, wC, _ = pIndex.getCounts(tHandle)
nwItem.setCharCount(cC)
nwItem.setWordCount(wC)
nwItem.setParaCount(pC)
self.propagateCount(tHandle, wC) self.propagateCount(tHandle, wC)
self.wordCountsChanged.emit() self.wordCountsChanged.emit()
@@ -280,8 +287,8 @@ class GuiProjectTree(QTreeWidget):
return True return True
def moveTreeItem(self, nStep): def moveTreeItem(self, nStep):
"""Move an item up or down in the tree, but only if the treeView """Move an item up or down in the tree, but only if the project
has focus. This also applies when the menu is used. tree has focus. This also applies when the menu is used.
""" """
if not self.theParent.hasProject: if not self.theParent.hasProject:
logger.error("No project open") logger.error("No project open")
@@ -321,13 +328,9 @@ class GuiProjectTree(QTreeWidget):
return True return True
def editTreeItem(self, tHandle=None): def editTreeItem(self, tHandle):
"""Open the edit item dialog. """Open the edit item dialog.
""" """
if tHandle is None:
logger.warning("No item selected")
return False
tItem = self.theProject.tree[tHandle] tItem = self.theProject.tree[tHandle]
if tItem is None: if tItem is None:
return False return False
@@ -357,8 +360,8 @@ class GuiProjectTree(QTreeWidget):
return True return True
def getTreeFromHandle(self, tHandle): def getTreeFromHandle(self, tHandle):
"""Recursively return all the children items starting from a """Recursively return all the child items starting from a given
given item handle. item handle.
""" """
theList = [] theList = []
theItem = self._getTreeItem(tHandle) theItem = self._getTreeItem(tHandle)
@@ -366,14 +369,6 @@ class GuiProjectTree(QTreeWidget):
theList = self._scanChildren(theList, theItem, 0) theList = self._scanChildren(theList, theItem, 0)
return theList return theList
def toggleExpanded(self, tHandle):
"""Expand an item based on its handle.
"""
trItem = self._getTreeItem(tHandle)
if trItem is not None:
trItem.setExpanded(not trItem.isExpanded())
return
def getColumnSizes(self): def getColumnSizes(self):
"""Return the column widths for the tree columns. """Return the column widths for the tree columns.
""" """
@@ -719,9 +714,52 @@ class GuiProjectTree(QTreeWidget):
return self._timeChanged > checkTime return self._timeChanged > checkTime
## ##
# Slots # Public Solts
## ##
@pyqtSlot(str, int, int, int)
def doUpdateCounts(self, tHandle, cCount, wCount, pCount):
"""Slot for updating the word count of a specific item.
"""
self.propagateCount(tHandle, wCount, countChildren=True)
self.wordCountsChanged.emit()
return
##
# Private Slots
##
@pyqtSlot()
def _treeSelectionChange(self):
"""The user changed which item is selected.
"""
tHandle = self.getSelectedHandle()
if tHandle is not None:
self.selectedItemChanged.emit(tHandle)
return
@pyqtSlot("QTreeWidgetItem*", int)
def _treeDoubleClick(self, tItem, colNo):
"""Capture a double-click event and either request the document
for editing if it is a file, or expand/close the node it is not.
"""
tHandle = self.getSelectedHandle()
if tHandle is None:
return
tItem = self.theProject.tree[tHandle]
if tItem is None:
return
if tItem.itemType == nwItemType.FILE:
self.openDocumentRequest.emit(tHandle, nwDocMode.EDIT)
else:
trItem = self._getTreeItem(tHandle)
if trItem is not None:
trItem.setExpanded(not trItem.isExpanded())
return
@pyqtSlot("QPoint") @pyqtSlot("QPoint")
def _rightClickMenu(self, clickPos): def _rightClickMenu(self, clickPos):
"""The user right clicked an element in the project tree, so we """The user right clicked an element in the project tree, so we
@@ -739,14 +777,6 @@ class GuiProjectTree(QTreeWidget):
return return
@pyqtSlot(str, int, int, int)
def doUpdateCounts(self, tHandle, cCount, wCount, pCount):
"""Slot for updating the word count of a specific item.
"""
self.propagateCount(tHandle, wCount, countChildren=True)
self.wordCountsChanged.emit()
return
## ##
# Events # Events
## ##
@@ -774,7 +804,7 @@ class GuiProjectTree(QTreeWidget):
return return
if tItem.itemType == nwItemType.FILE: if tItem.itemType == nwItemType.FILE:
self.theParent.viewDocument(tHandle) self.openDocumentRequest.emit(tHandle, nwDocMode.VIEW)
return return
+35 -48
View File
@@ -115,28 +115,6 @@ class GuiMain(QMainWindow):
self.mainMenu = GuiMainMenu(self) self.mainMenu = GuiMainMenu(self)
self.viewsBar = GuiViewsBar(self) self.viewsBar = GuiViewsBar(self)
# Connect Signals Between Main Elements
self.viewsBar.viewChangeRequested.connect(self._changeView)
self.treeView.itemSelectionChanged.connect(self._treeSingleClick)
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
self.treeView.treeItemChanged.connect(self.docEditor.updateDocInfo)
self.treeView.treeItemChanged.connect(self.docViewer.updateDocInfo)
self.treeView.treeItemChanged.connect(self.treeMeta.updateViewBox)
self.treeView.rootFolderChanged.connect(self.projView.updateRootItem)
self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage)
self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus)
self.docEditor.docCountsChanged.connect(self.treeMeta.doUpdateCounts)
self.docEditor.docCountsChanged.connect(self.treeView.doUpdateCounts)
self.docEditor.loadDocumentTagRequest.connect(self._followTag)
self.docViewer.loadDocumentTagRequest.connect(self._followTag)
self.projView.loadDocumentTagRequest.connect(self._followTag)
# Project Tree Stack # Project Tree Stack
self.projStack = QStackedWidget() self.projStack = QStackedWidget()
self.projStack.addWidget(self.treeView) self.projStack.addWidget(self.treeView)
@@ -214,6 +192,30 @@ class GuiMain(QMainWindow):
self.setStatusBar(self.statusBar) self.setStatusBar(self.statusBar)
self.addToolBar(Qt.LeftToolBarArea, self.viewsBar) self.addToolBar(Qt.LeftToolBarArea, self.viewsBar)
# Connect Signals
# ===============
self.viewsBar.viewChangeRequested.connect(self._changeView)
self.treeView.selectedItemChanged.connect(self.treeMeta.updateViewBox)
self.treeView.openDocumentRequest.connect(self._openDocument)
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
self.treeView.treeItemChanged.connect(self.docEditor.updateDocInfo)
self.treeView.treeItemChanged.connect(self.docViewer.updateDocInfo)
self.treeView.treeItemChanged.connect(self.treeMeta.updateViewBox)
self.treeView.rootFolderChanged.connect(self.projView.updateRootItem)
self.docEditor.spellDictionaryChanged.connect(self.statusBar.setLanguage)
self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus)
self.docEditor.docCountsChanged.connect(self.treeMeta.doUpdateCounts)
self.docEditor.docCountsChanged.connect(self.treeView.doUpdateCounts)
self.docEditor.loadDocumentTagRequest.connect(self._followTag)
self.docViewer.loadDocumentTagRequest.connect(self._followTag)
self.projView.loadDocumentTagRequest.connect(self._followTag)
# Finalise Initialisation # Finalise Initialisation
# ======================= # =======================
@@ -1468,6 +1470,17 @@ class GuiMain(QMainWindow):
self.viewDocument(tHandle=tHandle, tAnchor=f"#{sTitle}") self.viewDocument(tHandle=tHandle, tAnchor=f"#{sTitle}")
return return
@pyqtSlot(str, Enum)
def _openDocument(self, tHandle, tMode):
"""Handle an open document request.
"""
if tHandle is not None:
if tMode == nwDocMode.EDIT:
self.openDocument(tHandle, changeFocus=False)
elif tMode == nwDocMode.VIEW:
self.viewDocument(tHandle=tHandle)
return
@pyqtSlot(nwView) @pyqtSlot(nwView)
def _changeView(self, view): def _changeView(self, view):
"""Handle the requested change of view from the GuiViewBar. """Handle the requested change of view from the GuiViewBar.
@@ -1531,32 +1544,6 @@ class GuiMain(QMainWindow):
return return
@pyqtSlot()
def _treeSingleClick(self):
"""Single click on a project tree item just updates the details
panel below the tree.
"""
tHandle = self.treeView.getSelectedHandle()
if tHandle is not None:
self.treeMeta.updateViewBox(tHandle)
return
@pyqtSlot("QTreeWidgetItem*", int)
def _treeDoubleClick(self, tItem, colNo):
"""The user double-clicked an item in the tree. If it is a file,
we open it. Otherwise, we toggle the expanded status.
"""
tHandle = self.treeView.getSelectedHandle()
if tHandle is not None:
tItem = self.theProject.tree[tHandle]
if tItem is None:
return
if tItem.itemType == nwItemType.FILE:
self.openDocument(tHandle, changeFocus=False, doScroll=False)
else:
self.treeView.toggleExpanded(tHandle)
return
@pyqtSlot() @pyqtSlot()
def _treeNovelItemChanged(self): def _treeNovelItemChanged(self):
"""Triggered when there is a change to a novel item in the """Triggered when there is a change to a novel item in the