Simplify updating an item after it has been moved

This commit is contained in:
Veronica Berglyd Olsen
2022-04-17 17:49:47 +02:00
parent d158de5d82
commit 50db7fcddb
7 changed files with 62 additions and 75 deletions
+1 -10
View File
@@ -25,7 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP from PyQt5.QtCore import QCoreApplication, QT_TRANSLATE_NOOP
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType, nwOutline from novelwriter.enum import nwItemClass, nwItemLayout, nwOutline
def trConst(tString): def trConst(tString):
@@ -51,18 +51,9 @@ class nwConst():
class nwLists(): class nwLists():
"""Lists used for grouping various other constants. """Lists used for grouping various other constants.
""" """
# Regular user-accessible item types
REG_TYPES = {nwItemType.ROOT, nwItemType.FOLDER, nwItemType.FILE}
# Item classes where the full list of novel layouts are allowed
CLS_NOVEL = {nwItemClass.NOVEL, nwItemClass.ARCHIVE}
# Item classes which do not require items to have same class # Item classes which do not require items to have same class
FREE_CLASS = {nwItemClass.ARCHIVE, nwItemClass.TRASH} FREE_CLASS = {nwItemClass.ARCHIVE, nwItemClass.TRASH}
# Deprecated nwItemLayout entries
DEP_LAYOUT = ("TITLE", "PAGE", "BOOK", "PARTITION", "UNNUMBERED", "CHAPTER", "SCENE")
# END Class nwLists # END Class nwLists
+31 -7
View File
@@ -31,10 +31,13 @@ from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout
from novelwriter.common import ( from novelwriter.common import (
checkInt, isHandle, isItemClass, isItemLayout, isItemType, simplified checkInt, isHandle, isItemClass, isItemLayout, isItemType, simplified
) )
from novelwriter.constants import nwLabels, nwLists, trConst from novelwriter.constants import nwLabels, trConst
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Deprecated layout labels
DEP_LAYOUTS = ("TITLE", "PAGE", "BOOK", "PARTITION", "UNNUMBERED", "CHAPTER", "SCENE")
class NWItem(): class NWItem():
@@ -282,11 +285,27 @@ class NWItem():
return trConst(nwLabels.ITEM_DESCRIPTION.get(descKey, "")) return trConst(nwLabels.ITEM_DESCRIPTION.get(descKey, ""))
def isNovelLike(self):
"""Returns true if the item is of a novel-like class.
"""
return self._class in (nwItemClass.NOVEL, nwItemClass.ARCHIVE)
def documentAllowed(self):
"""Returns true if the item is allowed to be of document layout.
"""
return self._class in (nwItemClass.NOVEL, nwItemClass.ARCHIVE, nwItemClass.TRASH)
def isInactive(self):
"""Returns true if the item is in the inactive parts of the
project.
"""
return self._class in (nwItemClass.NO_CLASS, nwItemClass.ARCHIVE, nwItemClass.TRASH)
def getImportStatus(self): def getImportStatus(self):
"""Return the relevant importance or status label and icon for """Return the relevant importance or status label and icon for
the current item based on its class. the current item based on its class.
""" """
if self._class in nwLists.CLS_NOVEL: if self.isNovelLike():
stName = self.theProject.statusItems.name(self._status) stName = self.theProject.statusItems.name(self._status)
stIcon = self.theProject.statusItems.icon(self._status) stIcon = self.theProject.statusItems.icon(self._status)
else: else:
@@ -298,7 +317,7 @@ class NWItem():
"""Update the importance or status value based on class. This is """Update the importance or status value based on class. This is
a wrapper setter for setStatus and setImport. a wrapper setter for setStatus and setImport.
""" """
if self._class in nwLists.CLS_NOVEL: if self.isNovelLike():
self.setStatus(value) self.setStatus(value)
else: else:
self.setImport(value) self.setImport(value)
@@ -312,9 +331,14 @@ class NWItem():
# Only update for child items # Only update for child items
self.setClass(itemClass) self.setClass(itemClass)
if self._class in nwLists.CLS_NOVEL: if self._layout == nwItemLayout.NO_LAYOUT:
self._layout = nwItemLayout.DOCUMENT # If no layout is set, pick one
else: if self.isNovelLike():
self._layout = nwItemLayout.DOCUMENT
else:
self._layout = nwItemLayout.NOTE
elif not self.documentAllowed():
# Change layout to note if it is not in an allowed folder
self._layout = nwItemLayout.NOTE self._layout = nwItemLayout.NOTE
if self._status is None: if self._status is None:
@@ -411,7 +435,7 @@ class NWItem():
self._layout = itemLayout self._layout = itemLayout
elif isItemLayout(itemLayout): elif isItemLayout(itemLayout):
self._layout = nwItemLayout[itemLayout] self._layout = nwItemLayout[itemLayout]
elif itemLayout in nwLists.DEP_LAYOUT: elif itemLayout in DEP_LAYOUTS:
self._layout = nwItemLayout.DOCUMENT self._layout = nwItemLayout.DOCUMENT
else: else:
logger.error("Unrecognised item layout '%s'", itemLayout) logger.error("Unrecognised item layout '%s'", itemLayout)
+2 -2
View File
@@ -46,7 +46,7 @@ from novelwriter.common import (
checkString, checkBool, checkInt, isHandle, formatTimeStamp, checkString, checkBool, checkInt, isHandle, formatTimeStamp,
makeFileNameSafe, hexToInt, simplified makeFileNameSafe, hexToInt, simplified
) )
from novelwriter.constants import nwLists, trConst, nwFiles, nwLabels from novelwriter.constants import trConst, nwFiles, nwLabels
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -1197,7 +1197,7 @@ class NWProject():
self.statusItems.resetCounts() self.statusItems.resetCounts()
self.importItems.resetCounts() self.importItems.resetCounts()
for nwItem in self.projTree: for nwItem in self.projTree:
if nwItem.itemClass in nwLists.CLS_NOVEL: if nwItem.isNovelLike():
self.statusItems.increment(nwItem.itemStatus) self.statusItems.increment(nwItem.itemStatus)
else: else:
self.importItems.increment(nwItem.itemImport) self.importItems.increment(nwItem.itemImport)
+3 -3
View File
@@ -33,7 +33,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter.enum import nwItemLayout, nwItemType from novelwriter.enum import nwItemLayout, nwItemType
from novelwriter.constants import trConst, nwLists, nwLabels from novelwriter.constants import trConst, nwLabels
from novelwriter.gui.custom import QSwitch from novelwriter.gui.custom import QSwitch
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -74,7 +74,7 @@ class GuiItemEditor(QDialog):
# Item Status # Item Status
self.editStatus = QComboBox() self.editStatus = QComboBox()
self.editStatus.setMinimumWidth(mVd) self.editStatus.setMinimumWidth(mVd)
if self.theItem.itemClass in nwLists.CLS_NOVEL: if self.theItem.isNovelLike():
for key, entry in self.theProject.statusItems.items(): for key, entry in self.theProject.statusItems.items():
self.editStatus.addItem(entry["icon"], entry["name"], key) self.editStatus.addItem(entry["icon"], entry["name"], key)
@@ -95,7 +95,7 @@ class GuiItemEditor(QDialog):
self.editLayout.setMinimumWidth(mVd) self.editLayout.setMinimumWidth(mVd)
validLayouts = [] validLayouts = []
if self.theItem.itemType == nwItemType.FILE: if self.theItem.itemType == nwItemType.FILE:
if self.theItem.itemClass in nwLists.CLS_NOVEL: if self.theItem.documentAllowed():
validLayouts.append(nwItemLayout.DOCUMENT) validLayouts.append(nwItemLayout.DOCUMENT)
validLayouts.append(nwItemLayout.NOTE) validLayouts.append(nwItemLayout.NOTE)
else: else:
+23 -50
View File
@@ -206,7 +206,7 @@ class GuiProjectTree(QTreeWidget):
# Add the file or folder # Add the file or folder
if itemType == nwItemType.FILE: if itemType == nwItemType.FILE:
if pItem.itemClass in nwLists.CLS_NOVEL: if pItem.isNovelLike():
tHandle = self.theProject.newFile(self.tr("New Document"), sHandle) tHandle = self.theProject.newFile(self.tr("New Document"), sHandle)
else: else:
tHandle = self.theProject.newFile(self.tr("New Note"), sHandle) tHandle = self.theProject.newFile(self.tr("New Note"), sHandle)
@@ -495,10 +495,7 @@ class GuiProjectTree(QTreeWidget):
tIndex = trItemP.indexOfChild(trItemS) tIndex = trItemP.indexOfChild(trItemS)
trItemC = trItemP.takeChild(tIndex) trItemC = trItemP.takeChild(tIndex)
trItemT.addChild(trItemC) trItemT.addChild(trItemC)
self._updateItemParent(tHandle) self._postItemMove(tHandle, wCount)
self.propagateCount(tHandle, wCount)
self.theIndex.deleteHandle(tHandle)
self._recordLastMove(trItemS, trItemP, tIndex) self._recordLastMove(trItemS, trItemP, tIndex)
self._setTreeChanged(True) self._setTreeChanged(True)
@@ -661,9 +658,7 @@ class GuiProjectTree(QTreeWidget):
movItem = parItem.takeChild(srcIndex) movItem = parItem.takeChild(srcIndex)
dstItem.insertChild(dstIndex, movItem) dstItem.insertChild(dstIndex, movItem)
snItem = self.theProject.projTree[sHandle] self._postItemMove(sHandle, wCount)
dnItem = self.theProject.projTree[dHandle]
self._postItemMove(sHandle, snItem, dnItem, wCount)
self.clearSelection() self.clearSelection()
movItem.setSelected(True) movItem.setSelected(True)
@@ -812,7 +807,7 @@ class GuiProjectTree(QTreeWidget):
logger.debug("Drag'n'drop of item '%s' accepted", sHandle) logger.debug("Drag'n'drop of item '%s' accepted", sHandle)
self.propagateCount(sHandle, 0) self.propagateCount(sHandle, 0)
QTreeWidget.dropEvent(self, theEvent) QTreeWidget.dropEvent(self, theEvent)
self._postItemMove(sHandle, snItem, dnItem, wCount) self._postItemMove(sHandle, wCount)
self._recordLastMove(sItem, pItem, pIndex) self._recordLastMove(sItem, pItem, pIndex)
else: else:
@@ -828,40 +823,37 @@ class GuiProjectTree(QTreeWidget):
# Internal Functions # Internal Functions
## ##
def _postItemMove(self, sHandle, snItem, dnItem, wCount): def _postItemMove(self, tHandle, wCount):
"""Run various maintenance tasks for a moved item. """Run various maintenance tasks for a moved item.
""" """
isFile = snItem.itemType == nwItemType.FILE trItemS = self._getTreeItem(tHandle)
isSame = snItem.itemClass == dnItem.itemClass nwItemS = self.theProject.projTree[tHandle]
onFree = dnItem.itemClass in nwLists.FREE_CLASS and isFile trItemP = trItemS.parent()
if trItemP is None:
logger.error("Failed to find new parent item of '%s'", tHandle)
return False
self._updateItemParent(sHandle) pHandle = trItemP.data(self.C_NAME, Qt.UserRole)
nwItemS.setParent(pHandle)
self.theProject.projTree.updateItemData(tHandle)
self.setTreeItemValues(tHandle)
self.propagateCount(tHandle, wCount)
# If the item does not have the same class as the target, logger.debug("The parent of item '%s' has been changed to '%s'", tHandle, pHandle)
# and the target is not a free root folder, update its class
if not (isSame or onFree):
logger.debug(
"Item '%s' class has been changed from '%s' to '%s'",
sHandle, snItem.itemClass.name, dnItem.itemClass.name
)
snItem.setClass(dnItem.itemClass)
self.setTreeItemValues(sHandle)
self.propagateCount(sHandle, wCount)
# The items dropped into archive or trash should be removed # The items dropped into archive or trash should be removed
# from the project index, for all other items, we rescan the # from the project index, for all other items, we rescan the
# file to ensure the index is up to date. # file to ensure the index is up to date.
if onFree: if nwItemS.isInactive():
self.theIndex.deleteHandle(sHandle) self.theIndex.deleteHandle(tHandle)
else: else:
self.theIndex.reIndexHandle(sHandle) self.theIndex.reIndexHandle(tHandle)
# Trigger dependent updates # Trigger dependent updates
self._setTreeChanged(True) self._setTreeChanged(True)
self._emitItemChange(sHandle) self._emitItemChange(tHandle)
return return True
def _getTreeItem(self, tHandle): def _getTreeItem(self, tHandle):
"""Returns the QTreeWidgetItem of a given item handle. """Returns the QTreeWidgetItem of a given item handle.
@@ -961,25 +953,6 @@ class GuiProjectTree(QTreeWidget):
return trItem return trItem
def _updateItemParent(self, tHandle):
"""Update the parent handle of an item so that the information
in the project is consistent with the treeView.
"""
trItemS = self._getTreeItem(tHandle)
nwItemS = self.theProject.projTree[tHandle]
trItemP = trItemS.parent()
if trItemP is None:
logger.error("Failed to find new parent item of '%s'", tHandle)
return False
pHandle = trItemP.data(self.C_NAME, Qt.UserRole)
nwItemS.setParent(pHandle)
self.setTreeItemValues(tHandle)
logger.debug("The parent of item '%s' has been changed to '%s'", tHandle, pHandle)
return True
def _setTreeChanged(self, theState): def _setTreeChanged(self, theState):
"""Set the tree change flag, and propagate to the project. """Set the tree change flag, and propagate to the project.
""" """
@@ -994,7 +967,7 @@ class GuiProjectTree(QTreeWidget):
""" """
if self.theProject.projTree.checkType(tHandle, nwItemType.FILE): if self.theProject.projTree.checkType(tHandle, nwItemType.FILE):
nwItem = self.theProject.projTree[tHandle] nwItem = self.theProject.projTree[tHandle]
if nwItem.itemClass in nwLists.CLS_NOVEL: if nwItem.isNovelLike():
self.novelItemChanged.emit() self.novelItemChanged.emit()
else: else:
self.noteItemChanged.emit() self.noteItemChanged.emit()
+1 -2
View File
@@ -55,7 +55,6 @@ from novelwriter.enum import (
nwItemType, nwItemClass, nwAlert, nwWidget, nwState nwItemType, nwItemClass, nwAlert, nwWidget, nwState
) )
from novelwriter.common import getGuiItem, hexToInt from novelwriter.common import getGuiItem, hexToInt
from novelwriter.constants import nwLists
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -848,7 +847,7 @@ class GuiMain(QMainWindow):
tItem = self.theProject.projTree[tHandle] tItem = self.theProject.projTree[tHandle]
if tItem is None: if tItem is None:
return False return False
if tItem.itemType not in nwLists.REG_TYPES: if tItem.itemType == nwItemType.NO_TYPE:
return False return False
logger.verbose("Requesting change to item '%s'", tHandle) logger.verbose("Requesting change to item '%s'", tHandle)
+1 -1
View File
@@ -1076,7 +1076,7 @@ def testCoreProject_OrphanedFiles(mockGUI, nwLipsum):
assert oItem.itemParent == "b3643d0f92e32" assert oItem.itemParent == "b3643d0f92e32"
assert oItem.itemClass == nwItemClass.NOVEL assert oItem.itemClass == nwItemClass.NOVEL
assert oItem.itemType == nwItemType.FILE assert oItem.itemType == nwItemType.FILE
assert oItem.itemLayout == nwItemLayout.DOCUMENT assert oItem.itemLayout == nwItemLayout.NOTE
assert theProject.saveProject(nwLipsum) assert theProject.saveProject(nwLipsum)
assert theProject.closeProject() assert theProject.closeProject()