Remove project content attribute from project class
This commit is contained in:
@@ -23,9 +23,10 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter.enum import nwItemLayout, nwItemClass
|
from novelwriter.enum import nwItemLayout, nwItemClass
|
||||||
from novelwriter.error import formatException
|
from novelwriter.error import formatException
|
||||||
from novelwriter.common import isHandle, sha256sum
|
from novelwriter.common import isHandle, sha256sum
|
||||||
@@ -73,7 +74,7 @@ class NWDoc:
|
|||||||
empty string. If something went wrong, return None.
|
empty string. If something went wrong, return None.
|
||||||
"""
|
"""
|
||||||
self._docError = ""
|
self._docError = ""
|
||||||
if self._docHandle is None:
|
if not isinstance(self._docHandle, str):
|
||||||
logger.error("No document handle set")
|
logger.error("No document handle set")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -81,17 +82,22 @@ class NWDoc:
|
|||||||
logger.error("Unknown novelWriter document")
|
logger.error("Unknown novelWriter document")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
contentPath = self.theProject.storage.contentPath
|
||||||
|
if not isinstance(contentPath, Path):
|
||||||
|
logger.error("No content path set")
|
||||||
|
return None
|
||||||
|
|
||||||
docFile = self._docHandle+".nwd"
|
docFile = self._docHandle+".nwd"
|
||||||
logger.debug("Opening document: %s", docFile)
|
logger.debug("Opening document: %s", docFile)
|
||||||
|
|
||||||
docPath = os.path.join(self.theProject.projContent, docFile)
|
docPath = contentPath / docFile
|
||||||
self._fileLoc = docPath
|
self._fileLoc = docPath
|
||||||
|
|
||||||
theText = ""
|
theText = ""
|
||||||
self._docMeta = {}
|
self._docMeta = {}
|
||||||
self._prevHash = None
|
self._prevHash = None
|
||||||
|
|
||||||
if os.path.isfile(docPath):
|
if docPath.exists():
|
||||||
self._prevHash = sha256sum(docPath)
|
self._prevHash = sha256sum(docPath)
|
||||||
try:
|
try:
|
||||||
with open(docPath, mode="r", encoding="utf-8") as inFile:
|
with open(docPath, mode="r", encoding="utf-8") as inFile:
|
||||||
@@ -125,17 +131,20 @@ class NWDoc:
|
|||||||
if not.
|
if not.
|
||||||
"""
|
"""
|
||||||
self._docError = ""
|
self._docError = ""
|
||||||
if self._docHandle is None:
|
if not isinstance(self._docHandle, str):
|
||||||
logger.error("No document handle set")
|
logger.error("No document handle set")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
self.theProject.ensureFolderStructure()
|
contentPath = self.theProject.storage.contentPath
|
||||||
|
if not isinstance(contentPath, Path):
|
||||||
|
logger.error("No content path set")
|
||||||
|
return None
|
||||||
|
|
||||||
docFile = self._docHandle+".nwd"
|
docFile = self._docHandle+".nwd"
|
||||||
logger.debug("Saving document: %s", docFile)
|
logger.debug("Saving document: %s", docFile)
|
||||||
|
|
||||||
docPath = os.path.join(self.theProject.projContent, docFile)
|
docPath = contentPath / docFile
|
||||||
docTemp = os.path.join(self.theProject.projContent, docFile+"~")
|
docTemp = docPath.with_suffix(".tmp")
|
||||||
|
|
||||||
if self._prevHash is not None and not forceWrite:
|
if self._prevHash is not None and not forceWrite:
|
||||||
self._currHash = sha256sum(docPath)
|
self._currHash = sha256sum(docPath)
|
||||||
@@ -164,7 +173,7 @@ class NWDoc:
|
|||||||
# 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
|
||||||
try:
|
try:
|
||||||
os.replace(docTemp, docPath)
|
docTemp.replace(docPath)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
self._docError = formatException(exc)
|
self._docError = formatException(exc)
|
||||||
return False
|
return False
|
||||||
@@ -179,23 +188,24 @@ class NWDoc:
|
|||||||
from the project data folder.
|
from the project data folder.
|
||||||
"""
|
"""
|
||||||
self._docError = ""
|
self._docError = ""
|
||||||
if self._docHandle is None:
|
if not isinstance(self._docHandle, str):
|
||||||
logger.error("No document handle set")
|
logger.error("No document handle set")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
chkList = [
|
contentPath = self.theProject.storage.contentPath
|
||||||
os.path.join(self.theProject.projContent, f"{self._docHandle}.nwd"),
|
if not isinstance(contentPath, Path):
|
||||||
os.path.join(self.theProject.projContent, f"{self._docHandle}.nwd~"),
|
logger.error("No content path set")
|
||||||
]
|
return None
|
||||||
|
|
||||||
for chkFile in chkList:
|
docPath = contentPath / f"{self._docHandle}.nwd"
|
||||||
if os.path.isfile(chkFile):
|
docTemp = docPath.with_suffix(".tmp")
|
||||||
try:
|
|
||||||
os.unlink(chkFile)
|
try:
|
||||||
logger.debug("Deleted: %s", chkFile)
|
docPath.unlink(missing_ok=True)
|
||||||
except Exception as exc:
|
docTemp.unlink(missing_ok=True)
|
||||||
self._docError = formatException(exc)
|
except Exception as exc:
|
||||||
return False
|
self._docError = formatException(exc)
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -206,7 +216,7 @@ class NWDoc:
|
|||||||
def getFileLocation(self):
|
def getFileLocation(self):
|
||||||
"""Return the file location of the current document.
|
"""Return the file location of the current document.
|
||||||
"""
|
"""
|
||||||
return self._fileLoc
|
return str(self._fileLoc)
|
||||||
|
|
||||||
def getCurrentItem(self):
|
def getCurrentItem(self):
|
||||||
"""Return a pointer to the currently open NWItem.
|
"""Return a pointer to the currently open NWItem.
|
||||||
|
|||||||
+20
-38
@@ -27,12 +27,12 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
from pathlib import Path
|
|
||||||
import shutil
|
import shutil
|
||||||
import logging
|
import logging
|
||||||
import novelwriter
|
import novelwriter
|
||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
from pathlib import Path
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication, QObject, pyqtSignal
|
from PyQt5.QtCore import QCoreApplication, QObject, pyqtSignal
|
||||||
@@ -84,10 +84,9 @@ class NWProject(QObject):
|
|||||||
self.lockedBy = None # Data on which computer has the project open
|
self.lockedBy = None # Data on which computer has the project open
|
||||||
|
|
||||||
# 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.projContent = None # The full path to the project's content folder
|
self.projDict = None # The spell check dictionary
|
||||||
self.projDict = None # The spell check dictionary
|
self.projFiles = [] # A list of all files in the content folder on load
|
||||||
self.projFiles = [] # A list of all files in the content folder on load
|
|
||||||
|
|
||||||
# Internal Mapping
|
# Internal Mapping
|
||||||
self.tr = partial(QCoreApplication.translate, "NWProject")
|
self.tr = partial(QCoreApplication.translate, "NWProject")
|
||||||
@@ -252,10 +251,9 @@ class NWProject(QObject):
|
|||||||
self._data = NWProjectData(self)
|
self._data = NWProjectData(self)
|
||||||
|
|
||||||
# Project Settings
|
# Project Settings
|
||||||
self.projPath = None
|
self.projPath = None
|
||||||
self.projContent = None
|
self.projDict = None
|
||||||
self.projDict = None
|
self.projFiles = []
|
||||||
self.projFiles = []
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -271,7 +269,6 @@ class NWProject(QObject):
|
|||||||
|
|
||||||
# ToDo: These should not be set explicitly, and should stay as Path
|
# ToDo: These should not be set explicitly, and should stay as Path
|
||||||
self.projPath = str(self._storage.runtimePath)
|
self.projPath = str(self._storage.runtimePath)
|
||||||
self.projContent = str(self._storage.contentPath)
|
|
||||||
|
|
||||||
logger.info("Opening project: %s", self.projPath)
|
logger.info("Opening project: %s", self.projPath)
|
||||||
|
|
||||||
@@ -468,24 +465,6 @@ class NWProject(QObject):
|
|||||||
self.lockedBy = None
|
self.lockedBy = None
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def ensureFolderStructure(self):
|
|
||||||
"""Ensure that all necessary folders exist in the project
|
|
||||||
folder.
|
|
||||||
"""
|
|
||||||
if self.projPath is None or self.projPath == "":
|
|
||||||
return False
|
|
||||||
|
|
||||||
self.projContent = os.path.join(self.projPath, "content")
|
|
||||||
|
|
||||||
if self.projPath == os.path.expanduser("~"):
|
|
||||||
# Don't make a mess in the user's home folder
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not self._checkFolder(self.projContent):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def setDefaultStatusImport(self):
|
def setDefaultStatusImport(self):
|
||||||
"""Set the default status and importance values.
|
"""Set the default status and importance values.
|
||||||
"""
|
"""
|
||||||
@@ -790,31 +769,34 @@ class NWProject(QObject):
|
|||||||
orphaned files so the user can either delete them, or put them
|
orphaned files so the user can either delete them, or put them
|
||||||
back into the project tree.
|
back into the project tree.
|
||||||
"""
|
"""
|
||||||
if self.projPath is None:
|
contentPath = self._storage.contentPath
|
||||||
|
if not isinstance(contentPath, Path):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Then check the files in the data folder
|
# Then check the files in the data folder
|
||||||
logger.debug("Checking files in project content folder")
|
logger.debug("Checking files in project content folder")
|
||||||
orphanFiles = []
|
orphanFiles = []
|
||||||
self.projFiles = []
|
self.projFiles = []
|
||||||
for fileItem in os.listdir(self.projContent):
|
|
||||||
if not fileItem.endswith(".nwd"):
|
for item in contentPath.iterdir():
|
||||||
logger.warning("Skipping file: %s", fileItem)
|
itemName = item.name
|
||||||
|
if not itemName.endswith(".nwd"):
|
||||||
|
logger.warning("Skipping file: %s", itemName)
|
||||||
continue
|
continue
|
||||||
if len(fileItem) != 17:
|
if len(itemName) != 17:
|
||||||
logger.warning("Skipping file: %s", fileItem)
|
logger.warning("Skipping file: %s", itemName)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
fHandle = fileItem[:13]
|
fHandle = itemName[:13]
|
||||||
if not isHandle(fHandle):
|
if not isHandle(fHandle):
|
||||||
logger.warning("Skipping file: %s", fileItem)
|
logger.warning("Skipping file: %s", itemName)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if fHandle in self._tree:
|
if fHandle in self._tree:
|
||||||
self.projFiles.append(fHandle)
|
self.projFiles.append(fHandle)
|
||||||
logger.debug("Checking file %s, handle '%s': OK", fileItem, fHandle)
|
logger.debug("Checking file %s, handle '%s': OK", itemName, fHandle)
|
||||||
else:
|
else:
|
||||||
logger.warning("Checking file %s, handle '%s': Orphaned", fileItem, fHandle)
|
logger.warning("Checking file %s, handle '%s': Orphaned", itemName, fHandle)
|
||||||
orphanFiles.append(fHandle)
|
orphanFiles.append(fHandle)
|
||||||
|
|
||||||
# Report status
|
# Report status
|
||||||
|
|||||||
@@ -151,6 +151,8 @@ class NWStorage:
|
|||||||
return xmlWriter
|
return xmlWriter
|
||||||
|
|
||||||
def getDocument(self, tHandle):
|
def getDocument(self, tHandle):
|
||||||
|
"""Return a document wrapper object.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def getMetaFile(self, fileName):
|
def getMetaFile(self, fileName):
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter.enum import nwItemClass, nwItemLayout
|
from novelwriter.enum import nwItemClass, nwItemLayout
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
from novelwriter.common import checkHandle
|
from novelwriter.common import checkHandle
|
||||||
@@ -140,16 +141,22 @@ class NWTree:
|
|||||||
"""Write the convenience table of contents file in the root of
|
"""Write the convenience table of contents file in the root of
|
||||||
the project directory.
|
the project directory.
|
||||||
"""
|
"""
|
||||||
|
runtimePath = self.theProject.storage.runtimePath
|
||||||
|
contentPath = self.theProject.storage.contentPath
|
||||||
|
if not (isinstance(contentPath, Path) and isinstance(runtimePath, Path)):
|
||||||
|
return False
|
||||||
|
|
||||||
tocList = []
|
tocList = []
|
||||||
tocLen = 0
|
tocLen = 0
|
||||||
for tHandle in self._treeOrder:
|
for tHandle in self._treeOrder:
|
||||||
tItem = self.__getitem__(tHandle)
|
tItem = self.__getitem__(tHandle)
|
||||||
if tItem is None:
|
if tItem is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
tFile = tHandle+".nwd"
|
tFile = tHandle+".nwd"
|
||||||
if os.path.isfile(os.path.join(self.theProject.projContent, tFile)):
|
if (contentPath / tFile).is_file():
|
||||||
tocLine = "{0:<25s} {1:<9s} {2:<8s} {3:s}".format(
|
tocLine = "{0:<25s} {1:<9s} {2:<8s} {3:s}".format(
|
||||||
os.path.join("content", tFile),
|
str(Path("content") / tFile),
|
||||||
tItem.itemClass.name,
|
tItem.itemClass.name,
|
||||||
tItem.itemLayout.name,
|
tItem.itemLayout.name,
|
||||||
tItem.itemName,
|
tItem.itemName,
|
||||||
@@ -159,7 +166,7 @@ class NWTree:
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# Dump the text
|
# Dump the text
|
||||||
tocText = os.path.join(self.theProject.projPath, nwFiles.TOC_TXT)
|
tocText = runtimePath / nwFiles.TOC_TXT
|
||||||
with open(tocText, mode="w", encoding="utf-8") as outFile:
|
with open(tocText, mode="w", encoding="utf-8") as outFile:
|
||||||
outFile.write("\n")
|
outFile.write("\n")
|
||||||
outFile.write("Table of Contents\n")
|
outFile.write("Table of Contents\n")
|
||||||
|
|||||||
@@ -163,9 +163,7 @@ class GuiWordList(QDialog):
|
|||||||
if item is not None:
|
if item is not None:
|
||||||
outFile.write(item.text() + "\n")
|
outFile.write(item.text() + "\n")
|
||||||
|
|
||||||
if dctFile.exists():
|
tmpFile.replace(dctFile)
|
||||||
dctFile.unlink()
|
|
||||||
tmpFile.rename(dctFile)
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.error("Could not save new word list")
|
logger.error("Could not save new word list")
|
||||||
|
|||||||
@@ -64,6 +64,13 @@ def tmpDir():
|
|||||||
return theDir
|
return theDir
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope="function")
|
||||||
|
def tmpPath(tmpDir):
|
||||||
|
"""A temporary folder for a single test function.
|
||||||
|
"""
|
||||||
|
return Path(tmpDir)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="session")
|
@pytest.fixture(scope="session")
|
||||||
def tstPaths(tmpDir):
|
def tstPaths(tmpDir):
|
||||||
"""Returns an object that can provide the various paths needed for
|
"""Returns an object that can provide the various paths needed for
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
|
|||||||
|
|
||||||
# Cause os.replace() to fail while saving
|
# Cause os.replace() to fail while saving
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.replace", causeOSError)
|
mp.setattr("pathlib.Path.replace", causeOSError)
|
||||||
assert theDoc.writeDocument(theText) is False
|
assert theDoc.writeDocument(theText) is False
|
||||||
assert theDoc.getError() == "OSError: Mock OSError"
|
assert theDoc.getError() == "OSError: Mock OSError"
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ def testCoreDocument_LoadSave(monkeypatch, mockGUI, fncDir, mockRnd):
|
|||||||
|
|
||||||
# Cause the delete to fail
|
# Cause the delete to fail
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.unlink", causeOSError)
|
mp.setattr("pathlib.Path.unlink", causeOSError)
|
||||||
theDoc = NWDoc(theProject, xHandle)
|
theDoc = NWDoc(theProject, xHandle)
|
||||||
assert theDoc.deleteDocument() is False
|
assert theDoc.deleteDocument() is False
|
||||||
assert theDoc.getError() == "OSError: Mock OSError"
|
assert theDoc.getError() == "OSError: Mock OSError"
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ def testCoreProject_NewFileFolder(monkeypatch, fncDir, outDir, refDir, mockGUI,
|
|||||||
|
|
||||||
# Delete new file, but block access
|
# Delete new file, but block access
|
||||||
with monkeypatch.context() as mp:
|
with monkeypatch.context() as mp:
|
||||||
mp.setattr("os.unlink", causeOSError)
|
mp.setattr("pathlib.Path.unlink", causeOSError)
|
||||||
assert theProject.removeItem("0000000000011") is False
|
assert theProject.removeItem("0000000000011") is False
|
||||||
assert "0000000000011" in theProject.tree
|
assert "0000000000011" in theProject.tree
|
||||||
|
|
||||||
@@ -270,36 +270,6 @@ def testCoreProject_Save(monkeypatch, mockGUI, mockRnd, fncDir, refDir):
|
|||||||
# END Test testCoreProject_Save
|
# END Test testCoreProject_Save
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
|
||||||
def testCoreProject_Helpers(monkeypatch, fncDir, mockGUI):
|
|
||||||
"""Test helper functions for the project folder.
|
|
||||||
"""
|
|
||||||
theProject = NWProject(mockGUI)
|
|
||||||
|
|
||||||
# No path
|
|
||||||
assert theProject.ensureFolderStructure() is False
|
|
||||||
|
|
||||||
# Set the correct dir
|
|
||||||
theProject.projPath = fncDir
|
|
||||||
|
|
||||||
# Block user's home folder
|
|
||||||
with monkeypatch.context() as mp:
|
|
||||||
mp.setattr("os.path.expanduser", lambda *a, **k: fncDir)
|
|
||||||
assert theProject.ensureFolderStructure() is False
|
|
||||||
|
|
||||||
# Create a file to block content folder
|
|
||||||
contentDir = os.path.join(fncDir, "content")
|
|
||||||
writeFile(contentDir, "stuff")
|
|
||||||
assert theProject.ensureFolderStructure() is False
|
|
||||||
os.unlink(contentDir)
|
|
||||||
|
|
||||||
# Now, do it right
|
|
||||||
assert theProject.ensureFolderStructure() is True
|
|
||||||
assert os.path.isdir(contentDir)
|
|
||||||
|
|
||||||
# END Test testCoreProject_Helpers
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreProject_AccessItems(mockGUI, fncDir, mockRnd):
|
def testCoreProject_AccessItems(mockGUI, fncDir, mockRnd):
|
||||||
"""Test helper functions for the project folder.
|
"""Test helper functions for the project folder.
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import pytest
|
import pytest
|
||||||
import random
|
import random
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from tools import readFile
|
from tools import readFile
|
||||||
|
|
||||||
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
from novelwriter.enum import nwItemClass, nwItemType, nwItemLayout
|
||||||
@@ -394,7 +395,7 @@ def testCoreTree_Reorder(mockGUI, mockItems):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.core
|
@pytest.mark.core
|
||||||
def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpDir):
|
def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpPath):
|
||||||
"""Test writing the ToC.txt file.
|
"""Test writing the ToC.txt file.
|
||||||
"""
|
"""
|
||||||
theProject = NWProject(mockGUI)
|
theProject = NWProject(mockGUI)
|
||||||
@@ -411,24 +412,23 @@ def testCoreTree_ToCFile(monkeypatch, mockGUI, mockItems, tmpDir):
|
|||||||
"""Return True for items that are files in novelWriter and
|
"""Return True for items that are files in novelWriter and
|
||||||
should thus also be files in the project folder structure.
|
should thus also be files in the project folder structure.
|
||||||
"""
|
"""
|
||||||
dItem = theTree[fileName[8:21]]
|
dItem = theTree[fileName.name[:13]]
|
||||||
assert dItem is not None
|
assert dItem is not None
|
||||||
return dItem.itemType == nwItemType.FILE
|
return dItem.itemType == nwItemType.FILE
|
||||||
|
|
||||||
monkeypatch.setattr("os.path.isfile", mockIsFile)
|
monkeypatch.setattr("pathlib.Path.is_file", mockIsFile)
|
||||||
|
|
||||||
theProject.projContent = "content"
|
theProject._storage._runtimePath = None
|
||||||
theProject.projPath = None
|
assert theTree.writeToCFile() is False
|
||||||
assert not theTree.writeToCFile()
|
|
||||||
|
|
||||||
theProject.projPath = tmpDir
|
theProject._storage._runtimePath = tmpPath
|
||||||
assert theTree.writeToCFile()
|
assert theTree.writeToCFile() is True
|
||||||
|
|
||||||
pathA = os.path.join("content", "c000000000001.nwd")
|
pathA = str(Path("content") / "c000000000001.nwd")
|
||||||
pathB = os.path.join("content", "c000000000002.nwd")
|
pathB = str(Path("content") / "c000000000002.nwd")
|
||||||
pathC = os.path.join("content", "b000000000002.nwd")
|
pathC = str(Path("content") / "b000000000002.nwd")
|
||||||
|
|
||||||
assert readFile(os.path.join(tmpDir, nwFiles.TOC_TXT)) == (
|
assert readFile(tmpPath / nwFiles.TOC_TXT) == (
|
||||||
"\n"
|
"\n"
|
||||||
"Table of Contents\n"
|
"Table of Contents\n"
|
||||||
"=================\n"
|
"=================\n"
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tools import C, buildTestProject, writeFile
|
from pathlib import Path
|
||||||
|
|
||||||
|
from tools import C, buildTestProject
|
||||||
|
|
||||||
from PyQt5.QtGui import QFocusEvent
|
from PyQt5.QtGui import QFocusEvent
|
||||||
from PyQt5.QtCore import Qt, QEvent
|
from PyQt5.QtCore import Qt, QEvent
|
||||||
@@ -46,18 +47,18 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
|||||||
nwGUI.projView.projTree._getTreeItem(C.hCharRoot).setSelected(True)
|
nwGUI.projView.projTree._getTreeItem(C.hCharRoot).setSelected(True)
|
||||||
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE)
|
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE)
|
||||||
|
|
||||||
writeFile(
|
contentPath = nwGUI.theProject.storage.contentPath
|
||||||
os.path.join(nwGUI.theProject.projContent, "0000000000010.nwd"),
|
assert isinstance(contentPath, Path)
|
||||||
"# Jane Doe\n\n@tag: Jane\n\n"
|
|
||||||
)
|
(contentPath / "0000000000010.nwd").write_text(
|
||||||
writeFile(
|
"# Jane Doe\n\n@tag: Jane\n\n", encoding="utf-8"
|
||||||
os.path.join(nwGUI.theProject.projContent, "000000000000f.nwd"), (
|
|
||||||
"### Scene One\n\n"
|
|
||||||
"@pov: Jane\n"
|
|
||||||
"@focus: Jane\n\n"
|
|
||||||
"% Synopsis: This is a scene."
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
(contentPath / "000000000000f.nwd").write_text((
|
||||||
|
"### Scene One\n\n"
|
||||||
|
"@pov: Jane\n"
|
||||||
|
"@focus: Jane\n\n"
|
||||||
|
"% Synopsis: This is a scene."
|
||||||
|
), encoding="utf-8")
|
||||||
|
|
||||||
novelView = nwGUI.novelView
|
novelView = nwGUI.novelView
|
||||||
novelTree = novelView.novelTree
|
novelTree = novelView.novelTree
|
||||||
|
|||||||
Reference in New Issue
Block a user