Improve the way the project tree is managed and elements deleted.

This commit is contained in:
Veronica K. B. Olsen
2020-09-17 14:03:51 +02:00
parent 9bca006a45
commit 27ee82aad0
4 changed files with 47 additions and 27 deletions
+12
View File
@@ -82,6 +82,18 @@ def checkBool(checkValue, defaultValue, allowNone=False):
return defaultValue return defaultValue
return defaultValue return defaultValue
def checkHandle(checkValue, defaultValue, allowNone=False):
"""Check if a value is a handle.
"""
if allowNone:
if checkValue is None:
return None
if checkValue == "None":
return None
if isHandle(checkValue):
return str(checkValue)
return defaultValue
def isHandle(theString): def isHandle(theString):
"""Check if a string is a valid novelWriter handle. """Check if a string is a valid novelWriter handle.
Note: This is case sensitive. Must be lower case! Note: This is case sensitive. Must be lower case!
+20 -21
View File
@@ -34,7 +34,7 @@ from hashlib import sha256
from time import time from time import time
from nw.core.item import NWItem from nw.core.item import NWItem
from nw.common import checkString from nw.common import checkHandle
from nw.constants import nwFiles, nwItemType, nwItemClass, nwItemLayout, nwConst from nw.constants import nwFiles, nwItemType, nwItemClass, nwItemLayout, nwConst
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -49,7 +49,6 @@ class NWTree():
self._treeOrder = [] # The order of the tree items on the tree view self._treeOrder = [] # The order of the tree items on the tree view
self._treeRoots = [] # The root items of the tree self._treeRoots = [] # The root items of the tree
self._trashRoot = None # The handle of the trash root folder self._trashRoot = None # The handle of the trash root folder
self._theLength = 0 # Always the length of _treeOrder
self._theIndex = 0 # The current iterator index self._theIndex = 0 # The current iterator index
self._treeChanged = False # True if tree structure has changed self._treeChanged = False # True if tree structure has changed
self._handleSeed = None # Used for generating handles for testing self._handleSeed = None # Used for generating handles for testing
@@ -68,7 +67,6 @@ class NWTree():
self._treeRoots = [] self._treeRoots = []
self._trashRoot = None self._trashRoot = None
self._archRoot = None self._archRoot = None
self._theLength = 0
self._theIndex = 0 self._theIndex = 0
self._treeChanged = False self._treeChanged = False
return return
@@ -81,8 +79,8 @@ class NWTree():
def append(self, tHandle, pHandle, nwItem): def append(self, tHandle, pHandle, nwItem):
"""Add a new item to the end of the tree. """Add a new item to the end of the tree.
""" """
tHandle = checkString(tHandle, None, True) tHandle = checkHandle(tHandle, None, True)
pHandle = checkString(pHandle, None, True) pHandle = checkHandle(pHandle, None, True)
if tHandle is None: if tHandle is None:
tHandle = self._makeHandle() tHandle = self._makeHandle()
@@ -108,16 +106,16 @@ class NWTree():
else: else:
logger.error("Only one trash folder allowed") logger.error("Only one trash folder allowed")
self._theLength = len(self._treeOrder)
self._setTreeChanged(True) self._setTreeChanged(True)
return return
def packXML(self, xParent): def packXML(self, xParent):
"""Pack the content of the tree into an XML object. """Pack the content of the tree into the provided XML object. In
the order defined by the _treeOrder list.
""" """
xContent = etree.SubElement(xParent, "content", attrib={ xContent = etree.SubElement(xParent, "content", attrib={
"count": str(self._theLength)} "count": str(len(self._treeOrder))}
) )
for tHandle in self._treeOrder: for tHandle in self._treeOrder:
tItem = self.__getitem__(tHandle) tItem = self.__getitem__(tHandle)
@@ -309,7 +307,6 @@ class NWTree():
# Save the temp list # Save the temp list
self._treeOrder = tmpOrder self._treeOrder = tmpOrder
self._theLength = len(self._treeOrder)
self._setTreeChanged(True) self._setTreeChanged(True)
logger.verbose("Project tree order updated") logger.verbose("Project tree order updated")
@@ -330,7 +327,7 @@ class NWTree():
if tItem is None: if tItem is None:
return False return False
if tItem.itemType != nwItemType.FILE: if tItem.itemType != nwItemType.FILE:
logger.error("Item '%s' is not a file" % tHandle) logger.error("Item %s is not a file" % tHandle)
return False return False
if not isinstance(itemLayout, nwItemLayout): if not isinstance(itemLayout, nwItemLayout):
return False return False
@@ -370,12 +367,12 @@ class NWTree():
def __len__(self): def __len__(self):
"""Return the length counter. Does not check that it is correct! """Return the length counter. Does not check that it is correct!
""" """
return self._theLength return len(self._treeOrder)
def __bool__(self): def __bool__(self):
"""Returns True if the tree has any entries. """Returns True if the tree has any entries.
""" """
return self._theLength > 0 return len(self._treeOrder) > 0
## ##
# Item Access Methods # Item Access Methods
@@ -391,19 +388,21 @@ class NWTree():
return None return None
def __delitem__(self, tHandle): def __delitem__(self, tHandle):
"""This only removes the item from the order list, but not from """Remove an item from the internal lists and dictionaries.
the project tree.
""" """
if tHandle not in self._treeOrder: if tHandle in self._treeOrder and tHandle in self._projTree:
logger.warning( self._treeOrder.remove(tHandle)
"Could not remove item %s from project tree as it does not exist" % tHandle del self._projTree[tHandle]
) else:
logger.warning("Failed to delete item %s: item not found" % tHandle)
return False return False
self._treeOrder.remove(tHandle)
self._theLength = len(self._treeOrder)
if tHandle in self._treeRoots: if tHandle in self._treeRoots:
self._treeRoots.remove(tHandle) self._treeRoots.remove(tHandle)
if tHandle == self._trashRoot:
self._trashRoot = None
if tHandle == self._archRoot:
self._archRoot = None
self._setTreeChanged(True) self._setTreeChanged(True)
@@ -427,7 +426,7 @@ class NWTree():
def __next__(self): def __next__(self):
"""Returns the item from the next entry in the _treeOrder list. """Returns the item from the next entry in the _treeOrder list.
""" """
if self._theIndex < self._theLength: if self._theIndex < len(self._treeOrder):
theItem = self.__getitem__(self._treeOrder[self._theIndex]) theItem = self.__getitem__(self._treeOrder[self._theIndex])
self._theIndex += 1 self._theIndex += 1
return theItem return theItem
+5 -5
View File
@@ -378,11 +378,11 @@ class GuiProjectTree(QTreeWidget):
return True return True
def deleteItem(self, tHandle=None, alreadyAsked=False, askForTrash=False): def deleteItem(self, tHandle=None, alreadyAsked=False, askForTrash=False):
"""Delete items from the tree. Note that this does not delete """Delete an item from the project tree. As a first step, files are
the item from the item tree in the project object. However, moved to the Trash folder. Permanent deletion is a second step. This
since this is only meta data, there isn't really a need to do second step also deletes the item from the project object as well as
that to save memory. Items not in the tree are not saved to the delete the files on disk. Folders are deleted if they're empty only,
project file, so a loaded project will be clean anyway. and the deletion is always permanent.
""" """
if tHandle is None: if tHandle is None:
tHandle = self.getSelectedHandle() tHandle = self.getSelectedHandle()
+10 -1
View File
@@ -5,7 +5,7 @@
import pytest import pytest
from nw.common import ( from nw.common import (
checkString, checkBool, checkInt, colRange, formatInt, transferCase, checkString, checkBool, checkInt, colRange, formatInt, transferCase,
fuzzyTime fuzzyTime, checkHandle
) )
from nwtools import cmpList from nwtools import cmpList
@@ -42,6 +42,15 @@ def testCheckBool():
assert checkBool(1.0, None, False) is None assert checkBool(1.0, None, False) is None
assert checkBool(2.0, None, False) is None assert checkBool(2.0, None, False) is None
@pytest.mark.core
def testCheckHandle():
assert checkHandle("None", 1, True) is None
assert checkHandle("None", 1, False) == 1
assert checkHandle(None, 1, True) is None
assert checkHandle(None, 1, False) == 1
assert checkHandle("47666c91c7ccf", None, False) == "47666c91c7ccf"
assert checkHandle("h7666c91c7ccf", None, False) is None
@pytest.mark.core @pytest.mark.core
def testColRange(): def testColRange():
assert colRange([0, 0], [0, 0], 0) is None assert colRange([0, 0], [0, 0], 0) is None