Changed the data structure of the project folder

This commit is contained in:
Veronica K. B. Olsen
2020-05-28 18:55:44 +02:00
parent 604aa84987
commit 192427deaa
3 changed files with 104 additions and 38 deletions
+8 -25
View File
@@ -93,8 +93,9 @@ class NWDoc():
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
self.docEditable = False
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
self.fileLoc = path.join(docDir,docFile)
docDir = "content"
docFile = self.docHandle+".nwd"
self.fileLoc = path.join(docDir, docFile)
logger.debug("Opening document %s" % self.fileLoc)
dataDir = path.join(self.theProject.projPath, docDir)
docPath = path.join(dataDir, docFile)
@@ -139,8 +140,9 @@ class NWDoc():
if self.docHandle is None or not self.docEditable:
return False
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
logger.debug("Saving document %s" % path.join(docDir,docFile))
docDir = "content"
docFile = self.docHandle+".nwd"
logger.debug("Saving document %s" % path.join(docDir, docFile))
dataPath = path.join(self.theProject.projPath, docDir)
docPath = path.join(dataPath, docFile)
if not path.isdir(dataPath):
@@ -159,12 +161,6 @@ class NWDoc():
self.makeAlert(["Could not save document.",str(e)], nwAlert.ERROR)
return False
# Remove bak files from old file save method, if one exists
# This part can eventually be removed
docBack = path.join(dataPath, docFile[:-3]+"bak")
if path.isfile(docBack):
unlink(docBack)
# If we're here, the file was successfully saved, so we can
# replace the temp file with the actual file
if path.isfile(docPath):
@@ -179,7 +175,8 @@ class NWDoc():
"""Permanently delete a document source file and its backups
from the project data folder.
"""
docDir, docFile = self._assemblePath(tHandle, self.FILE_MN)
docDir = "content"
docFile = self.docHandle+".nwd"
dataPath = path.join(self.theProject.projPath, docDir)
chkList = []
chkList.append(path.join(dataPath, docFile))
@@ -226,18 +223,4 @@ class NWDoc():
return theMeta, thePath
##
# Internal Functions
##
@staticmethod
def _assemblePath(tHandle, docExt):
"""Assemble the file path for a given handle.
"""
if tHandle is None:
return None, None
docDir = "data_"+tHandle[0]
docFile = tHandle[1:13]+"_"+docExt
return docDir, docFile
# END Class NWDoc
+95 -7
View File
@@ -33,7 +33,7 @@
import logging
import nw
from os import path, mkdir, listdir, unlink, rename
from os import path, mkdir, listdir, unlink, rename, rmdir
from lxml import etree
from hashlib import sha256
from time import time
@@ -74,6 +74,7 @@ class NWProject():
# Class Settings
self.projPath = None # The full path to where the currently open project is saved
self.projMeta = None # The full path to the project's meta data folder
self.projData = None # The full path to the project's data folder
self.projDict = None # The spell check dictionary
self.projFile = None # The file name of the project main XML file
@@ -195,6 +196,7 @@ class NWProject():
# Project Settings
self.projPath = None
self.projMeta = None
self.projData = None
self.projDict = None
self.projFile = nwFiles.PROJ_FILE
self.projName = ""
@@ -247,10 +249,13 @@ class NWProject():
logger.debug("Opening project: %s" % self.projPath)
self.projMeta = path.join(self.projPath,"meta")
self.projData = path.join(self.projPath,"content")
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
if not self._checkFolder(self.projMeta):
return False
if not self._checkFolder(self.projData):
return False
if overrideLock:
self._clearLockFile()
@@ -291,7 +296,7 @@ class NWProject():
self.clearProject()
return False
xRoot = nwXML.getroot()
xRoot = nwXML.getroot()
nwxRoot = xRoot.tag
appVersion = "Unknown"
@@ -314,13 +319,40 @@ class NWProject():
logger.verbose("XML root is %s" % nwxRoot)
logger.verbose("File version is %s" % fileVersion)
if not nwxRoot == "novelWriterXML" or not fileVersion == "1.0":
# Check File Type
# ===============
if not nwxRoot == "novelWriterXML":
self.makeAlert(
"Project file does not appear to be a novelWriterXML file version 1.0",
"Project file does not appear to be a novelWriterXML file.",
nwAlert.ERROR
)
return False
# Check Project Storage Version
# =============================
if fileVersion == "1.0":
msgBox = QMessageBox()
msgRes = msgBox.question(self.theParent, "Old Project Version", (
"The project file and data is created by a %s version lower than 0.7. "
"Do you want to upgrade the project to the most recent format?<br><br>"
"Note that after the upgrade, you cannot open the project with an older "
"version of novelWriter any more, so make sure you have a recent backup."
) % nw.__package__)
if msgRes == QMessageBox.Yes:
self._updateStorage()
else:
return False
elif fileVersion != "1.1":
self.makeAlert((
"Unknown or unsupported %s project format. "
"The project cannot be opened by this version of %s."
) % (
nw.__package__, nw.__package__
), nwAlert.ERROR)
return False
# Check novelWriter Version
# =========================
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI:
msgBox = QMessageBox()
msgRes = msgBox.question(self.theParent, "Version Conflict", (
@@ -333,6 +365,8 @@ class NWProject():
if msgRes != QMessageBox.Yes:
return False
# Start Parsing XML
# =================
for xChild in xRoot:
if xChild.tag == "project":
logger.debug("Found project meta")
@@ -404,16 +438,21 @@ class NWProject():
file.
"""
if self.projPath is None:
self.makeAlert("Project path not set, cannot save.", nwAlert.ERROR)
self.makeAlert(
"Project path not set, cannot save project.", nwAlert.ERROR
)
return False
self.projMeta = path.join(self.projPath,"meta")
self.projMeta = path.join(self.projPath, "meta")
self.projData = path.join(self.projPath, "content")
saveTime = time()
if not self._checkFolder(self.projPath):
return False
if not self._checkFolder(self.projMeta):
return False
if not self._checkFolder(self.projData):
return False
logger.debug("Saving project: %s" % self.projPath)
@@ -427,7 +466,7 @@ class NWProject():
nwXML = etree.Element("novelWriterXML",attrib={
"appVersion" : str(nw.__version__),
"hexVersion" : str(nw.__hexversion__),
"fileVersion" : "1.0",
"fileVersion" : "1.1",
"saveCount" : str(self.saveCount),
"autoCount" : str(self.autoCount),
"timeStamp" : formatTimeStamp(saveTime),
@@ -1016,6 +1055,55 @@ class NWProject():
return True
def _updateStorage(self):
"""Updates the project storage folder from 1.0 to 1.1.
"""
contDir = path.join(self.projPath, "content")
self._checkFolder(contDir)
errList = []
for projItem in listdir(self.projPath):
itemPath = path.join(self.projPath, projItem)
if not path.isdir(itemPath) or not projItem.startswith("data_"):
continue
for dataFile in listdir(itemPath):
dataPath = path.join(itemPath, dataFile)
if dataFile.endswith(".bak"):
try:
unlink(dataPath)
logger.info("Deleted file: %s" % dataPath)
except:
errList.append("Failed to delete: %s" % dataPath)
elif dataFile.endswith(".nwd") and len(dataFile) == 21:
tHandle = projItem[-1]+dataFile[:12]
newPath = path.join(contDir, tHandle+".nwd")
try:
rename(dataPath, newPath)
logger.info("Moved file: %s" % dataPath)
logger.info("New location: %s" % newPath)
except:
errList.append("Failed to move: %s" % dataPath)
else:
newPath = path.join(self.projPath, "unknown_"+dataFile)
try:
rename(dataPath, newPath)
logger.info("Moved file: %s" % dataPath)
logger.info("New location: %s" % newPath)
except:
errList.append("Failed to move: %s" % dataPath)
try:
rmdir(itemPath)
logger.info("Removed folder: %s" % itemPath)
except:
errList.append("Failed to delete: %s" % itemPath)
if errList:
self.makeAlert(errList, nwAlert.ERROR)
return
# END Class NWProject
# ================================================================================================ #
+1 -6
View File
@@ -89,7 +89,7 @@ def projectMaintenance(theProject):
if path.isdir(theProject.projPath):
cacheDir = path.join(theProject.projPath, "cache")
if path.isdir(cacheDir):
logger.info("Deprecated cache folder found")
logger.info("Deprecated cache folder content found")
rmList = []
for i in range(10):
rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
@@ -101,11 +101,6 @@ def projectMaintenance(theProject):
unlink(rmFile)
except Exception as e:
logger.error(str(e))
logger.info("Deleting: %s" % cacheDir)
try:
rmdir(cacheDir)
except Exception as e:
logger.error(str(e))
# Remove no longer used meta files
rmList = []