Changed the data structure of the project folder
This commit is contained in:
+8
-25
@@ -93,8 +93,9 @@ class NWDoc():
|
|||||||
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
|
if self.theItem.parHandle == self.theProject.projTree.trashRoot():
|
||||||
self.docEditable = False
|
self.docEditable = False
|
||||||
|
|
||||||
docDir, docFile = self._assemblePath(self.docHandle, self.FILE_MN)
|
docDir = "content"
|
||||||
self.fileLoc = path.join(docDir,docFile)
|
docFile = self.docHandle+".nwd"
|
||||||
|
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)
|
||||||
docPath = path.join(dataDir, docFile)
|
docPath = path.join(dataDir, docFile)
|
||||||
@@ -139,8 +140,9 @@ 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 = "content"
|
||||||
logger.debug("Saving document %s" % path.join(docDir,docFile))
|
docFile = self.docHandle+".nwd"
|
||||||
|
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)
|
||||||
if not path.isdir(dataPath):
|
if not path.isdir(dataPath):
|
||||||
@@ -159,12 +161,6 @@ class NWDoc():
|
|||||||
self.makeAlert(["Could not save document.",str(e)], nwAlert.ERROR)
|
self.makeAlert(["Could not save document.",str(e)], nwAlert.ERROR)
|
||||||
return False
|
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
|
# If we're here, the file was successfully saved, so we can
|
||||||
# replace the temp file with the actual file
|
# replace the temp file with the actual file
|
||||||
if path.isfile(docPath):
|
if path.isfile(docPath):
|
||||||
@@ -179,7 +175,8 @@ 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 = "content"
|
||||||
|
docFile = self.docHandle+".nwd"
|
||||||
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))
|
||||||
@@ -226,18 +223,4 @@ class NWDoc():
|
|||||||
|
|
||||||
return theMeta, thePath
|
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
|
# END Class NWDoc
|
||||||
|
|||||||
+95
-7
@@ -33,7 +33,7 @@
|
|||||||
import logging
|
import logging
|
||||||
import nw
|
import nw
|
||||||
|
|
||||||
from os import path, mkdir, listdir, unlink, rename
|
from os import path, mkdir, listdir, unlink, rename, rmdir
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from hashlib import sha256
|
from hashlib import sha256
|
||||||
from time import time
|
from time import time
|
||||||
@@ -74,6 +74,7 @@ class NWProject():
|
|||||||
# Class Settings
|
# Class Settings
|
||||||
self.projPath = None # The full path to where the currently open project is saved
|
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.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.projDict = None # The spell check dictionary
|
||||||
self.projFile = None # The file name of the project main XML file
|
self.projFile = None # The file name of the project main XML file
|
||||||
|
|
||||||
@@ -195,6 +196,7 @@ class NWProject():
|
|||||||
# Project Settings
|
# Project Settings
|
||||||
self.projPath = None
|
self.projPath = None
|
||||||
self.projMeta = None
|
self.projMeta = None
|
||||||
|
self.projData = None
|
||||||
self.projDict = None
|
self.projDict = None
|
||||||
self.projFile = nwFiles.PROJ_FILE
|
self.projFile = nwFiles.PROJ_FILE
|
||||||
self.projName = ""
|
self.projName = ""
|
||||||
@@ -247,10 +249,13 @@ class NWProject():
|
|||||||
logger.debug("Opening project: %s" % self.projPath)
|
logger.debug("Opening project: %s" % self.projPath)
|
||||||
|
|
||||||
self.projMeta = path.join(self.projPath,"meta")
|
self.projMeta = path.join(self.projPath,"meta")
|
||||||
|
self.projData = path.join(self.projPath,"content")
|
||||||
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
|
self.projDict = path.join(self.projMeta, nwFiles.PROJ_DICT)
|
||||||
|
|
||||||
if not self._checkFolder(self.projMeta):
|
if not self._checkFolder(self.projMeta):
|
||||||
return False
|
return False
|
||||||
|
if not self._checkFolder(self.projData):
|
||||||
|
return False
|
||||||
|
|
||||||
if overrideLock:
|
if overrideLock:
|
||||||
self._clearLockFile()
|
self._clearLockFile()
|
||||||
@@ -291,7 +296,7 @@ class NWProject():
|
|||||||
self.clearProject()
|
self.clearProject()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
xRoot = nwXML.getroot()
|
xRoot = nwXML.getroot()
|
||||||
nwxRoot = xRoot.tag
|
nwxRoot = xRoot.tag
|
||||||
|
|
||||||
appVersion = "Unknown"
|
appVersion = "Unknown"
|
||||||
@@ -314,13 +319,40 @@ class NWProject():
|
|||||||
logger.verbose("XML root is %s" % nwxRoot)
|
logger.verbose("XML root is %s" % nwxRoot)
|
||||||
logger.verbose("File version is %s" % fileVersion)
|
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(
|
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
|
nwAlert.ERROR
|
||||||
)
|
)
|
||||||
return False
|
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:
|
if int(hexVersion, 16) > int(nw.__hexversion__, 16) and self.mainConf.showGUI:
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
msgRes = msgBox.question(self.theParent, "Version Conflict", (
|
||||||
@@ -333,6 +365,8 @@ class NWProject():
|
|||||||
if msgRes != QMessageBox.Yes:
|
if msgRes != QMessageBox.Yes:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Start Parsing XML
|
||||||
|
# =================
|
||||||
for xChild in xRoot:
|
for xChild in xRoot:
|
||||||
if xChild.tag == "project":
|
if xChild.tag == "project":
|
||||||
logger.debug("Found project meta")
|
logger.debug("Found project meta")
|
||||||
@@ -404,16 +438,21 @@ class NWProject():
|
|||||||
file.
|
file.
|
||||||
"""
|
"""
|
||||||
if self.projPath is None:
|
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
|
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()
|
saveTime = time()
|
||||||
|
|
||||||
if not self._checkFolder(self.projPath):
|
if not self._checkFolder(self.projPath):
|
||||||
return False
|
return False
|
||||||
if not self._checkFolder(self.projMeta):
|
if not self._checkFolder(self.projMeta):
|
||||||
return False
|
return False
|
||||||
|
if not self._checkFolder(self.projData):
|
||||||
|
return False
|
||||||
|
|
||||||
logger.debug("Saving project: %s" % self.projPath)
|
logger.debug("Saving project: %s" % self.projPath)
|
||||||
|
|
||||||
@@ -427,7 +466,7 @@ class NWProject():
|
|||||||
nwXML = etree.Element("novelWriterXML",attrib={
|
nwXML = etree.Element("novelWriterXML",attrib={
|
||||||
"appVersion" : str(nw.__version__),
|
"appVersion" : str(nw.__version__),
|
||||||
"hexVersion" : str(nw.__hexversion__),
|
"hexVersion" : str(nw.__hexversion__),
|
||||||
"fileVersion" : "1.0",
|
"fileVersion" : "1.1",
|
||||||
"saveCount" : str(self.saveCount),
|
"saveCount" : str(self.saveCount),
|
||||||
"autoCount" : str(self.autoCount),
|
"autoCount" : str(self.autoCount),
|
||||||
"timeStamp" : formatTimeStamp(saveTime),
|
"timeStamp" : formatTimeStamp(saveTime),
|
||||||
@@ -1016,6 +1055,55 @@ class NWProject():
|
|||||||
|
|
||||||
return True
|
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
|
# END Class NWProject
|
||||||
|
|
||||||
# ================================================================================================ #
|
# ================================================================================================ #
|
||||||
|
|||||||
+1
-6
@@ -89,7 +89,7 @@ def projectMaintenance(theProject):
|
|||||||
if path.isdir(theProject.projPath):
|
if path.isdir(theProject.projPath):
|
||||||
cacheDir = path.join(theProject.projPath, "cache")
|
cacheDir = path.join(theProject.projPath, "cache")
|
||||||
if path.isdir(cacheDir):
|
if path.isdir(cacheDir):
|
||||||
logger.info("Deprecated cache folder found")
|
logger.info("Deprecated cache folder content found")
|
||||||
rmList = []
|
rmList = []
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
|
rmList.append(path.join(cacheDir, "nwProject.nwx.%d" % i))
|
||||||
@@ -101,11 +101,6 @@ def projectMaintenance(theProject):
|
|||||||
unlink(rmFile)
|
unlink(rmFile)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(str(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
|
# Remove no longer used meta files
|
||||||
rmList = []
|
rmList = []
|
||||||
|
|||||||
Reference in New Issue
Block a user