Remove the old project wizard
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 116 KiB |
@@ -326,11 +326,9 @@ class ProjectBuilder:
|
|||||||
##
|
##
|
||||||
|
|
||||||
def buildProject(self, data: dict) -> bool:
|
def buildProject(self, data: dict) -> bool:
|
||||||
"""Build a project from a data dictionary of specifications
|
"""Build or copy a project from a data dictionary."""
|
||||||
provided by the wizard.
|
|
||||||
"""
|
|
||||||
if not isinstance(data, dict):
|
if not isinstance(data, dict):
|
||||||
logger.error("Invalid call to newProject function")
|
logger.error("Invalid call to buildProject function")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
path = data.get("path", None)
|
path = data.get("path", None)
|
||||||
@@ -353,9 +351,7 @@ class ProjectBuilder:
|
|||||||
##
|
##
|
||||||
|
|
||||||
def _buildAndPopulate(self, path: Path, data: dict) -> bool:
|
def _buildAndPopulate(self, path: Path, data: dict) -> bool:
|
||||||
"""Build a project from a data dictionary of specifications
|
"""Build a blank project from a data dictionary."""
|
||||||
provided by the wizard.
|
|
||||||
"""
|
|
||||||
project = NWProject()
|
project = NWProject()
|
||||||
status = project.storage.createNewProject(path)
|
status = project.storage.createNewProject(path)
|
||||||
if status == NWStorageCreate.NOT_EMPTY:
|
if status == NWStorageCreate.NOT_EMPTY:
|
||||||
|
|||||||
@@ -487,7 +487,6 @@ class GuiIcons:
|
|||||||
}
|
}
|
||||||
|
|
||||||
IMAGE_MAP: dict[str, tuple[str, str]] = {
|
IMAGE_MAP: dict[str, tuple[str, str]] = {
|
||||||
"wiz-back": ("wizard-back.jpg", "wizard-back.jpg"),
|
|
||||||
"welcome": ("welcome.jpg", "welcome.jpg"),
|
"welcome": ("welcome.jpg", "welcome.jpg"),
|
||||||
"nw-text": ("novelwriter-text-light.svg", "novelwriter-text-dark.svg"),
|
"nw-text": ("novelwriter-text-light.svg", "novelwriter-text-dark.svg"),
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-90
@@ -58,16 +58,13 @@ from novelwriter.dialogs.projdetails import GuiProjectDetails
|
|||||||
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
||||||
from novelwriter.tools.welcome import GuiWelcome
|
from novelwriter.tools.welcome import GuiWelcome
|
||||||
from novelwriter.tools.manuscript import GuiManuscript
|
from novelwriter.tools.manuscript import GuiManuscript
|
||||||
from novelwriter.tools.projwizard import GuiProjectWizard
|
|
||||||
from novelwriter.tools.dictionaries import GuiDictionaries
|
from novelwriter.tools.dictionaries import GuiDictionaries
|
||||||
from novelwriter.tools.writingstats import GuiWritingStats
|
from novelwriter.tools.writingstats import GuiWritingStats
|
||||||
from novelwriter.core.coretools import ProjectBuilder
|
|
||||||
|
|
||||||
from novelwriter.enum import (
|
from novelwriter.enum import (
|
||||||
nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwItemClass, nwWidget, nwView
|
nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwWidget, nwView
|
||||||
)
|
)
|
||||||
from novelwriter.common import hexToInt
|
from novelwriter.common import hexToInt
|
||||||
from novelwriter.constants import nwFiles
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -373,42 +370,6 @@ class GuiMain(QMainWindow):
|
|||||||
# Project Actions
|
# 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:
|
def closeProject(self, isYes: bool = False) -> bool:
|
||||||
"""Close the project if one is open. isYes is passed on from the
|
"""Close the project if one is open. isYes is passed on from the
|
||||||
close application event so the user doesn't get prompted twice
|
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.result() == QDialog.Accepted:
|
||||||
if dlgProj.openState == GuiProjectLoad.OPEN_STATE:
|
if dlgProj.openState == GuiProjectLoad.OPEN_STATE:
|
||||||
self.openProject(dlgProj.openPath)
|
self.openProject(dlgProj.openPath)
|
||||||
elif dlgProj.openState == GuiProjectLoad.NEW_STATE:
|
|
||||||
self.newProject()
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
@@ -862,16 +821,6 @@ class GuiMain(QMainWindow):
|
|||||||
dialog.exec_()
|
dialog.exec_()
|
||||||
return
|
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()
|
@pyqtSlot()
|
||||||
def showPreferencesDialog(self) -> None:
|
def showPreferencesDialog(self) -> None:
|
||||||
"""Open the preferences dialog."""
|
"""Open the preferences dialog."""
|
||||||
@@ -1472,44 +1421,6 @@ class GuiMain(QMainWindow):
|
|||||||
self.setWindowTitle(winTitle)
|
self.setWindowTitle(winTitle)
|
||||||
return
|
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]:
|
def _getTagSource(self, tag: str) -> tuple[str | None, str | None]:
|
||||||
"""Handle the index lookup of a tag and display an alert if the
|
"""Handle the index lookup of a tag and display an alert if the
|
||||||
tag cannot be found.
|
tag cannot be found.
|
||||||
|
|||||||
@@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
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(
|
|
||||||
"<p>%s</p><p> • %s</p><p>%s</p>" % (
|
|
||||||
self.tr("You have selected the following:"),
|
|
||||||
"<br> • ".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
|
|
||||||
@@ -297,48 +297,6 @@ def testCoreStorage_ZipIt(monkeypatch, mockGUI, fncPath, tstPaths, mockRnd):
|
|||||||
# END Test testCoreStorage_ZipIt
|
# 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
|
@pytest.mark.core
|
||||||
def testCoreStorage_LegacyDataFolder(monkeypatch, fncPath):
|
def testCoreStorage_LegacyDataFolder(monkeypatch, fncPath):
|
||||||
"""Test project file format 1.0 folder structure conversion."""
|
"""Test project file format 1.0 folder structure conversion."""
|
||||||
|
|||||||
@@ -26,16 +26,15 @@ import pytest
|
|||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
|
|
||||||
from tools import (
|
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.QtGui import QColor, QPalette
|
||||||
from PyQt5.QtCore import Qt
|
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 import CONFIG, SHARED
|
||||||
from novelwriter.enum import nwItemType, nwView, nwWidget
|
from novelwriter.enum import nwItemType, nwView, nwWidget
|
||||||
from novelwriter.constants import nwFiles
|
|
||||||
from novelwriter.gui.outline import GuiOutlineView
|
from novelwriter.gui.outline import GuiOutlineView
|
||||||
from novelwriter.gui.projtree import GuiProjectTree
|
from novelwriter.gui.projtree import GuiProjectTree
|
||||||
from novelwriter.gui.doceditor import GuiDocEditor
|
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.about import GuiAbout
|
||||||
from novelwriter.dialogs.projload import GuiProjectLoad
|
from novelwriter.dialogs.projload import GuiProjectLoad
|
||||||
from novelwriter.dialogs.editlabel import GuiEditLabel
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
||||||
from novelwriter.tools.projwizard import GuiProjectWizard
|
|
||||||
|
|
||||||
KEY_DELAY = 1
|
KEY_DELAY = 1
|
||||||
|
|
||||||
@@ -114,42 +112,6 @@ def testGuiMain_Launch(qtbot, monkeypatch, nwGUI, projPath):
|
|||||||
# END Test testGuiMain_Launch
|
# 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
|
@pytest.mark.gui
|
||||||
def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
|
||||||
"""Test handling of project tree items based on GUI focus states."""
|
"""Test handling of project tree items based on GUI focus states."""
|
||||||
|
|||||||
@@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
Reference in New Issue
Block a user