Streamline how project item changes are reported

This commit is contained in:
Veronica Berglyd Olsen
2022-06-05 17:25:39 +02:00
parent 2873336dce
commit 88976d6800
9 changed files with 122 additions and 123 deletions
+16 -11
View File
@@ -569,16 +569,6 @@ class GuiDocEditor(QTextEdit):
return return
def updateDocInfo(self, tHandle):
"""Called when an item label is changed to check if the document
title bar needs updating,
"""
if tHandle == self._docHandle:
self.docHeader.setTitleFromHandle(self._docHandle)
self.docFooter.updateInfo()
self.updateDocMargins()
return
## ##
# Properties # Properties
## ##
@@ -1068,7 +1058,22 @@ class GuiDocEditor(QTextEdit):
return return
## ##
# Slots # Public Slots
##
@pyqtSlot(str)
def updateDocInfo(self, tHandle):
"""Called when an item label is changed to check if the document
title bar needs updating,
"""
if tHandle == self._docHandle:
self.docHeader.setTitleFromHandle(self._docHandle)
self.docFooter.updateInfo()
self.updateDocMargins()
return
##
# Private Slots
## ##
@pyqtSlot(int, int, int) @pyqtSlot(int, int, int)
+15 -10
View File
@@ -322,15 +322,6 @@ class GuiDocViewer(QTextBrowser):
return return
def updateDocInfo(self, tHandle):
"""Called when an item label is changed to check if the document
title bar needs updating,
"""
if tHandle == self._docHandle:
self.docHeader.setTitleFromHandle(self._docHandle)
self.updateDocMargins()
return
## ##
# Properties # Properties
## ##
@@ -389,7 +380,21 @@ class GuiDocViewer(QTextBrowser):
return 0 return 0
## ##
# Slots # Public Slots
##
@pyqtSlot(str)
def updateDocInfo(self, tHandle):
"""Called when an item label is changed to check if the document
title bar needs updating,
"""
if tHandle == self._docHandle:
self.docHeader.setTitleFromHandle(self._docHandle)
self.updateDocMargins()
return
##
# Private Slots
## ##
@pyqtSlot("QUrl") @pyqtSlot("QUrl")
+5 -4
View File
@@ -220,6 +220,11 @@ class GuiItemDetails(QWidget):
""" """
self.updateViewBox(self._itemHandle) self.updateViewBox(self._itemHandle)
##
# Public Slots
##
@pyqtSlot(str)
def updateViewBox(self, tHandle): def updateViewBox(self, tHandle):
"""Populate the details box from a given handle. """Populate the details box from a given handle.
""" """
@@ -290,10 +295,6 @@ class GuiItemDetails(QWidget):
return return
##
# Slots
##
@pyqtSlot(str, int, int, int) @pyqtSlot(str, int, int, int)
def doUpdateCounts(self, tHandle, cC, wC, pC): def doUpdateCounts(self, tHandle, cC, wC, pC):
"""Update the counts if the handle is the same as the one we're """Update the counts if the handle is the same as the one we're
-1
View File
@@ -146,7 +146,6 @@ class GuiNovelTree(QTreeWidget):
if selItem: if selItem:
titleKey = selItem[0].data(self.C_TITLE, Qt.UserRole)[2] titleKey = selItem[0].data(self.C_TITLE, Qt.UserRole)[2]
self.theParent.treeView.flushTreeOrder()
self._populateTree() self._populateTree()
if titleKey is not None and titleKey in self._treeMap: if titleKey is not None and titleKey in self._treeMap:
+8 -4
View File
@@ -126,17 +126,21 @@ class GuiOutline(QWidget):
return self.outlineView.setFocus() return self.outlineView.setFocus()
## ##
# Slots # Public Slots
## ##
@pyqtSlot() @pyqtSlot(str)
def projectUpdated(self): def updateRootItem(self, tHandle):
"""Should be called whenever the number of root folders change. """Should be called whenever a root folders changes.
""" """
self.outlineBar.populateNovelList() self.outlineBar.populateNovelList()
self.outlineData.updateClasses() self.outlineData.updateClasses()
return return
##
# Private Slots
##
@pyqtSlot() @pyqtSlot()
def _updateMenuColumns(self): def _updateMenuColumns(self):
"""Trigger an update of the toggled state of the column menu """Trigger an update of the toggled state of the column menu
+67 -57
View File
@@ -32,11 +32,13 @@ from time import time
from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot from PyQt5.QtCore import Qt, QSize, pyqtSignal, pyqtSlot
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import ( from PyQt5.QtWidgets import (
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction, QFrame QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction, QFrame,
QDialog
) )
from novelwriter.core import NWDoc from novelwriter.core import NWDoc
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert
from novelwriter.dialogs.itemeditor import GuiItemEditor
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -48,10 +50,10 @@ class GuiProjectTree(QTreeWidget):
C_EXPORT = 2 C_EXPORT = 2
C_STATUS = 3 C_STATUS = 3
novelItemChanged = pyqtSignal() treeItemChanged = pyqtSignal(str)
noteItemChanged = pyqtSignal() novelItemChanged = pyqtSignal(str)
rootFolderChanged = pyqtSignal(str)
wordCountsChanged = pyqtSignal() wordCountsChanged = pyqtSignal()
rootFoldersChanged = pyqtSignal()
def __init__(self, theParent): def __init__(self, theParent):
QTreeWidget.__init__(self, theParent) QTreeWidget.__init__(self, theParent)
@@ -64,10 +66,9 @@ class GuiProjectTree(QTreeWidget):
self.theProject = theParent.theProject self.theProject = theParent.theProject
# Internal Variables # Internal Variables
self._treeMap = {} self._treeMap = {}
self._treeChanged = False self._lastMove = {}
self._timeChanged = 0 self._timeChanged = 0
self._lastMove = {}
## ##
# Build GUI # Build GUI
@@ -157,15 +158,15 @@ class GuiProjectTree(QTreeWidget):
""" """
self.clear() self.clear()
self._treeMap = {} self._treeMap = {}
self._treeChanged = False self._lastMove = {}
self._timeChanged = 0 self._timeChanged = 0
return return
def newTreeItem(self, itemType, itemClass=None): def newTreeItem(self, itemType, itemClass=None):
"""Add new item to the tree, with a given itemType (and """Add new item to the tree, with a given itemType (and
itemClass if Root), and attach it to the selected handle. Also make itemClass if Root), and attach it to the selected handle. Also
sure the item is added in a place it can be added, and that other make sure the item is added in a place it can be added, and that
meta data is set correctly to ensure a valid project tree. other meta data is set correctly to ensure a valid project tree.
""" """
if not self.theParent.hasProject: if not self.theParent.hasProject:
logger.error("No project open") logger.error("No project open")
@@ -177,7 +178,6 @@ class GuiProjectTree(QTreeWidget):
if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass): if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass):
tHandle = self.theProject.newRoot(itemClass) tHandle = self.theProject.newRoot(itemClass)
self.rootFoldersChanged.emit()
elif itemType in (nwItemType.FILE, nwItemType.FOLDER): elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
@@ -223,9 +223,9 @@ class GuiProjectTree(QTreeWidget):
# Add the new item to the tree # Add the new item to the tree
self.revealNewTreeItem(tHandle, nHandle) self.revealNewTreeItem(tHandle, nHandle)
self.theParent.editItem(tHandle) self.theParent.editItem(tHandle)
nwItem = self.theProject.tree[tHandle]
# If this is a folder, return here # Handle new file creation
nwItem = self.theProject.tree[tHandle]
if nwItem.itemType != nwItemType.FILE: if nwItem.itemType != nwItemType.FILE:
return True return True
@@ -268,7 +268,7 @@ class GuiProjectTree(QTreeWidget):
if pHandle is not None and pHandle in self._treeMap: if pHandle is not None and pHandle in self._treeMap:
self._treeMap[pHandle].setExpanded(True) self._treeMap[pHandle].setExpanded(True)
self._emitItemChange(tHandle) self._alertTreeChange(tHandle=tHandle, flush=True)
self.clearSelection() self.clearSelection()
trItem.setSelected(True) trItem.setSelected(True)
@@ -310,10 +310,31 @@ class GuiProjectTree(QTreeWidget):
pItem.insertChild(nIndex, cItem) pItem.insertChild(nIndex, cItem)
self._recordLastMove(cItem, pItem, tIndex) self._recordLastMove(cItem, pItem, tIndex)
self._alertTreeChange(tHandle=tHandle, flush=True)
self.clearSelection() self.clearSelection()
cItem.setSelected(True) cItem.setSelected(True)
self._setTreeChanged(True)
self._emitItemChange(tHandle) return True
def editTreeItem(self, tHandle=None):
"""Open the edit item dialog.
"""
if tHandle is None:
logger.warning("No item selected")
return False
tItem = self.theProject.tree[tHandle]
if tItem is None:
return False
if tItem.itemType == nwItemType.NO_TYPE:
return False
logger.verbose("Requesting change to item '%s'", tHandle)
dlgProj = GuiItemEditor(self, tHandle)
dlgProj.exec_()
if dlgProj.result() == QDialog.Accepted:
self.setTreeItemValues(tHandle)
self._alertTreeChange(tHandle=tHandle, flush=False)
return True return True
@@ -330,16 +351,6 @@ class GuiProjectTree(QTreeWidget):
self.theProject.setTreeOrder(theList) self.theProject.setTreeOrder(theList)
return True return True
def flushTreeOrder(self):
"""Calls saveTreeOrder if there are unsaved changes, otherwise
does nothing.
"""
if self._treeChanged:
logger.verbose("Flushing project tree to project class")
self.saveTreeOrder()
self._setTreeChanged(False)
return
def getTreeFromHandle(self, tHandle): def getTreeFromHandle(self, tHandle):
"""Recursively return all the children items starting from a """Recursively return all the children items starting from a
given item handle. given item handle.
@@ -411,7 +422,7 @@ class GuiProjectTree(QTreeWidget):
self.deleteItem(tHandle, alreadyAsked=True, bulkAction=True) self.deleteItem(tHandle, alreadyAsked=True, bulkAction=True)
if nTrash > 0: if nTrash > 0:
self._setTreeChanged(True) self._alertTreeChange(tHandle=trashHandle, flush=True)
return True return True
@@ -445,6 +456,7 @@ class GuiProjectTree(QTreeWidget):
return False return False
wCount = self._getItemWordCount(tHandle) wCount = self._getItemWordCount(tHandle)
autoFlush = not bulkAction
if nwItemS.itemType == nwItemType.ROOT: if nwItemS.itemType == nwItemType.ROOT:
# Only an empty ROOT folder can be deleted # Only an empty ROOT folder can be deleted
logger.debug("User requested a root folder '%s' deleted", tHandle) logger.debug("User requested a root folder '%s' deleted", tHandle)
@@ -452,8 +464,7 @@ class GuiProjectTree(QTreeWidget):
if trItemS.childCount() == 0: if trItemS.childCount() == 0:
self.takeTopLevelItem(tIndex) self.takeTopLevelItem(tIndex)
self._deleteTreeItem(tHandle) self._deleteTreeItem(tHandle)
self._setTreeChanged(True) self._alertTreeChange(tHandle=tHandle, flush=True)
self.rootFoldersChanged.emit()
else: else:
self.theParent.makeAlert(self.tr( self.theParent.makeAlert(self.tr(
"Cannot delete root folder. It is not empty. " "Cannot delete root folder. It is not empty. "
@@ -469,7 +480,7 @@ class GuiProjectTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS) tIndex = trItemP.indexOfChild(trItemS)
trItemP.takeChild(tIndex) trItemP.takeChild(tIndex)
self._deleteTreeItem(tHandle) self._deleteTreeItem(tHandle)
self._setTreeChanged(True) self._alertTreeChange(tHandle=tHandle, flush=autoFlush)
else: else:
# A populated FOLDER or a FILE requires confirmtation # A populated FOLDER or a FILE requires confirmtation
@@ -505,7 +516,7 @@ class GuiProjectTree(QTreeWidget):
self.theParent.closeDocument() self.theParent.closeDocument()
self._deleteTreeItem(dHandle) self._deleteTreeItem(dHandle)
self._setTreeChanged(True) self._alertTreeChange(tHandle=tHandle, flush=autoFlush)
self.wordCountsChanged.emit() self.wordCountsChanged.emit()
else: else:
@@ -524,7 +535,7 @@ class GuiProjectTree(QTreeWidget):
trItemT.addChild(trItemC) trItemT.addChild(trItemC)
self._postItemMove(tHandle, wCount) self._postItemMove(tHandle, wCount)
self._recordLastMove(trItemS, trItemP, tIndex) self._recordLastMove(trItemS, trItemP, tIndex)
self._setTreeChanged(True) self._alertTreeChange(tHandle=tHandle, flush=autoFlush)
return True return True
@@ -660,6 +671,7 @@ class GuiProjectTree(QTreeWidget):
dstItem.insertChild(dstIndex, movItem) dstItem.insertChild(dstIndex, movItem)
self._postItemMove(sHandle, wCount) self._postItemMove(sHandle, wCount)
self._alertTreeChange(tHandle=sHandle, flush=True)
self.clearSelection() self.clearSelection()
movItem.setSelected(True) movItem.setSelected(True)
@@ -788,6 +800,7 @@ class GuiProjectTree(QTreeWidget):
QTreeWidget.dropEvent(self, theEvent) QTreeWidget.dropEvent(self, theEvent)
self._postItemMove(sHandle, wCount) self._postItemMove(sHandle, wCount)
self._recordLastMove(sItem, pItem, pIndex) self._recordLastMove(sItem, pItem, pIndex)
self._alertTreeChange(tHandle=sHandle, flush=True)
sItem.setExpanded(isExpanded) sItem.setExpanded(isExpanded)
return return
@@ -829,8 +842,6 @@ class GuiProjectTree(QTreeWidget):
# Trigger dependent updates # Trigger dependent updates
self.propagateCount(tHandle, wCount) self.propagateCount(tHandle, wCount)
self._setTreeChanged(True)
self._emitItemChange(tHandle)
return True return True
@@ -931,8 +942,6 @@ class GuiProjectTree(QTreeWidget):
self.setTreeItemValues(tHandle) self.setTreeItemValues(tHandle)
newItem.setExpanded(nwItem.isExpanded) newItem.setExpanded(nwItem.isExpanded)
self._setTreeChanged(True)
return newItem return newItem
def _addTrashRoot(self): def _addTrashRoot(self):
@@ -945,33 +954,34 @@ class GuiProjectTree(QTreeWidget):
trItem = self._getTreeItem(trashHandle) trItem = self._getTreeItem(trashHandle)
if trItem is None: if trItem is None:
trItem = self._addTreeItem( trItem = self._addTreeItem(self.theProject.tree[trashHandle])
self.theProject.tree[trashHandle]
)
if trItem is not None: if trItem is not None:
trItem.setExpanded(True) trItem.setExpanded(True)
self._setTreeChanged(True) self._alertTreeChange(tHandle=trashHandle, flush=True)
return trItem return trItem
def _setTreeChanged(self, theState): def _alertTreeChange(self, tHandle=None, flush=True):
"""Set the tree change flag, and propagate to the project. """Update information on tree change state, and emit necessary
signals.
""" """
self._treeChanged = theState self._timeChanged = time()
if theState: self.theProject.setProjectChanged(True)
self._timeChanged = time() if flush:
self.theProject.setProjectChanged(True) self.saveTreeOrder()
return
tItem = self.theProject.tree[tHandle]
if tItem is None:
return
itemType = tItem.itemType
if itemType == nwItemType.ROOT:
self.rootFolderChanged.emit(tHandle)
elif itemType == nwItemType.FILE and tItem.isNovelLike():
self.novelItemChanged.emit(tHandle)
self.treeItemChanged.emit(tHandle)
def _emitItemChange(self, tHandle):
"""Emit an item change signal for a given handle.
"""
if self.theProject.tree.checkType(tHandle, nwItemType.FILE):
nwItem = self.theProject.tree[tHandle]
if nwItem.isNovelLike():
self.novelItemChanged.emit()
else:
self.noteItemChanged.emit()
return return
def _recordLastMove(self, srcItem, parItem, parIndex): def _recordLastMove(self, srcItem, parItem, parIndex):
+11 -30
View File
@@ -44,9 +44,8 @@ from novelwriter.gui import (
GuiViewsBar GuiViewsBar
) )
from novelwriter.dialogs import ( from novelwriter.dialogs import (
GuiAbout, GuiDocMerge, GuiDocSplit, GuiItemEditor, GuiPreferences, GuiAbout, GuiDocMerge, GuiDocSplit, GuiPreferences, GuiProjectDetails,
GuiProjectDetails, GuiProjectLoad, GuiProjectSettings, GuiUpdates, GuiProjectLoad, GuiProjectSettings, GuiUpdates, GuiWordList
GuiWordList
) )
from novelwriter.tools import ( from novelwriter.tools import (
GuiBuildNovel, GuiLipsum, GuiProjectWizard, GuiWritingStats GuiBuildNovel, GuiLipsum, GuiProjectWizard, GuiWritingStats
@@ -123,7 +122,10 @@ class GuiMain(QMainWindow):
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick) self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged) self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount) self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
self.treeView.rootFoldersChanged.connect(self.projView.projectUpdated) 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.spellDictionaryChanged.connect(self.statusBar.setLanguage)
self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus) self.docEditor.docEditedStatusChanged.connect(self.statusBar.doUpdateDocumentStatus)
@@ -357,7 +359,7 @@ class GuiMain(QMainWindow):
self.rebuildTrees() self.rebuildTrees()
self.saveProject() self.saveProject()
self.docEditor.setDictionaries() self.docEditor.setDictionaries()
self.projView.projectUpdated() self.projView.updateRootItem(None)
self.rebuildIndex(beQuiet=True) self.rebuildIndex(beQuiet=True)
self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setRefTime(self.theProject.projOpened)
self.statusBar.setProjectStatus(nwState.GOOD) self.statusBar.setProjectStatus(nwState.GOOD)
@@ -504,7 +506,7 @@ class GuiMain(QMainWindow):
self.docEditor.setDictionaries() self.docEditor.setDictionaries()
self.docEditor.toggleSpellCheck(self.theProject.spellCheck) self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
self.statusBar.setRefTime(self.theProject.projOpened) self.statusBar.setRefTime(self.theProject.projOpened)
self.projView.projectUpdated() self.projView.updateRootItem(None)
self._updateStatusWordCount() self._updateStatusWordCount()
# Restore previously open documents, if any # Restore previously open documents, if any
@@ -596,7 +598,6 @@ class GuiMain(QMainWindow):
logger.error("No project open") logger.error("No project open")
return False return False
self.treeView.flushTreeOrder()
nHandle = None # The next handle after tHandle nHandle = None # The next handle after tHandle
fHandle = None # The first file handle we encounter fHandle = None # The first file handle we encounter
foundIt = False # We've found tHandle, pick the next we see foundIt = False # We've found tHandle, pick the next we see
@@ -813,27 +814,10 @@ class GuiMain(QMainWindow):
tHandle = self.docEditor.docHandle() tHandle = self.docEditor.docHandle()
else: else:
tHandle = self.treeView.getSelectedHandle() tHandle = self.treeView.getSelectedHandle()
if tHandle:
return self.treeView.editTreeItem(tHandle)
if tHandle is None: return False
logger.warning("No item selected")
return False
tItem = self.theProject.tree[tHandle]
if tItem is None:
return False
if tItem.itemType == nwItemType.NO_TYPE:
return False
logger.verbose("Requesting change to item '%s'", tHandle)
dlgProj = GuiItemEditor(self, tHandle)
dlgProj.exec_()
if dlgProj.result() == QDialog.Accepted:
self.treeView.setTreeItemValues(tHandle)
self.treeMeta.updateViewBox(tHandle)
self.docEditor.updateDocInfo(tHandle)
self.docViewer.updateDocInfo(tHandle)
return True
def rebuildTrees(self): def rebuildTrees(self):
"""Rebuild the project tree. """Rebuild the project tree.
@@ -966,8 +950,6 @@ class GuiMain(QMainWindow):
logger.error("No project open") logger.error("No project open")
return False return False
self.treeView.flushTreeOrder()
dlgDetails = getGuiItem("GuiProjectDetails") dlgDetails = getGuiItem("GuiProjectDetails")
if dlgDetails is None: if dlgDetails is None:
dlgDetails = GuiProjectDetails(self) dlgDetails = GuiProjectDetails(self)
@@ -1583,7 +1565,6 @@ class GuiMain(QMainWindow):
if self.mainStack.currentIndex() == self.idxOutlineView: if self.mainStack.currentIndex() == self.idxOutlineView:
logger.verbose("Novel tree changed while Outline tab active") logger.verbose("Novel tree changed while Outline tab active")
if self.hasProject: if self.hasProject:
self.treeView.flushTreeOrder()
self.projView.refreshView(novelChanged=True) self.projView.refreshView(novelChanged=True)
return return
-1
View File
@@ -709,7 +709,6 @@ class GuiBuildNovel(QDialog):
bldObj.initDocument() bldObj.initDocument()
# Make sure the project and document is up to date # Make sure the project and document is up to date
self.theParent.treeView.flushTreeOrder()
self.theParent.saveDocument() self.theParent.saveDocument()
self.buildProgress.setMaximum(len(self.theProject.tree)) self.buildProgress.setMaximum(len(self.theProject.tree))
-5
View File
@@ -246,17 +246,14 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd):
# Move novel folder up # Move novel folder up
assert nwTree.moveTreeItem(-1) is False assert nwTree.moveTreeItem(-1) is False
nwTree.flushTreeOrder()
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Move novel folder down # Move novel folder down
assert nwTree.moveTreeItem(1) is True assert nwTree.moveTreeItem(1) is True
nwTree.flushTreeOrder()
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 1 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 1
# Move novel folder up again # Move novel folder up again
assert nwTree.moveTreeItem(-1) is True assert nwTree.moveTreeItem(-1) is True
nwTree.flushTreeOrder()
assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0 assert nwGUI.theProject.tree._treeOrder.index("0000000000008") == 0
# Clean up # Clean up
@@ -432,10 +429,8 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR
assert nwTree.emptyTrash() is False assert nwTree.emptyTrash() is False
# Empty the trash proper # Empty the trash proper
nwTree._setTreeChanged(False)
assert nwTree.emptyTrash() is True assert nwTree.emptyTrash() is True
assert nwTree.getTreeFromHandle(trashHandle) == [trashHandle] assert nwTree.getTreeFromHandle(trashHandle) == [trashHandle]
assert nwTree._treeChanged is True
# Try to delete a file, but block the underlying deletion of the file on disk # Try to delete a file, but block the underlying deletion of the file on disk
assert os.path.isfile(os.path.join(fncDir, "project", "content", "000000000000e.nwd")) assert os.path.isfile(os.path.join(fncDir, "project", "content", "000000000000e.nwd"))