From b0f1db0aeaa0d8d40dca29cc14e0246fd52e33e6 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Wed, 31 Jan 2024 23:56:09 +0100 Subject: [PATCH] Add copy project feature to project builder class --- novelwriter/core/coretools.py | 58 +++++++++++++++++++++++--- tests/test_core/test_core_coretools.py | 2 +- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/novelwriter/core/coretools.py b/novelwriter/core/coretools.py index c220d14e..2ac855eb 100644 --- a/novelwriter/core/coretools.py +++ b/novelwriter/core/coretools.py @@ -36,8 +36,8 @@ from functools import partial from PyQt5.QtCore import QCoreApplication from novelwriter import CONFIG, SHARED -from novelwriter.common import minmax, simplified -from novelwriter.constants import nwItemClass +from novelwriter.common import isHandle, minmax, simplified +from novelwriter.constants import nwFiles, nwItemClass from novelwriter.core.item import NWItem from novelwriter.core.project import NWProject from novelwriter.core.storage import NWStorageCreate @@ -330,9 +330,8 @@ class ProjectBuilder: self._path = Path(path).resolve() if data.get("sample", False): return self._extractSampleProject(self._path) - elif data.get("template"): # pragma: no cover - # Not implemented yet - return True + elif data.get("template"): + return self._copyProject(self._path, data) else: return self._buildAndPopulate(self._path, data) SHARED.error("A project path is required.") @@ -348,7 +347,7 @@ class ProjectBuilder: status = project.storage.createNewProject(path) if status == NWStorageCreate.NOT_EMPTY: SHARED.error(self.tr( - "A project already exists in that location. " + "The target folder is not empty. " "Please choose another folder." )) return False @@ -454,6 +453,53 @@ class ProjectBuilder: return True + def _copyProject(self, path: Path, data: dict) -> bool: + """Copy an existing project content, but not the meta data, and + update new settings. + """ + source = data.get("template") + if not (isinstance(source, Path) and source.is_file() + and source.name == nwFiles.PROJ_FILE): + return False + + logger.info("Copying project: %s", source) + if path.exists(): + SHARED.error(self.tr( + "The target folder already exists. " + "Please choose another folder." + )) + return False + + # Begin copying + srcPath = source.parent + dstPath = path.resolve() + srcCont = srcPath / "content" + dstCont = dstPath / "content" + dstPath.mkdir(exist_ok=True) + dstCont.mkdir(exist_ok=True) + shutil.copy2(srcPath / nwFiles.PROJ_FILE, dstPath) + for contFile in srcCont.iterdir(): + if contFile.is_file() and contFile.suffix == ".nwd" and isHandle(contFile.stem): + shutil.copy2(contFile, dstCont) + + # Open the copied project and update settings + project = NWProject() + project.openProject(dstPath) + project.data.setUuid("") # Creates a fresh uuid + project.data.setName(data.get("name", "None")) + project.data.setAuthor(data.get("author", "")) + project.data.setLanguage(data.get("language", "en_GB")) + project.data.setSpellCheck(True) + project.data.setSpellLang(None) + project.data.setDoBackup(True) + project.data.setSaveCount(0) + project.data.setAutoCount(0) + project.data.setEditTime(0) + project.saveProject() + project.closeProject() + + return True + def _extractSampleProject(self, path: Path) -> bool: """Make a copy of the sample project by extracting the sample.zip file to the new path. diff --git a/tests/test_core/test_core_coretools.py b/tests/test_core/test_core_coretools.py index 9625a17a..bcf545d8 100644 --- a/tests/test_core/test_core_coretools.py +++ b/tests/test_core/test_core_coretools.py @@ -425,7 +425,7 @@ def testCoreTools_ProjectBuilderWrapper(monkeypatch, caplog, fncPath, mockGUI): # Creating the project once more should fail caplog.clear() assert builder.buildProject({"path": fncPath}) is False - assert "A project already exists" in caplog.text + assert "The target folder is not empty." in caplog.text # END Test testCoreTools_ProjectBuilderWrapper