Can now restore document label for orphaned files
This commit is contained in:
@@ -77,6 +77,20 @@ def checkBool(checkValue, defaultValue, allowNone=False):
|
|||||||
return defaultValue
|
return defaultValue
|
||||||
return defaultValue
|
return defaultValue
|
||||||
|
|
||||||
|
def isHandle(theString):
|
||||||
|
"""Check if a string is a valid novelWriter handle.
|
||||||
|
Note: This is case sensitive. Must be lower case!
|
||||||
|
"""
|
||||||
|
if not isinstance(theString, str):
|
||||||
|
return False
|
||||||
|
if len(theString) != 13:
|
||||||
|
return False
|
||||||
|
invalidChar = False
|
||||||
|
for c in theString:
|
||||||
|
if c not in "0123456789abcdef":
|
||||||
|
invalidChar = True
|
||||||
|
return not invalidChar
|
||||||
|
|
||||||
def colRange(rgbStart, rgbEnd, nStep):
|
def colRange(rgbStart, rgbEnd, nStep):
|
||||||
|
|
||||||
if len(rgbStart) != 3 and len(rgbEnd) != 3 and nStep < 1:
|
if len(rgbStart) != 3 and len(rgbEnd) != 3 and nStep < 1:
|
||||||
@@ -127,6 +141,9 @@ def formatInt(theInt):
|
|||||||
return "%d" % theInt
|
return "%d" % theInt
|
||||||
|
|
||||||
def formatTimeStamp(theTime, fileSafe=False):
|
def formatTimeStamp(theTime, fileSafe=False):
|
||||||
|
"""Take a number (on the format returned by time.time()) and convert
|
||||||
|
it to a timestamp string.
|
||||||
|
"""
|
||||||
if fileSafe:
|
if fileSafe:
|
||||||
return datetime.fromtimestamp(theTime).strftime(nwConst.fStampFmt)
|
return datetime.fromtimestamp(theTime).strftime(nwConst.fStampFmt)
|
||||||
else:
|
else:
|
||||||
|
|||||||
+52
-11
@@ -31,6 +31,7 @@ import nw
|
|||||||
from os import path, mkdir, rename, unlink
|
from os import path, mkdir, rename, unlink
|
||||||
|
|
||||||
from nw.constants import nwAlert
|
from nw.constants import nwAlert
|
||||||
|
from nw.common import isHandle
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -68,25 +69,29 @@ class NWDoc():
|
|||||||
self.docMeta = ""
|
self.docMeta = ""
|
||||||
return
|
return
|
||||||
|
|
||||||
def openDocument(self, tHandle, showStatus=True):
|
def openDocument(self, tHandle, showStatus=True, isOrphan=False):
|
||||||
"""Open a document from handle, capturing potential file system
|
"""Open a document from handle, capturing potential file system
|
||||||
errors and parse meta data.
|
errors and parse meta data.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.docHandle = tHandle
|
self.docHandle = tHandle
|
||||||
self.theItem = self.theProject.projTree[tHandle]
|
if not isOrphan:
|
||||||
|
self.theItem = self.theProject.projTree[tHandle]
|
||||||
|
else:
|
||||||
|
self.theItem = None
|
||||||
|
|
||||||
if self.theItem is None:
|
if self.theItem is None and not isOrphan:
|
||||||
self.clearDocument()
|
self.clearDocument()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# By default, the document is editable.
|
# By default, the document is editable.
|
||||||
# Except for files in the trash folder.
|
# Except for files in the trash folder.
|
||||||
self.docEditable = True
|
self.docEditable = True
|
||||||
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
|
if self.theItem is not None:
|
||||||
self.docEditable = False
|
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
|
||||||
|
self.docEditable = False
|
||||||
|
|
||||||
docDir, docFile = self.assemblePath(self.docHandle, self.FILE_MN)
|
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
|
||||||
self.fileLoc = path.join(docDir,docFile)
|
self.fileLoc = path.join(docDir,docFile)
|
||||||
logger.debug("Opening document %s" % self.fileLoc)
|
logger.debug("Opening document %s" % self.fileLoc)
|
||||||
dataDir = path.join(self.theProject.projPath, docDir)
|
dataDir = path.join(self.theProject.projPath, docDir)
|
||||||
@@ -100,7 +105,7 @@ class NWDoc():
|
|||||||
fstLine = inFile.readline()
|
fstLine = inFile.readline()
|
||||||
if fstLine.startswith("%%~ "):
|
if fstLine.startswith("%%~ "):
|
||||||
# This is the meta line
|
# This is the meta line
|
||||||
self.docMeta = fstLine.strip()
|
self.docMeta = fstLine[4:].strip()
|
||||||
else:
|
else:
|
||||||
theText = fstLine
|
theText = fstLine
|
||||||
theText += inFile.read()
|
theText += inFile.read()
|
||||||
@@ -120,7 +125,7 @@ class NWDoc():
|
|||||||
|
|
||||||
logger.verbose("DocMeta: '%s'" % self.docMeta)
|
logger.verbose("DocMeta: '%s'" % self.docMeta)
|
||||||
|
|
||||||
if showStatus:
|
if showStatus and not isOrphan:
|
||||||
self.theParent.statusBar.setStatus("Opened Document: %s" % self.theItem.itemName)
|
self.theParent.statusBar.setStatus("Opened Document: %s" % self.theItem.itemName)
|
||||||
|
|
||||||
return theText
|
return theText
|
||||||
@@ -133,7 +138,7 @@ class NWDoc():
|
|||||||
if self.docHandle is None or not self.docEditable:
|
if self.docHandle is None or not self.docEditable:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
docDir, docFile = self.assemblePath(self.docHandle, self.FILE_MN)
|
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
|
||||||
logger.debug("Saving document %s" % path.join(docDir,docFile))
|
logger.debug("Saving document %s" % path.join(docDir,docFile))
|
||||||
dataPath = path.join(self.theProject.projPath, docDir)
|
dataPath = path.join(self.theProject.projPath, docDir)
|
||||||
docPath = path.join(dataPath, docFile)
|
docPath = path.join(dataPath, docFile)
|
||||||
@@ -171,7 +176,7 @@ class NWDoc():
|
|||||||
"""Permanently delete a document source file and its backups
|
"""Permanently delete a document source file and its backups
|
||||||
from the project data folder.
|
from the project data folder.
|
||||||
"""
|
"""
|
||||||
docDir, docFile = self.assemblePath(tHandle, self.FILE_MN)
|
docDir, docFile = self._assemblePath(tHandle, self.FILE_MN)
|
||||||
dataPath = path.join(self.theProject.projPath, docDir)
|
dataPath = path.join(self.theProject.projPath, docDir)
|
||||||
chkList = []
|
chkList = []
|
||||||
chkList.append(path.join(dataPath, docFile))
|
chkList.append(path.join(dataPath, docFile))
|
||||||
@@ -187,8 +192,44 @@ class NWDoc():
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
##
|
||||||
|
# Getters
|
||||||
|
##
|
||||||
|
|
||||||
|
def getMeta(self):
|
||||||
|
"""Parses the document meta tag and returns the path and name as
|
||||||
|
a list and a string.
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(self.docMeta) < 14:
|
||||||
|
# Not enough information
|
||||||
|
return "", []
|
||||||
|
|
||||||
|
theMeta = self.docMeta
|
||||||
|
|
||||||
|
# Scan for handles
|
||||||
|
thePath = []
|
||||||
|
for n in range(200):
|
||||||
|
if len(theMeta) < 14:
|
||||||
|
break
|
||||||
|
if theMeta[13] == ":":
|
||||||
|
theHandle = theMeta[:13]
|
||||||
|
if isHandle(theHandle):
|
||||||
|
thePath.append(theHandle)
|
||||||
|
theMeta = theMeta[14:]
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
return theMeta, thePath
|
||||||
|
|
||||||
|
##
|
||||||
|
# Internal Functions
|
||||||
|
##
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def assemblePath(tHandle, docExt):
|
def _assemblePath(tHandle, docExt):
|
||||||
if tHandle is None:
|
if tHandle is None:
|
||||||
return None, None
|
return None, None
|
||||||
docDir = "data_"+tHandle[0]
|
docDir = "data_"+tHandle[0]
|
||||||
|
|||||||
+12
-2
@@ -41,6 +41,7 @@ from shutil import make_archive
|
|||||||
|
|
||||||
from nw.gui.tools import OptionState
|
from nw.gui.tools import OptionState
|
||||||
from nw.core.tools import projectMaintenance
|
from nw.core.tools import projectMaintenance
|
||||||
|
from nw.core.document import NWDoc
|
||||||
from nw.common import checkString, checkBool, checkInt, formatTimeStamp
|
from nw.common import checkString, checkBool, checkInt, formatTimeStamp
|
||||||
from nw.constants import (
|
from nw.constants import (
|
||||||
nwFiles, nwConst, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
nwFiles, nwConst, nwItemType, nwItemClass, nwItemLayout, nwAlert
|
||||||
@@ -913,11 +914,20 @@ class NWProject():
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Handle orphans
|
# Handle orphans
|
||||||
|
aDoc = NWDoc(self, self.theParent)
|
||||||
nOrph = 0
|
nOrph = 0
|
||||||
for oHandle in orphanFiles:
|
for oHandle in orphanFiles:
|
||||||
nOrph += 1
|
|
||||||
|
# Look for meta data
|
||||||
|
if aDoc.openDocument(oHandle, showStatus=False, isOrphan=True):
|
||||||
|
oName, oPath = aDoc.getMeta()
|
||||||
|
aDoc.clearDocument()
|
||||||
|
else:
|
||||||
|
nOrph += 1
|
||||||
|
oName = "Orphaned File %d" % nOrph
|
||||||
|
|
||||||
orphItem = NWItem(self)
|
orphItem = NWItem(self)
|
||||||
orphItem.setName("Orphaned File %d" % nOrph)
|
orphItem.setName(oName)
|
||||||
orphItem.setType(nwItemType.FILE)
|
orphItem.setType(nwItemType.FILE)
|
||||||
orphItem.setClass(nwItemClass.NO_CLASS)
|
orphItem.setClass(nwItemClass.NO_CLASS)
|
||||||
orphItem.setLayout(nwItemLayout.NO_LAYOUT)
|
orphItem.setLayout(nwItemLayout.NO_LAYOUT)
|
||||||
|
|||||||
+1
-1
@@ -404,7 +404,7 @@ class GuiMain(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# project is loaded
|
# Project is loaded
|
||||||
self.hasProject = True
|
self.hasProject = True
|
||||||
|
|
||||||
# Load the tag index
|
# Load the tag index
|
||||||
|
|||||||
Reference in New Issue
Block a user