diff --git a/nw/constants.py b/nw/constants.py index b9484971..7dc39f05 100644 --- a/nw/constants.py +++ b/nw/constants.py @@ -23,6 +23,7 @@ class nwLabels(): nwItemClass.TIMELINE : "Timeline", nwItemClass.OBJECT : "Objects", nwItemClass.CUSTOM : "Custom", + nwItemClass.TRASH : "Trash", } CLASS_FLAG = { nwItemClass.NO_CLASS : "0", @@ -33,6 +34,7 @@ class nwLabels(): nwItemClass.TIMELINE : "T", nwItemClass.OBJECT : "O", nwItemClass.CUSTOM : "X", + nwItemClass.TRASH : "R", } LAYOUT_NAME = { nwItemLayout.NO_LAYOUT : "None", diff --git a/nw/enum.py b/nw/enum.py index e162feeb..d253f684 100644 --- a/nw/enum.py +++ b/nw/enum.py @@ -18,7 +18,7 @@ class nwItemType(Enum): ROOT = 1 FOLDER = 2 FILE = 3 - TRASHFOLDER = 4 + TRASH = 4 TRASHFILE = 5 # END Enum nwItemType @@ -33,6 +33,7 @@ class nwItemClass(Enum): TIMELINE = 5 OBJECT = 6 CUSTOM = 7 + TRASH = 8 # END Enum nwItemClass diff --git a/nw/gui/doctree.py b/nw/gui/doctree.py index 9d8b6b72..609338de 100644 --- a/nw/gui/doctree.py +++ b/nw/gui/doctree.py @@ -76,6 +76,10 @@ class GuiDocTree(QTreeWidget): return + ## + # Class Methods + ## + def clearTree(self): self.clear() @@ -164,18 +168,6 @@ class GuiDocTree(QTreeWidget): cItem.setSelected(True) return - def renameTreeItem(self, tHandle): - tItem = self.theMap[tHandle] - oldName = tItem.text(self.C_NAME) - newName, isOk = QInputDialog.getText(self, "Rename Item", "New Name", QLineEdit.Normal,oldName) - if isOk: - newName = newName.strip() - if newName == "": - newName = oldName - tItem.setText(self.C_NAME,newName) - self.theProject.setItemName(tHandle, newName) - return - def saveTreeOrder(self): theList = [] for i in range(self.topLevelItemCount()): @@ -193,107 +185,12 @@ class GuiDocTree(QTreeWidget): ] return retVals - ## - # Internal Functions - ## - - def _scanChildren(self, theList, theItem, theIndex): - tHandle = theItem.text(self.C_HANDLE) - nwItem = self.theProject.projTree[tHandle] - nwItem.setExpanded(theItem.isExpanded()) - nwItem.setOrder(theIndex) - theList.append(tHandle) - for i in range(theItem.childCount()): - self._scanChildren(theList, theItem.child(i), i) - return theList - - def _scanParents(self, theItem, theCount=0): - if theItem.parent() is not None: - theItem, theCount = self._scanParents(theItem.parent(), theCount) - return theItem, theCount+1 - - def _addTreeItem(self, nwItem): - - tHandle = nwItem.itemHandle - pHandle = nwItem.parHandle - newItem = QTreeWidgetItem([""]*4) - - newItem.setText(self.C_NAME, "") - newItem.setText(self.C_COUNT, "0") - newItem.setText(self.C_FLAGS, "") - newItem.setText(self.C_HANDLE, tHandle) - - newItem.setForeground(self.C_COUNT,QColor(0,105,135)) - newItem.setTextAlignment(self.C_COUNT,Qt.AlignRight) - newItem.setFont(self.C_FLAGS,self.fontFlags) - - self.theMap[tHandle] = newItem - if pHandle is None: - if nwItem.itemType == nwItemType.ROOT: - self.addTopLevelItem(newItem) - self.theParent.mainMenu.setAvailableRoot() - else: - self._addOrphanedRoot() - self.orphRoot.addChild(newItem) - else: - self.theMap[pHandle].addChild(newItem) - self.propagateCount(tHandle, nwItem.wordCount) - - self.setTreeItemValues(tHandle) - newItem.setExpanded(nwItem.isExpanded) - - if nwItem.itemType == nwItemType.ROOT: - newItem.setIcon(self.C_NAME, QIcon.fromTheme("drive-harddisk")) - elif nwItem.itemType == nwItemType.FOLDER: - newItem.setIcon(self.C_NAME, QIcon.fromTheme("folder")) - elif nwItem.itemType == nwItemType.FILE: - newItem.setIcon(self.C_NAME, QIcon.fromTheme("x-office-document")) - - return newItem - - def _addOrphanedRoot(self): - if self.orphRoot is None: - newItem = QTreeWidgetItem([""]*4) - newItem.setText(self.C_NAME, "Orphaned Files") - newItem.setText(self.C_COUNT, "") - newItem.setText(self.C_FLAGS, "") - newItem.setText(self.C_HANDLE, "") - self.addTopLevelItem(newItem) - self.orphRoot = newItem - newItem.setExpanded(True) - return - - def _cleanOrphanedRoot(self): - if self.orphRoot.childCount() == 0: - self.takeTopLevelItem(self.indexOfTopLevelItem(self.orphRoot)) - self.orphRoot = None - return - - def _updateItemParent(self, tHandle): - trItemS = self.theMap[tHandle] - nwItemS = self.theProject.getItem(tHandle) - trItemP = trItemS.parent() - if trItemP is None: - logger.error("Failed to find new parent item of %s" % tHandle) - return - pHandle = trItemP.text(self.C_HANDLE) - nwItemS.setParent(pHandle) - self.setTreeItemValues(tHandle) - return - - def _moveOrphanedItem(self, tHandle, dHandle): - trItemS = self.theMap[tHandle] - nwItemS = self.theProject.getItem(tHandle) - nwItemD = self.theProject.getItem(dHandle) - trItemP = trItemS.parent() - nwItemS.setClass(nwItemD.itemClass) - if trItemP is None: - logger.error("Failed to find new parent item of %s" % tHandle) - return - pHandle = trItemP.text(self.C_HANDLE) - nwItemS.setParent(pHandle) - nwItemS.setDepth(self.theProject.countItemDepth(tHandle)) - self.setTreeItemValues(tHandle) + def deleteItem(self): + tHandle = self.getSelectedHandle() + nwItem = self.theProject.getItem(tHandle) + if nwItem.itemType == nwItemType.FILE: + logger.debug("User requested item %s moved to trash" % tHandle) + self._addTrashRoot() return def setTreeItemValues(self, tHandle): @@ -345,6 +242,119 @@ class GuiDocTree(QTreeWidget): return selItem[0].text(self.C_HANDLE) return None + ## + # Internal Functions + ## + + def _scanChildren(self, theList, theItem, theIndex): + tHandle = theItem.text(self.C_HANDLE) + nwItem = self.theProject.projTree[tHandle] + nwItem.setExpanded(theItem.isExpanded()) + nwItem.setOrder(theIndex) + theList.append(tHandle) + for i in range(theItem.childCount()): + self._scanChildren(theList, theItem.child(i), i) + return theList + + def _scanParents(self, theItem, theCount=0): + if theItem.parent() is not None: + theItem, theCount = self._scanParents(theItem.parent(), theCount) + return theItem, theCount+1 + + def _addTreeItem(self, nwItem): + + tHandle = nwItem.itemHandle + pHandle = nwItem.parHandle + newItem = QTreeWidgetItem([""]*4) + + newItem.setText(self.C_NAME, "") + newItem.setText(self.C_COUNT, "0") + newItem.setText(self.C_FLAGS, "") + newItem.setText(self.C_HANDLE, tHandle) + + newItem.setForeground(self.C_COUNT,QColor(0,105,135)) + newItem.setTextAlignment(self.C_COUNT,Qt.AlignRight) + newItem.setFont(self.C_FLAGS,self.fontFlags) + + self.theMap[tHandle] = newItem + if pHandle is None: + if nwItem.itemType == nwItemType.ROOT: + self.addTopLevelItem(newItem) + self.theParent.mainMenu.setAvailableRoot() + elif nwItem.itemType == nwItemType.TRASH: + self.addTopLevelItem(newItem) + else: + self._addOrphanedRoot() + self.orphRoot.addChild(newItem) + else: + self.theMap[pHandle].addChild(newItem) + self.propagateCount(tHandle, nwItem.wordCount) + + self.setTreeItemValues(tHandle) + newItem.setExpanded(nwItem.isExpanded) + + if nwItem.itemType == nwItemType.ROOT: + newItem.setIcon(self.C_NAME, QIcon.fromTheme("drive-harddisk")) + elif nwItem.itemType == nwItemType.FOLDER: + newItem.setIcon(self.C_NAME, QIcon.fromTheme("folder")) + elif nwItem.itemType == nwItemType.FILE: + newItem.setIcon(self.C_NAME, QIcon.fromTheme("x-office-document")) + elif nwItem.itemType == nwItemType.TRASH: + newItem.setIcon(self.C_NAME, QIcon.fromTheme("user-trash")) + + return newItem + + def _addTrashRoot(self): + if self.theProject.trashRoot is None: + self.theProject.addTrash() + self._addTreeItem(self.theProject.getItem(self.theProject.trashRoot)) + return + + def _addOrphanedRoot(self): + if self.orphRoot is None: + newItem = QTreeWidgetItem([""]*4) + newItem.setText(self.C_NAME, "Orphaned Files") + newItem.setText(self.C_COUNT, "") + newItem.setText(self.C_FLAGS, "") + newItem.setText(self.C_HANDLE, "") + self.addTopLevelItem(newItem) + self.orphRoot = newItem + newItem.setExpanded(True) + return + + def _cleanOrphanedRoot(self): + if self.orphRoot.childCount() == 0: + self.takeTopLevelItem(self.indexOfTopLevelItem(self.orphRoot)) + self.orphRoot = None + return + + def _updateItemParent(self, tHandle): + trItemS = self.theMap[tHandle] + nwItemS = self.theProject.getItem(tHandle) + trItemP = trItemS.parent() + if trItemP is None: + logger.error("Failed to find new parent item of %s" % tHandle) + return + pHandle = trItemP.text(self.C_HANDLE) + nwItemS.setParent(pHandle) + self.setTreeItemValues(tHandle) + return + + def _moveOrphanedItem(self, tHandle, dHandle): + trItemS = self.theMap[tHandle] + nwItemS = self.theProject.getItem(tHandle) + nwItemD = self.theProject.getItem(dHandle) + trItemP = trItemS.parent() + nwItemS.setClass(nwItemD.itemClass) + if trItemP is None: + logger.error("Failed to find new parent item of %s" % tHandle) + return + pHandle = trItemP.text(self.C_HANDLE) + nwItemS.setParent(pHandle) + nwItemS.setDepth(self.theProject.countItemDepth(tHandle)) + self.setTreeItemValues(tHandle) + return + ## # Event Overloading ## diff --git a/nw/gui/mainmenu.py b/nw/gui/mainmenu.py index d54a1ac1..a2669b22 100644 --- a/nw/gui/mainmenu.py +++ b/nw/gui/mainmenu.py @@ -54,10 +54,11 @@ class GuiMainMenu(QMenuBar): def setAvailableRoot(self): for itemClass in nwItemClass: - if itemClass != nwItemClass.NO_CLASS: - self.rootItems[itemClass].setEnabled( - self.theProject.checkRootUnique(itemClass) - ) + if itemClass == nwItemClass.NO_CLASS: continue + if itemClass == nwItemClass.TRASH: continue + self.rootItems[itemClass].setEnabled( + self.theProject.checkRootUnique(itemClass) + ) return def updateRecentProjects(self): @@ -186,6 +187,7 @@ class GuiMainMenu(QMenuBar): menuItem = QAction(QIcon.fromTheme("edit-delete"), "&Delete Item", self) menuItem.setStatusTip("Delete Selected Item") menuItem.setShortcut("Ctrl+Del") + menuItem.triggered.connect(self.theParent.treeView.deleteItem) self.projMenu.addAction(menuItem) # Project > Separator diff --git a/nw/project/project.py b/nw/project/project.py index 1a6b15ec..cbaa0327 100644 --- a/nw/project/project.py +++ b/nw/project/project.py @@ -38,6 +38,7 @@ class NWProject(): self.projTree = None self.treeOrder = None self.treeRoots = None + self.trashRoot = None self.projPath = None self.projFile = None self.projName = None @@ -52,7 +53,7 @@ class NWProject(): return ## - # Add Entries + # Item Methods ## def newRoot(self, rootName, rootClass): @@ -83,6 +84,18 @@ class NWProject(): self._appendItem(None,pHandle,newItem) return newItem.itemHandle + def addTrash(self): + newItem = NWItem() + newItem.setName("Trash") + newItem.setType(nwItemType.TRASH) + newItem.setClass(nwItemClass.TRASH) + self._appendItem(None,None,newItem) + return newItem.itemHandle + + ## + # Project Methods + ## + def newProject(self): self.clearProject() @@ -101,6 +114,7 @@ class NWProject(): self.projTree = {} self.treeOrder = [] self.treeRoots = [] + self.trashRoot = None self.projPath = None self.projFile = "nwProject.nwx" self.projName = "" @@ -119,10 +133,6 @@ class NWProject(): return - ## - # File I/O - ## - def openProject(self, fileName): if not path.isfile(fileName): @@ -390,6 +400,13 @@ class NWProject(): logger.verbose("Entry %s is a root item" % str(tHandle)) self.treeRoots.append(tHandle) + if nwItem.itemType == nwItemType.TRASH: + if self.trashRoot is None: + logger.verbose("Entry %s is the trash folder" % str(tHandle)) + self.trashRoot = tHandle + else: + logger.error("Only one trash folder allowed") + itemDepth = self.countItemDepth(tHandle) if itemDepth is None: logger.error("The depth of entry %s could not be determined" % tHandle)