diff --git a/novelwriter/assets/images/wizard-back.jpg b/novelwriter/assets/images/wizard-back.jpg
deleted file mode 100644
index 8db614c8..00000000
Binary files a/novelwriter/assets/images/wizard-back.jpg and /dev/null differ
diff --git a/novelwriter/core/coretools.py b/novelwriter/core/coretools.py
index 584d4cfd..ed0bb822 100644
--- a/novelwriter/core/coretools.py
+++ b/novelwriter/core/coretools.py
@@ -326,11 +326,9 @@ class ProjectBuilder:
##
def buildProject(self, data: dict) -> bool:
- """Build a project from a data dictionary of specifications
- provided by the wizard.
- """
+ """Build or copy a project from a data dictionary."""
if not isinstance(data, dict):
- logger.error("Invalid call to newProject function")
+ logger.error("Invalid call to buildProject function")
return False
path = data.get("path", None)
@@ -353,9 +351,7 @@ class ProjectBuilder:
##
def _buildAndPopulate(self, path: Path, data: dict) -> bool:
- """Build a project from a data dictionary of specifications
- provided by the wizard.
- """
+ """Build a blank project from a data dictionary."""
project = NWProject()
status = project.storage.createNewProject(path)
if status == NWStorageCreate.NOT_EMPTY:
diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py
index 6c8b4fca..66ba4b93 100644
--- a/novelwriter/gui/theme.py
+++ b/novelwriter/gui/theme.py
@@ -487,7 +487,6 @@ class GuiIcons:
}
IMAGE_MAP: dict[str, tuple[str, str]] = {
- "wiz-back": ("wizard-back.jpg", "wizard-back.jpg"),
"welcome": ("welcome.jpg", "welcome.jpg"),
"nw-text": ("novelwriter-text-light.svg", "novelwriter-text-dark.svg"),
}
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index 2340c799..75505273 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -58,16 +58,13 @@ from novelwriter.dialogs.projdetails import GuiProjectDetails
from novelwriter.dialogs.projsettings import GuiProjectSettings
from novelwriter.tools.welcome import GuiWelcome
from novelwriter.tools.manuscript import GuiManuscript
-from novelwriter.tools.projwizard import GuiProjectWizard
from novelwriter.tools.dictionaries import GuiDictionaries
from novelwriter.tools.writingstats import GuiWritingStats
-from novelwriter.core.coretools import ProjectBuilder
from novelwriter.enum import (
- nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwItemClass, nwWidget, nwView
+ nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwWidget, nwView
)
from novelwriter.common import hexToInt
-from novelwriter.constants import nwFiles
logger = logging.getLogger(__name__)
@@ -373,42 +370,6 @@ class GuiMain(QMainWindow):
# Project Actions
##
- def newProject(self, projData: dict | None = None) -> bool:
- """Create a new project via the new project wizard."""
- if SHARED.hasProject:
- if not self.closeProject():
- SHARED.error(self.tr(
- "Cannot create a new project when another project is open."
- ))
- return False
-
- if projData is None:
- projData = self.showNewProjectDialog()
-
- if projData is None:
- return False
-
- projPath = projData.get("projPath", None)
- if projPath is None or projData is None:
- logger.error("No projData or projPath set")
- return False
-
- if (Path(projPath) / nwFiles.PROJ_FILE).is_file():
- SHARED.error(self.tr(
- "A project already exists in that location. "
- "Please choose another folder."
- ))
- return False
-
- logger.info("Creating new project")
- nwProject = ProjectBuilder()
- if nwProject.buildProject(projData):
- self.openProject(projPath)
- else:
- return False
-
- return True
-
def closeProject(self, isYes: bool = False) -> bool:
"""Close the project if one is open. isYes is passed on from the
close application event so the user doesn't get prompted twice
@@ -850,8 +811,6 @@ class GuiMain(QMainWindow):
if dlgProj.result() == QDialog.Accepted:
if dlgProj.openState == GuiProjectLoad.OPEN_STATE:
self.openProject(dlgProj.openPath)
- elif dlgProj.openState == GuiProjectLoad.NEW_STATE:
- self.newProject()
return
@pyqtSlot()
@@ -862,16 +821,6 @@ class GuiMain(QMainWindow):
dialog.exec_()
return
- def showNewProjectDialog(self) -> dict | None:
- """Open the wizard and assemble a project options dict."""
- newProj = GuiProjectWizard(self)
- newProj.exec_()
-
- if newProj.result() == QDialog.Accepted:
- return self._assembleProjectWizardData(newProj)
-
- return None
-
@pyqtSlot()
def showPreferencesDialog(self) -> None:
"""Open the preferences dialog."""
@@ -1472,44 +1421,6 @@ class GuiMain(QMainWindow):
self.setWindowTitle(winTitle)
return
- def _assembleProjectWizardData(self, newProj: GuiProjectWizard) -> dict:
- """Extract the user choices from the New Project Wizard and
- store them in a dictionary.
- """
- projData = {
- "projName": newProj.field("projName"),
- "projTitle": newProj.field("projTitle"),
- "projAuthor": newProj.field("projAuthor"),
- "projPath": newProj.field("projPath"),
- "popSample": newProj.field("popSample"),
- "popMinimal": newProj.field("popMinimal"),
- "popCustom": newProj.field("popCustom"),
- "addRoots": [],
- "addNotes": False,
- "numChapters": 0,
- "numScenes": 0,
- }
- if newProj.field("popCustom"):
- addRoots = []
- if newProj.field("addPlot"):
- addRoots.append(nwItemClass.PLOT)
- if newProj.field("addChar"):
- addRoots.append(nwItemClass.CHARACTER)
- if newProj.field("addWorld"):
- addRoots.append(nwItemClass.WORLD)
- projData["addRoots"] = addRoots
- projData["addNotes"] = newProj.field("addNotes")
- projData["numChapters"] = newProj.field("numChapters")
- projData["numScenes"] = newProj.field("numScenes")
-
- try:
- langIdx = newProj.field("projLang")
- projData["projLang"] = CONFIG.listLanguages(CONFIG.LANG_PROJ)[langIdx][0]
- except Exception:
- projData["projLang"] = "en_GB"
-
- return projData
-
def _getTagSource(self, tag: str) -> tuple[str | None, str | None]:
"""Handle the index lookup of a tag and display an alert if the
tag cannot be found.
diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py
deleted file mode 100644
index b819435f..00000000
--- a/novelwriter/tools/projwizard.py
+++ /dev/null
@@ -1,478 +0,0 @@
-"""
-novelWriter – GUI New Project Wizard
-====================================
-
-File History:
-Created: 2020-07-11 [0.10.1] GuiProjectWizard
-
-This file is a part of novelWriter
-Copyright 2018–2023, Veronica Berglyd Olsen
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-from __future__ import annotations
-
-import os
-import logging
-
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import (
- QComboBox, QFileDialog, QFormLayout, QGridLayout, QHBoxLayout, QLabel,
- QLineEdit, QPushButton, QRadioButton, QSpinBox, QVBoxLayout, QWizard,
- QWizardPage
-)
-
-from novelwriter import CONFIG, SHARED
-from novelwriter.common import makeFileNameSafe
-from novelwriter.extensions.switch import NSwitch
-
-logger = logging.getLogger(__name__)
-
-PAGE_INTRO = 0
-PAGE_STORE = 1
-PAGE_POP = 2
-PAGE_CUSTOM = 3
-PAGE_FINAL = 4
-
-
-class GuiProjectWizard(QWizard):
-
- def __init__(self, mainGui):
- super().__init__(parent=mainGui)
-
- logger.debug("Create: GuiProjectWizard")
- self.setObjectName("GuiProjectWizard")
-
- self.mainGui = mainGui
-
- self.sideImage = SHARED.theme.loadDecoration(
- "wiz-back", None, CONFIG.pxInt(370)
- )
- self.setWizardStyle(QWizard.ModernStyle)
- self.setPixmap(QWizard.WatermarkPixmap, self.sideImage)
-
- self.introPage = ProjWizardIntroPage(self)
- self.storagePage = ProjWizardFolderPage(self)
- self.popPage = ProjWizardPopulatePage(self)
- self.customPage = ProjWizardCustomPage(self)
- self.finalPage = ProjWizardFinalPage(self)
-
- self.setPage(PAGE_INTRO, self.introPage)
- self.setPage(PAGE_STORE, self.storagePage)
- self.setPage(PAGE_POP, self.popPage)
- self.setPage(PAGE_CUSTOM, self.customPage)
- self.setPage(PAGE_FINAL, self.finalPage)
-
- self.setOption(QWizard.NoBackButtonOnStartPage, True)
-
- logger.debug("Ready: GuiProjectWizard")
-
- return
-
- def __del__(self) -> None: # pragma: no cover
- logger.debug("Delete: GuiProjectWizard")
- return
-
-# END Class GuiProjectWizard
-
-
-class ProjWizardIntroPage(QWizardPage):
-
- def __init__(self, theWizard):
- super().__init__()
-
- self.setTitle(self.tr("Create New Project"))
- self.theText = QLabel(self.tr(
- "Provide at least a project name. The project name should not "
- "be changed beyond this point as it is used for generating file "
- "names for for instance backups. The other fields are optional "
- "and can be changed at any time in Project Settings."
- ))
- self.theText.setWordWrap(True)
-
- self.imgCredit = QLabel(self.tr("Side image by {0}, {1}").format(
- "Peter Mitterhofer", "CC BY-SA 4.0"
- ))
- lblFont = self.imgCredit.font()
- lblFont.setPointSizeF(0.6*SHARED.theme.fontPointSize)
- self.imgCredit.setFont(lblFont)
-
- xW = CONFIG.pxInt(300)
- vS = CONFIG.pxInt(12)
- fS = CONFIG.pxInt(4)
-
- # The Page Form
- self.projName = QLineEdit()
- self.projName.setMaxLength(200)
- self.projName.setFixedWidth(xW)
- self.projName.setPlaceholderText(self.tr("Required"))
-
- self.projTitle = QLineEdit()
- self.projTitle.setMaxLength(200)
- self.projTitle.setFixedWidth(xW)
- self.projTitle.setPlaceholderText(self.tr("Optional"))
-
- self.projAuthor = QLineEdit()
- self.projAuthor.setMaxLength(200)
- self.projAuthor.setFixedWidth(xW)
- self.projAuthor.setPlaceholderText(self.tr("Optional"))
-
- self.projLang = QComboBox(self)
- self.projLang.setMaximumWidth(xW)
- for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
- self.projLang.addItem(language, tag)
-
- langIdx = self.projLang.findData(CONFIG.guiLocale)
- if langIdx == -1:
- langIdx = self.projLang.findData("en_GB")
- if langIdx != -1:
- self.projLang.setCurrentIndex(langIdx)
-
- self.mainForm = QFormLayout()
- self.mainForm.addRow(self.tr("Project Name"), self.projName)
- self.mainForm.addRow(self.tr("Novel Title"), self.projTitle)
- self.mainForm.addRow(self.tr("Author(s)"), self.projAuthor)
- self.mainForm.addRow(self.tr("Language"), self.projLang)
- self.mainForm.setVerticalSpacing(fS)
-
- self.registerField("projName*", self.projName)
- self.registerField("projTitle", self.projTitle)
- self.registerField("projAuthor", self.projAuthor)
- self.registerField("projLang", self.projLang)
-
- # Assemble
- self.outerBox = QVBoxLayout()
- self.outerBox.setSpacing(vS)
- self.outerBox.addWidget(self.theText)
- self.outerBox.addLayout(self.mainForm)
- self.outerBox.addStretch(1)
- self.outerBox.addWidget(self.imgCredit)
- self.setLayout(self.outerBox)
-
- return
-
-# END Class ProjWizardIntroPage
-
-
-class ProjWizardFolderPage(QWizardPage):
-
- def __init__(self, theWizard):
- super().__init__()
-
- self.setTitle(self.tr("Select Project Folder"))
- self.theText = QLabel(self.tr(
- "Select a location to store the project. A new project folder "
- "will be created in the selected location."
- ))
- self.theText.setWordWrap(True)
-
- xW = CONFIG.pxInt(300)
- vS = CONFIG.pxInt(12)
- fS = CONFIG.pxInt(8)
-
- self.projPath = QLineEdit("")
- self.projPath.setFixedWidth(xW)
- self.projPath.setPlaceholderText(self.tr("Required"))
-
- self.browseButton = QPushButton("...")
- self.browseButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("...")))
- self.browseButton.clicked.connect(self._doBrowse)
-
- self.errLabel = QLabel("")
- self.errLabel.setWordWrap(True)
-
- self.mainForm = QHBoxLayout()
- self.mainForm.addWidget(QLabel(self.tr("Project Path")), 0)
- self.mainForm.addWidget(self.projPath, 1)
- self.mainForm.addWidget(self.browseButton, 0)
- self.mainForm.setSpacing(fS)
-
- self.registerField("projPath*", self.projPath)
-
- # Assemble
- self.outerBox = QVBoxLayout()
- self.outerBox.setSpacing(vS)
- self.outerBox.addWidget(self.theText)
- self.outerBox.addLayout(self.mainForm)
- self.outerBox.addWidget(self.errLabel)
- self.outerBox.addStretch(1)
- self.setLayout(self.outerBox)
-
- return
-
- def isComplete(self):
- """Check that the selected path isn't already being used.
- """
- self.errLabel.setText("")
- if not super().isComplete():
- return False
-
- setPath = os.path.abspath(os.path.expanduser(self.projPath.text()))
- parPath = os.path.dirname(setPath)
- logger.debug("Path is: %s", setPath)
- if parPath and not os.path.isdir(parPath):
- self.errLabel.setText(self.tr(
- "Error: A project folder cannot be created using this path."
- ))
- return False
-
- if os.path.exists(setPath):
- self.errLabel.setText(self.tr(
- "Error: The selected path already exists."
- ))
- return False
-
- return True
-
- ##
- # Slots
- ##
-
- def _doBrowse(self):
- """Select a project folder.
- """
- lastPath = CONFIG.lastPath()
- projDir = QFileDialog.getExistingDirectory(
- self, self.tr("Select Project Folder"), str(lastPath), options=QFileDialog.ShowDirsOnly
- )
- if projDir:
- projName = self.field("projName")
- if projName is not None:
- fullDir = os.path.join(os.path.abspath(projDir), makeFileNameSafe(projName))
- self.projPath.setText(fullDir)
- else:
- self.projPath.setText("")
-
- return
-
-# END Class ProjWizardFolderPage
-
-
-class ProjWizardPopulatePage(QWizardPage):
-
- def __init__(self, theWizard):
- super().__init__()
-
- self.setTitle(self.tr("Populate Project"))
- self.theText = QLabel(self.tr(
- "Choose how to pre-fill the project. Either with a minimal set of "
- "starter items, an example project explaining and showing many of "
- "the features, or show further custom options on the next page."
- ))
- self.theText.setWordWrap(True)
-
- vS = CONFIG.pxInt(12)
- fS = CONFIG.pxInt(4)
-
- self.popMinimal = QRadioButton(self.tr("Fill the project with a minimal set of items"))
- self.popSample = QRadioButton(self.tr("Fill the project with example files"))
- self.popCustom = QRadioButton(self.tr("Show detailed options for filling the project"))
- self.popMinimal.setChecked(True)
-
- self.popBox = QVBoxLayout()
- self.popBox.setSpacing(fS)
- self.popBox.addWidget(self.popMinimal)
- self.popBox.addWidget(self.popSample)
- self.popBox.addWidget(self.popCustom)
-
- self.registerField("popMinimal", self.popMinimal)
- self.registerField("popSample", self.popSample)
- self.registerField("popCustom", self.popCustom)
-
- # Assemble
- self.outerBox = QVBoxLayout()
- self.outerBox.setSpacing(vS)
- self.outerBox.addWidget(self.theText)
- self.outerBox.addLayout(self.popBox)
- self.outerBox.addStretch(1)
- self.setLayout(self.outerBox)
-
- return
-
- def nextId(self):
- """Overload the nextID function to skip further pages if custom
- is not selected.
- """
- if self.popCustom.isChecked():
- return PAGE_CUSTOM
- else:
- return PAGE_FINAL
-
-# END Class ProjWizardPopulatePage
-
-
-class ProjWizardCustomPage(QWizardPage):
-
- def __init__(self, theWizard):
- super().__init__()
-
- self.setTitle(self.tr("Custom Project Options"))
- self.theText = QLabel(self.tr(
- "Select which additional elements to populate the project with. "
- "You can skip making chapters and add only scenes by setting the "
- "number of chapters to 0."
- ))
- self.theText.setWordWrap(True)
-
- cM = CONFIG.pxInt(12)
- mH = CONFIG.pxInt(26)
- fS = CONFIG.pxInt(4)
-
- # Root Folders
- self.addPlot = NSwitch()
- self.addPlot.setChecked(True)
- self.addPlot.clicked.connect(self._syncSwitches)
-
- self.addChar = NSwitch()
- self.addChar.setChecked(True)
- self.addChar.clicked.connect(self._syncSwitches)
-
- self.addWorld = NSwitch()
- self.addWorld.setChecked(False)
- self.addWorld.clicked.connect(self._syncSwitches)
-
- self.addNotes = NSwitch()
- self.addNotes.setChecked(False)
-
- # Generate Content
- self.numChapters = QSpinBox()
- self.numChapters.setRange(0, 100)
- self.numChapters.setValue(5)
-
- self.numScenes = QSpinBox()
- self.numScenes.setRange(0, 200)
- self.numScenes.setValue(5)
-
- # Grid Form
- self.addBox = QGridLayout()
- self.addBox.addWidget(QLabel(self.tr("Add a folder for plot notes")), 0, 0)
- self.addBox.addWidget(QLabel(self.tr("Add a folder for character notes")), 1, 0)
- self.addBox.addWidget(QLabel(self.tr("Add a folder for location notes")), 2, 0)
- self.addBox.addWidget(QLabel(self.tr("Add example notes to the above")), 3, 0)
- self.addBox.addWidget(QLabel(self.tr("Add chapters to the novel folder")), 4, 0)
- self.addBox.addWidget(QLabel(self.tr("Add scenes to each chapter")), 5, 0)
- self.addBox.addWidget(self.addPlot, 0, 1, 1, 1, Qt.AlignRight)
- self.addBox.addWidget(self.addChar, 1, 1, 1, 1, Qt.AlignRight)
- self.addBox.addWidget(self.addWorld, 2, 1, 1, 1, Qt.AlignRight)
- self.addBox.addWidget(self.addNotes, 3, 1, 1, 1, Qt.AlignRight)
- self.addBox.addWidget(self.numChapters, 4, 1, 1, 1, Qt.AlignRight)
- self.addBox.addWidget(self.numScenes, 5, 1, 1, 1, Qt.AlignRight)
- self.addBox.setVerticalSpacing(fS)
- self.addBox.setHorizontalSpacing(cM)
- self.addBox.setContentsMargins(cM, 0, cM, 0)
- self.addBox.setColumnStretch(2, 1)
- for i in range(6):
- self.addBox.setRowMinimumHeight(i, mH)
-
- # Wizard Fields
- self.registerField("addPlot", self.addPlot)
- self.registerField("addChar", self.addChar)
- self.registerField("addWorld", self.addWorld)
- self.registerField("addNotes", self.addNotes)
- self.registerField("numChapters", self.numChapters)
- self.registerField("numScenes", self.numScenes)
-
- # Assemble
- self.outerBox = QVBoxLayout()
- self.outerBox.setSpacing(cM)
- self.outerBox.addWidget(self.theText)
- self.outerBox.addLayout(self.addBox)
- self.outerBox.addStretch(1)
- self.setLayout(self.outerBox)
-
- return
-
- ##
- # Internal Functions
- ##
-
- def _syncSwitches(self):
- """Check if the add notes option should also be switched off.
- """
- addPlot = self.addPlot.isChecked()
- addChar = self.addChar.isChecked()
- addWorld = self.addWorld.isChecked()
- if not (addPlot or addChar or addWorld):
- self.addNotes.setChecked(False)
- return
-
-# END Class ProjWizardCustomPage
-
-
-class ProjWizardFinalPage(QWizardPage):
-
- def __init__(self, theWizard):
- super().__init__()
-
- self.setTitle(self.tr("Summary"))
- self.theText = QLabel("")
- self.theText.setWordWrap(True)
-
- # Assemble
- self.outerBox = QVBoxLayout()
- self.outerBox.setSpacing(CONFIG.pxInt(12))
- self.outerBox.addWidget(self.theText)
- self.outerBox.addStretch(1)
- self.setLayout(self.outerBox)
-
- return
-
- def initializePage(self):
- """Update the summary information on the final page.
- """
- super().initializePage()
-
- sumList = []
- sumList.append(self.tr("Project Name: {0}").format(self.field("projName")))
- sumList.append(self.tr("Project Path: {0}").format(self.field("projPath")))
-
- if self.field("popMinimal"):
- sumList.append(self.tr("Fill the project with a minimal set of items"))
- elif self.field("popSample"):
- sumList.append(self.tr("Fill the project with example files"))
- elif self.field("popCustom"):
- if self.field("addPlot"):
- sumList.append(self.tr("Add a folder for plot notes"))
- if self.field("addChar"):
- sumList.append(self.tr("Add a folder for character notes"))
- if self.field("addWorld"):
- sumList.append(self.tr("Add a folder for location notes"))
- if self.field("addNotes"):
- sumList.append(self.tr("Add example notes to the above"))
- if self.field("numChapters") > 0:
- sumList.append(self.tr("Add {0} chapters to the novel folder").format(
- self.field("numChapters")
- ))
- if self.field("numScenes") > 0:
- sumList.append(self.tr("Add {0} scenes to each chapter").format(
- self.field("numScenes")
- ))
- else:
- if self.field("numScenes") > 0:
- sumList.append(self.tr("Add {0} scenes").format(
- self.field("numScenes")
- ))
-
- self.theText.setText(
- "
%s
• %s
%s
" % (
- self.tr("You have selected the following:"),
- "
• ".join(sumList),
- self.tr("Press '{0}' to create the new project.").format(
- self.tr("Done") if CONFIG.osDarwin else self.tr("Finish")
- )
- )
- )
- return
-
-# END Class ProjWizardFinalPage
diff --git a/tests/test_core/test_core_storage.py b/tests/test_core/test_core_storage.py
index 1407d898..e2b877db 100644
--- a/tests/test_core/test_core_storage.py
+++ b/tests/test_core/test_core_storage.py
@@ -297,48 +297,6 @@ def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd):
# END Test testCoreStorage_ZipIt
-# @pytest.mark.core
-# def testCoreStorage_PrepareStorage(monkeypatch, fncPath):
-# """Test the project path preparation functions."""
-# storage = NWStorage(MockProject()) # type: ignore
-# assert storage.isOpen() is False
-
-# # No path set
-# assert storage._prepareStorage() is False
-
-# # Set path to home
-# storage._runtimePath = fncPath
-# with monkeypatch.context() as mp:
-# mp.setattr("pathlib.Path.home", lambda: fncPath)
-# assert storage._prepareStorage() is False
-
-# # Fail on mkdir
-# storage._runtimePath = fncPath
-# with monkeypatch.context() as mp:
-# mp.setattr("pathlib.Path.mkdir", causeOSError)
-# assert storage._prepareStorage() is False
-
-# # Set up the folder
-# storage._runtimePath = fncPath
-# assert storage._prepareStorage(checkLegacy=False) is True
-# assert (fncPath / "content").exists()
-# assert (fncPath / "meta").exists()
-# assert not (fncPath / "cache").exists() # Removed in 2.1b1
-
-# # Add a legacy folder
-# storage._runtimePath = fncPath
-# dataDir = fncPath / "data_0"
-# dataDir.mkdir()
-# assert storage._prepareStorage(checkLegacy=True) is True
-# assert not dataDir.exists()
-
-# # We cannot add a new project here
-# storage._runtimePath = fncPath
-# assert storage._prepareStorage(checkLegacy=False, newProject=True) is False
-
-# # END Test testCoreStorage_PrepareStorage
-
-
@pytest.mark.core
def testCoreStorage_LegacyDataFolder(monkeypatch, fncPath):
"""Test project file format 1.0 folder structure conversion."""
diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py
index a43e86e8..657ce7e8 100644
--- a/tests/test_gui/test_gui_guimain.py
+++ b/tests/test_gui/test_gui_guimain.py
@@ -26,16 +26,15 @@ import pytest
from shutil import copyfile
from tools import (
- C, NWD_IGNORE, cmpFiles, buildTestProject, XML_IGNORE, getGuiItem, writeFile
+ C, NWD_IGNORE, cmpFiles, buildTestProject, XML_IGNORE, getGuiItem
)
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QDialog, QMenu, QMessageBox, QInputDialog
+from PyQt5.QtWidgets import QDialog, QMenu, QInputDialog
from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwItemType, nwView, nwWidget
-from novelwriter.constants import nwFiles
from novelwriter.gui.outline import GuiOutlineView
from novelwriter.gui.projtree import GuiProjectTree
from novelwriter.gui.doceditor import GuiDocEditor
@@ -43,7 +42,6 @@ from novelwriter.gui.noveltree import GuiNovelView
from novelwriter.dialogs.about import GuiAbout
from novelwriter.dialogs.projload import GuiProjectLoad
from novelwriter.dialogs.editlabel import GuiEditLabel
-from novelwriter.tools.projwizard import GuiProjectWizard
KEY_DELAY = 1
@@ -114,42 +112,6 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, projPath):
# END Test testGuiMain_Launch
-@pytest.mark.gui
-def testGuiMain_NewProject(monkeypatch, nwGUI, projPath):
- """Test creating a new project."""
- # Open wizard, but return no data
- with monkeypatch.context() as mp:
- mp.setattr(GuiProjectWizard, "exec_", lambda *a: None)
- assert nwGUI.newProject(projData=None) is False
-
- # Close project
- with monkeypatch.context() as mp:
- SHARED.project._valid = True
- mp.setattr(QMessageBox, "result", lambda *a: QMessageBox.No)
- assert nwGUI.newProject(projData={"projPath": projPath}) is False
- SHARED.project._valid = False
-
- # No project path
- assert nwGUI.newProject(projData={}) is False
-
- # Project file already exists
- projFile = projPath / nwFiles.PROJ_FILE
- writeFile(projFile, "Stuff")
- assert nwGUI.newProject(projData={"projPath": projPath}) is False
- projFile.unlink()
-
- # An unreachable path should also fail
- stuffPath = projPath / "stuff" / "stuff" / "stuff"
- assert nwGUI.newProject(projData={"projPath": stuffPath}) is False
-
- # This one should work just fine
- assert nwGUI.newProject(projData={"projPath": projPath}) is True
- assert (projPath / nwFiles.PROJ_FILE).is_file()
- assert (projPath / "content").is_dir()
-
-# END Test testGuiMain_NewProject
-
-
@pytest.mark.gui
def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
"""Test handling of project tree items based on GUI focus states."""
diff --git a/tests/test_tools/test_tools_projwizard.py b/tests/test_tools/test_tools_projwizard.py
deleted file mode 100644
index 65a80687..00000000
--- a/tests/test_tools/test_tools_projwizard.py
+++ /dev/null
@@ -1,249 +0,0 @@
-"""
-novelWriter – New Project Wizard Class Tester
-=============================================
-
-This file is a part of novelWriter
-Copyright 2018–2023, Veronica Berglyd Olsen
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-from __future__ import annotations
-
-import sys
-import pytest
-
-from tools import buildTestProject, getGuiItem
-
-from PyQt5.QtCore import Qt
-from PyQt5.QtWidgets import QFileDialog, QWizard, QDialog
-
-from novelwriter.enum import nwItemClass
-from novelwriter.tools.projwizard import (
- GuiProjectWizard, ProjWizardIntroPage, ProjWizardFolderPage,
- ProjWizardPopulatePage, ProjWizardCustomPage, ProjWizardFinalPage
-)
-
-
-@pytest.mark.gui
-@pytest.mark.skipif(sys.platform.startswith("darwin"), reason="Not running on Darwin")
-def testToolProjectWizard_Handling(qtbot, monkeypatch, nwGUI, projPath):
- """Test the launch of the project wizard.
- Disabled for macOS because the test segfaults on QWizard.show()
- """
- # Test New Project Function
- # ========================
-
- # New with a project open should cause an error
- buildTestProject(nwGUI, projPath)
- with monkeypatch.context() as mp:
- mp.setattr(nwGUI, "closeProject", lambda *a: False)
- assert nwGUI.newProject() is False
-
- # Close project, but call with invalid path
- assert nwGUI.closeProject()
- with monkeypatch.context() as mp:
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: None)
- assert nwGUI.newProject() is False
-
- # Now, with an empty dictionary
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {})
- assert nwGUI.newProject() is False
-
- # Now, with a non-empty folder
- mp.setattr(nwGUI, "showNewProjectDialog", lambda *a: {"projPath": projPath})
- assert nwGUI.newProject() is False
-
- # Test the Wizard Launching
- # =========================
-
- monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None)
-
- result = nwGUI.showNewProjectDialog()
- qtbot.waitUntil(lambda: getGuiItem("GuiProjectWizard") is not None, timeout=1000)
-
- nwWiz = getGuiItem("GuiProjectWizard")
- assert isinstance(nwWiz, GuiProjectWizard)
- nwWiz.show()
-
- qtbot.mouseClick(nwWiz.button(QWizard.CancelButton), Qt.LeftButton)
- assert result is None
-
- with monkeypatch.context() as mp:
- mp.setattr(GuiProjectWizard, "result", lambda *a: QDialog.Accepted)
- result = nwGUI.showNewProjectDialog()
- nwWiz.button(QWizard.CancelButton).click()
- assert isinstance(result, dict)
-
- nwWiz.reject()
- nwWiz.close()
-
- # qtbot.stop()
-
-# END Test testToolProjectWizard_Handling
-
-
-@pytest.mark.gui
-@pytest.mark.parametrize("prjType", ["minimal", "custom1", "custom2", "sample"])
-@pytest.mark.skipif(sys.platform.startswith("darwin"), reason="Not running on Darwin")
-def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncPath, prjType):
- """Test the new project wizard with a set of selection scenarios.
- """
- monkeypatch.setattr(GuiProjectWizard, "exec_", lambda *a: None)
-
- nwWiz = GuiProjectWizard(nwGUI)
- nwWiz.show()
- qtbot.addWidget(nwWiz)
-
- # Intro Page
- # ==========
-
- introPage = nwWiz.currentPage()
- assert isinstance(introPage, ProjWizardIntroPage)
- assert not nwWiz.button(QWizard.NextButton).isEnabled()
-
- introPage.projName.setText("Test Wizard")
- introPage.projTitle.setText("My Novel")
- introPage.projAuthor.setText("Jane Doe")
-
- # Setting projName should activate the button
- assert nwWiz.button(QWizard.NextButton).isEnabled()
-
- qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
-
- # Folder Page
- # ===========
-
- storagePage = nwWiz.currentPage()
- assert isinstance(storagePage, ProjWizardFolderPage)
- assert not nwWiz.button(QWizard.NextButton).isEnabled()
- assert storagePage.errLabel.text() == ""
-
- # Set an invalid path
- storagePage.projPath.setText(str(fncPath / "not" / "a" / "path"))
- assert not nwWiz.button(QWizard.NextButton).isEnabled()
- assert storagePage.errLabel.text().startswith("Error")
-
- # Set an existing path
- storagePage.projPath.setText(str(fncPath))
- assert not nwWiz.button(QWizard.NextButton).isEnabled()
- assert storagePage.errLabel.text().startswith("Error")
-
- # Return a non-result from browse
- with monkeypatch.context() as mp:
- mp.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: "")
- qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
- assert storagePage.errLabel.text() == ""
-
- # Let the browse feature handle it
- projPath = fncPath / "Test Wizard"
- with monkeypatch.context() as mp:
- mp.setattr(QFileDialog, "getExistingDirectory", lambda *a, **k: str(fncPath))
- qtbot.mouseClick(storagePage.browseButton, Qt.LeftButton, delay=100)
-
- assert storagePage.projPath.text() == str(projPath)
- assert storagePage.errLabel.text() == ""
-
- # Setting projPath should activate the button
- assert nwWiz.button(QWizard.NextButton).isEnabled()
-
- qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
-
- # Populate Page
- # =============
-
- popPage = nwWiz.currentPage()
- assert isinstance(popPage, ProjWizardPopulatePage)
- assert nwWiz.button(QWizard.NextButton).isEnabled()
-
- if prjType.startswith("minimal"):
- popPage.popMinimal.setChecked(True)
- elif prjType.startswith("custom"):
- popPage.popCustom.setChecked(True)
- elif prjType.startswith("sample"):
- popPage.popSample.setChecked(True)
-
- qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
-
- # Custom Page
- # ===========
- if prjType.startswith("custom"):
-
- customPage = nwWiz.currentPage()
- assert isinstance(customPage, ProjWizardCustomPage)
- assert nwWiz.button(QWizard.NextButton).isEnabled()
-
- # Make sure the fourth option is also turned off
- customPage.addPlot.setChecked(False)
- customPage.addChar.setChecked(False)
- customPage.addWorld.setChecked(False)
- customPage._syncSwitches()
- assert not customPage.addNotes.isChecked()
-
- # Switch everything back on again
- customPage.addPlot.setChecked(True)
- customPage.addChar.setChecked(True)
- customPage.addWorld.setChecked(True)
- customPage.addNotes.setChecked(True)
-
- if prjType == "custom2":
- customPage.numChapters.setValue(0)
- customPage.numScenes.setValue(10)
-
- qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton)
-
- # Final Page
- # ==========
-
- finalPage = nwWiz.currentPage()
- assert isinstance(finalPage, ProjWizardFinalPage)
- assert nwWiz.button(QWizard.FinishButton).isEnabled() # But we don't click it
-
- # Check Data
- # ==========
-
- projData = nwGUI._assembleProjectWizardData(nwWiz)
- assert projData["projName"] == "Test Wizard"
- assert projData["projTitle"] == "My Novel"
- assert projData["projAuthor"] == "Jane Doe"
- assert projData["projPath"] == str(projPath)
- assert projData["popMinimal"] == prjType.startswith("minimal")
- assert projData["popCustom"] == prjType.startswith("custom")
- assert projData["popSample"] == prjType.startswith("sample")
- if prjType.startswith("custom"):
- assert projData["addRoots"] == [
- nwItemClass.PLOT,
- nwItemClass.CHARACTER,
- nwItemClass.WORLD,
- ]
- if prjType == "custom1":
- assert projData["numChapters"] == 5
- assert projData["numScenes"] == 5
- assert projData["addNotes"] is True
- else:
- assert projData["numChapters"] == 0
- assert projData["numScenes"] == 10
- assert projData["addNotes"] is True
- else:
- assert projData["addRoots"] == []
- assert projData["numChapters"] == 0
- assert projData["numScenes"] == 0
- assert projData["addNotes"] is False
-
- # Cleanup
- nwWiz.reject()
- nwWiz.close()
-
- # qtbot.stop()
-
-# END Test testToolProjectWizard_Run