Added handling of orphaned documents.
This commit is contained in:
+13
-10
@@ -64,17 +64,20 @@ class GuiDocDetails(QFrame):
|
||||
|
||||
def buildViewBox(self, tHandle):
|
||||
|
||||
nwItem = self.theProject.getItem(tHandle)
|
||||
itemStatus = nwItem.itemStatus
|
||||
if itemStatus < 0 or itemStatus >= len(self.theProject.statusLabels):
|
||||
itemStatus = 0
|
||||
nwItem = self.theProject.getItem(tHandle)
|
||||
|
||||
colTwo = [
|
||||
nwItem.itemName,
|
||||
self.theProject.statusLabels[itemStatus],
|
||||
nwLabels.CLASS_NAME[nwItem.itemClass],
|
||||
nwLabels.LAYOUT_NAME[nwItem.itemLayout],
|
||||
]
|
||||
if nwItem is None:
|
||||
colTwo = [""]*4
|
||||
else:
|
||||
itemStatus = nwItem.itemStatus
|
||||
if itemStatus < 0 or itemStatus >= len(self.theProject.statusLabels):
|
||||
itemStatus = 0
|
||||
colTwo = [
|
||||
nwItem.itemName,
|
||||
self.theProject.statusLabels[itemStatus],
|
||||
nwLabels.CLASS_NAME[nwItem.itemClass],
|
||||
nwLabels.LAYOUT_NAME[nwItem.itemLayout],
|
||||
]
|
||||
|
||||
for nRow in range(4):
|
||||
lblTwo = QLabel(colTwo[nRow])
|
||||
|
||||
+26
-6
@@ -40,6 +40,7 @@ class GuiDocTree(QTreeWidget):
|
||||
self.theParent = theParent
|
||||
self.theProject = theProject
|
||||
self.theMap = {}
|
||||
self.orphRoot = None
|
||||
|
||||
self.setIconSize(QSize(13,13))
|
||||
self.setExpandsOnDoubleClick(True)
|
||||
@@ -152,6 +153,8 @@ class GuiDocTree(QTreeWidget):
|
||||
def saveTreeOrder(self):
|
||||
theList = []
|
||||
for i in range(self.topLevelItemCount()):
|
||||
if self.topLevelItem(i) == self.orphRoot:
|
||||
continue
|
||||
theList = self._scanChildren(theList, self.topLevelItem(i), i)
|
||||
self.theProject.setTreeOrder(theList)
|
||||
return True
|
||||
@@ -200,7 +203,12 @@ class GuiDocTree(QTreeWidget):
|
||||
|
||||
self.theMap[tHandle] = newItem
|
||||
if pHandle is None:
|
||||
self.addTopLevelItem(newItem)
|
||||
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)
|
||||
@@ -210,7 +218,6 @@ class GuiDocTree(QTreeWidget):
|
||||
|
||||
if nwItem.itemType == nwItemType.ROOT:
|
||||
newItem.setIcon(self.C_NAME, QIcon.fromTheme("drive-harddisk"))
|
||||
self.theParent.mainMenu.setAvailableRoot()
|
||||
elif nwItem.itemType == nwItemType.FOLDER:
|
||||
newItem.setIcon(self.C_NAME, QIcon.fromTheme("folder"))
|
||||
elif nwItem.itemType == nwItemType.FILE:
|
||||
@@ -218,6 +225,18 @@ class GuiDocTree(QTreeWidget):
|
||||
|
||||
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 setTreeItemValues(self, tHandle):
|
||||
|
||||
trItem = self.theMap[tHandle]
|
||||
@@ -248,7 +267,7 @@ class GuiDocTree(QTreeWidget):
|
||||
for i in range(pItem.childCount()):
|
||||
pCount += int(pItem.child(i).text(self.C_COUNT))
|
||||
pHandle = pItem.text(self.C_HANDLE)
|
||||
if not nDepth > NWItem.MAX_DEPTH:
|
||||
if not nDepth > NWItem.MAX_DEPTH and pHandle != "":
|
||||
self.propagateCount(pHandle, pCount, nDepth+1)
|
||||
return
|
||||
|
||||
@@ -298,14 +317,15 @@ class GuiDocTree(QTreeWidget):
|
||||
snItem = self.theProject.getItem(sHandle)
|
||||
dnItem = self.theProject.getItem(dHandle)
|
||||
isSame = snItem.itemClass == dnItem.itemClass and dnItem.itemType
|
||||
isNone = snItem.itemClass == nwItemClass.NO_CLASS
|
||||
isFile = dnItem.itemType == nwItemType.FILE
|
||||
isRoot = snItem.itemType == nwItemType.ROOT
|
||||
isOnTop = self.dropIndicatorPosition() == QAbstractItemView.OnItem
|
||||
if isSame and not (isFile and isOnTop) and not isRoot:
|
||||
logger.verbose("Drag'n'drop on item %s allowed" % sHandle)
|
||||
if (isSame or isNone) and not (isFile and isOnTop) and not isRoot:
|
||||
logger.verbose("Drag'n'drop of item %s accepted" % sHandle)
|
||||
QTreeWidget.dropEvent(self, theEvent)
|
||||
else:
|
||||
logger.verbose("Drag'n'drop on item %s not allowed" % sHandle)
|
||||
logger.verbose("Drag'n'drop of item %s not accepted" % sHandle)
|
||||
|
||||
return
|
||||
|
||||
|
||||
+53
-1
@@ -13,7 +13,7 @@
|
||||
import logging
|
||||
import nw
|
||||
|
||||
from os import path, mkdir
|
||||
from os import path, mkdir, listdir
|
||||
from lxml import etree
|
||||
from hashlib import sha256
|
||||
from datetime import datetime
|
||||
@@ -167,6 +167,8 @@ class NWProject():
|
||||
self._makeStatusIcons()
|
||||
self.mainConf.setRecent(self.projPath)
|
||||
|
||||
self._scanProjectFolder()
|
||||
|
||||
return True
|
||||
|
||||
def saveProject(self):
|
||||
@@ -287,6 +289,56 @@ class NWProject():
|
||||
# Internal Functions
|
||||
##
|
||||
|
||||
def _scanProjectFolder(self):
|
||||
|
||||
if self.projPath is None:
|
||||
return
|
||||
|
||||
# First, scan the project data folders
|
||||
itemList = []
|
||||
for subItem in listdir(self.projPath):
|
||||
if subItem[:5] != "data_":
|
||||
continue
|
||||
dataDir = path.join(self.projPath,subItem)
|
||||
for subFile in listdir(dataDir):
|
||||
if subFile[-4:] == ".nwd":
|
||||
newItem = path.join(subItem,subFile)
|
||||
itemList.append(newItem)
|
||||
|
||||
# Then check the valid files
|
||||
orphanFiles = []
|
||||
for fileItem in itemList:
|
||||
if len(fileItem) != 28:
|
||||
# Just to be safe, shouldn't happen
|
||||
logger.warning("Skipping file %s" % fileItem)
|
||||
continue
|
||||
fHandle = fileItem[5]+fileItem[7:19]
|
||||
if fHandle in self.treeOrder:
|
||||
logger.verbose("Checking file %s, handle %s: OK" % (fileItem,fHandle))
|
||||
else:
|
||||
logger.verbose("Checking file %s, handle %s: Orphaned" % (fileItem,fHandle))
|
||||
orphanFiles.append(fHandle)
|
||||
|
||||
# Report status
|
||||
if len(orphanFiles) > 0:
|
||||
logger.warning("Found %d orphaned file(s) in project folder!" % len(orphanFiles))
|
||||
else:
|
||||
logger.verbose("File check OK")
|
||||
return
|
||||
|
||||
# Handle orphans
|
||||
nOrph = 0
|
||||
for oHandle in orphanFiles:
|
||||
nOrph += 1
|
||||
orItem = NWItem()
|
||||
orItem.setName("Orphaned File %d" % nOrph)
|
||||
orItem.setType(nwItemType.FILE)
|
||||
orItem.setClass(nwItemClass.NO_CLASS)
|
||||
orItem.setLayout(nwItemLayout.NO_LAYOUT)
|
||||
self._appendItem(oHandle,None,orItem)
|
||||
|
||||
return
|
||||
|
||||
def _countItemDepth(self, tHandle):
|
||||
theDepth = 0
|
||||
nwItem = self.getItem(tHandle)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# John Smith
|
||||
|
||||
He’s pretty cool. Nor Brad Pitt though.
|
||||
He’s pretty cool. Not Brad Pitt though.
|
||||
@@ -0,0 +1,4 @@
|
||||
# My Novel
|
||||
|
||||
**By Jane Doh**
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Earth
|
||||
|
||||
Third planet from the sun, fairly dense and with lots of people on it.
|
||||
Third planet from the sun, fairly dense, and with lots of people on it.
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<novelWriterXML appVersion="0.0.1" fileVersion="1.0" timeStamp="2019-04-28 13:15:28">
|
||||
<novelWriterXML appVersion="0.0.1" fileVersion="1.0" timeStamp="2019-04-28 14:03:05">
|
||||
<project>
|
||||
<name>Sample Project</name>
|
||||
<title>Sample Project</title>
|
||||
<author>Jane Smith</author>
|
||||
<author>Jay Doh</author>
|
||||
</project>
|
||||
<content count="9">
|
||||
<content count="10">
|
||||
<item handle="7031beac91f75" order="0" parent="None">
|
||||
<name>Novel</name>
|
||||
<type>ROOT</type>
|
||||
|
||||
Reference in New Issue
Block a user