Allow creating new project from zip archive
This commit is contained in:
@@ -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
@@ -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."""
|
||||||
|
|||||||
Reference in New Issue
Block a user