Allow creating new project from zip archive

This commit is contained in:
Veronica Berglyd Olsen
2024-02-03 14:54:01 +01:00
parent 8af720cbd6
commit a11657c145
2 changed files with 31 additions and 19 deletions
+21 -11
View File
@@ -32,6 +32,7 @@ import logging
from typing import Iterable from typing import Iterable
from pathlib import Path from pathlib import Path
from functools import partial from functools import partial
from zipfile import ZipFile, is_zipfile
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
@@ -459,7 +460,7 @@ class ProjectBuilder:
""" """
source = data.get("template") source = data.get("template")
if not (isinstance(source, Path) and source.is_file() if not (isinstance(source, Path) and source.is_file()
and source.name == nwFiles.PROJ_FILE): and (source.name == nwFiles.PROJ_FILE or is_zipfile(source))):
logger.error("Could not access source project: %s", source) logger.error("Could not access source project: %s", source)
return False return False
@@ -478,10 +479,22 @@ class ProjectBuilder:
dstCont = dstPath / "content" dstCont = dstPath / "content"
dstPath.mkdir(exist_ok=True) dstPath.mkdir(exist_ok=True)
dstCont.mkdir(exist_ok=True) dstCont.mkdir(exist_ok=True)
shutil.copy2(srcPath / nwFiles.PROJ_FILE, dstPath) try:
for contFile in srcCont.iterdir(): if is_zipfile(source):
if contFile.is_file() and contFile.suffix == ".nwd" and isHandle(contFile.stem): with ZipFile(source) as zipObj:
shutil.copy2(contFile, dstCont) for member in zipObj.namelist():
if member == nwFiles.PROJ_FILE:
zipObj.extract(member, dstPath)
elif member.startswith("content") and member.endswith(".nwd"):
zipObj.extract(member, dstPath)
else:
shutil.copy2(srcPath / nwFiles.PROJ_FILE, dstPath)
for item in srcCont.iterdir():
if item.is_file() and item.suffix == ".nwd" and isHandle(item.stem):
shutil.copy2(item, dstCont)
except Exception as exc:
SHARED.error(self.tr("Could not copy project files."), exc=exc)
return False
# Open the copied project and update settings # Open the copied project and update settings
project = NWProject() project = NWProject()
@@ -505,14 +518,11 @@ class ProjectBuilder:
"""Make a copy of the sample project by extracting the """Make a copy of the sample project by extracting the
sample.zip file to the new path. sample.zip file to the new path.
""" """
pkgSample = CONFIG.assetPath("sample.zip") if (sample := CONFIG.assetPath("sample.zip")).is_file():
if pkgSample.is_file():
try: try:
shutil.unpack_archive(pkgSample, path) shutil.unpack_archive(sample, path)
except Exception as exc: except Exception as exc:
SHARED.error(self.tr( SHARED.error(self.tr("Failed to create a new example project."), exc=exc)
"Failed to create a new example project."
), exc=exc)
return False return False
else: else:
SHARED.error(self.tr( SHARED.error(self.tr(
+10 -8
View File
@@ -221,16 +221,18 @@ class SharedData(QObject):
def getProjectPath(self, parent: QWidget, path: str | Path | None = None, def getProjectPath(self, parent: QWidget, path: str | Path | None = None,
allowZip: bool = False) -> Path | None: allowZip: bool = False) -> Path | None:
"""Open the file dialog and select a novelWriter project file.""" """Open the file dialog and select a novelWriter project file."""
ext = [
self.tr("novelWriter Project File ({0})").format(nwFiles.PROJ_FILE),
self.tr("All files ({0})").format("*"),
]
if allowZip: if allowZip:
ext.insert(1, self.tr("Zip Archives ({0})").format("*.zip")) label = self.tr("novelWriter Project File or Zip")
projFile, _ = QFileDialog.getOpenFileName( ext = f"{nwFiles.PROJ_FILE} *.zip"
parent, self.tr("Open Project"), str(path or ""), filter=";;".join(ext) else:
label = self.tr("novelWriter Project File")
ext = nwFiles.PROJ_FILE
selected, _ = QFileDialog.getOpenFileName(
parent, self.tr("Open Project"), str(path or ""), filter=";;".join(
[f"{label} ({ext})", "{0} (*)".format(self.tr("All Files"))]
)
) )
return Path(projFile) if projFile else None return Path(selected) if selected else None
def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None: def findTopLevelWidget(self, kind: type[NWWidget]) -> NWWidget | None:
"""Find a top level widget.""" """Find a top level widget."""