diff --git a/novelwriter/core/project.py b/novelwriter/core/project.py index 26efb323..3341e578 100644 --- a/novelwriter/core/project.py +++ b/novelwriter/core/project.py @@ -120,32 +120,34 @@ class NWProject(): # Item Methods ## - def newRoot(self, rootName, rootClass): - """Add a new root item. + def newRoot(self, itemClass, label=None): + """Add a new root item. If label is None, use the class label. """ + if label is None: + label = trConst(nwLabels.CLASS_NAME[itemClass]) newItem = NWItem(self) - newItem.setName(rootName) + newItem.setName(label) newItem.setType(nwItemType.ROOT) - newItem.setClass(rootClass) + newItem.setClass(itemClass) self.projTree.append(None, None, newItem) self.projTree.updateItemData(newItem.itemHandle) return newItem.itemHandle - def newFolder(self, folderName, pHandle): - """Add a new folder with a given name and parent item. + def newFolder(self, label, pHandle): + """Add a new folder with a given label and parent item. """ newItem = NWItem(self) - newItem.setName(folderName) + newItem.setName(label) newItem.setType(nwItemType.FOLDER) self.projTree.append(None, pHandle, newItem) self.projTree.updateItemData(newItem.itemHandle) return newItem.itemHandle - def newFile(self, fileName, pHandle): - """Add a new file with a given name and parent item. + def newFile(self, label, pHandle): + """Add a new file with a given label and parent item. """ newItem = NWItem(self) - newItem.setName(fileName) + newItem.setName(label) newItem.setType(nwItemType.FILE) self.projTree.append(None, pHandle, newItem) self.projTree.updateItemData(newItem.itemHandle) @@ -264,84 +266,88 @@ class NWProject(): self.setBookTitle(projTitle) self.setBookAuthors(projAuthors) + hNovelRoot = self.newRoot(nwItemClass.NOVEL) + hTitlePage = self.newFile(self.tr("Title Page"), hNovelRoot) + titlePage = "#! %s\n\n" % (self.bookTitle if self.bookTitle else self.projName) if self.bookAuthors: titlePage = "%s>> %s %s <<\n" % (titlePage, self.tr("By"), self.getAuthors()) + aDoc = NWDoc(self, hTitlePage) + aDoc.writeDocument(titlePage) + if popMinimal: # Creating a minimal project with a few root folders and a - # single chapter folder with a single file. - xHandle = {} - xHandle[1] = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL) - xHandle[2] = self.newRoot(self.tr("Plot"), nwItemClass.PLOT) - xHandle[3] = self.newRoot(self.tr("Characters"), nwItemClass.CHARACTER) - xHandle[4] = self.newRoot(self.tr("World"), nwItemClass.WORLD) - xHandle[5] = self.newFile(self.tr("Title Page"), xHandle[1]) - xHandle[6] = self.newFolder(self.tr("New Chapter"), xHandle[1]) - xHandle[7] = self.newFile(self.tr("New Chapter"), xHandle[6]) - xHandle[8] = self.newFile(self.tr("New Scene"), xHandle[6]) - - aDoc = NWDoc(self, xHandle[5]) - aDoc.writeDocument(titlePage) - - aDoc = NWDoc(self, xHandle[7]) + # single chapter with a single scene. + hChapter = self.newFile(self.tr("New Chapter"), hNovelRoot) + aDoc = NWDoc(self, hChapter) aDoc.writeDocument("## %s\n\n" % self.tr("New Chapter")) - aDoc = NWDoc(self, xHandle[8]) + hScene = self.newFile(self.tr("New Scene"), hChapter) + aDoc = NWDoc(self, hScene) aDoc.writeDocument("### %s\n\n" % self.tr("New Scene")) + self.newRoot(nwItemClass.PLOT) + self.newRoot(nwItemClass.CHARACTER) + self.newRoot(nwItemClass.WORLD) + self.newRoot(nwItemClass.ARCHIVE) + elif popCustom: # Create a project structure based on selected root folders # and a number of chapters and scenes selected in the # wizard's custom page. - # Create root folders - nHandle = self.newRoot(self.tr("Novel"), nwItemClass.NOVEL) - for newRoot in projData.get("addRoots", []): - if newRoot in nwItemClass: - self.newRoot(trConst(nwLabels.CLASS_NAME[newRoot]), newRoot) - - # Create a title page - tHandle = self.newFile(self.tr("Title Page"), nHandle) - - aDoc = NWDoc(self, tHandle) - aDoc.writeDocument(titlePage) - # Create chapters and scenes numChapters = projData.get("numChapters", 0) numScenes = projData.get("numScenes", 0) - chFolders = projData.get("chFolders", False) + + chSynop = self.tr("Summary of the chapter.") + scSynop = self.tr("Summary of the scene.") # Create chapters if numChapters > 0: for ch in range(numChapters): chTitle = self.tr("Chapter {0}").format(f"{ch+1:d}") - pHandle = nHandle - if chFolders: - pHandle = self.newFolder(chTitle, nHandle) - - cHandle = self.newFile(chTitle, pHandle) - + cHandle = self.newFile(chTitle, hNovelRoot) aDoc = NWDoc(self, cHandle) - aDoc.writeDocument("## %s\n\n" % chTitle) + aDoc.writeDocument(f"## {chTitle}\n\n% Synopsis: {chSynop}\n\n") # Create chapter scenes if numScenes > 0: for sc in range(numScenes): scTitle = self.tr("Scene {0}").format(f"{ch+1:d}.{sc+1:d}") - sHandle = self.newFile(scTitle, pHandle) - + sHandle = self.newFile(scTitle, cHandle) aDoc = NWDoc(self, sHandle) - aDoc.writeDocument("### %s\n\n" % scTitle) + aDoc.writeDocument(f"### {scTitle}\n\n% Synopsis: {scSynop}\n\n") # Create scenes (no chapters) elif numScenes > 0: for sc in range(numScenes): scTitle = self.tr("Scene {0}").format(f"{sc+1:d}") - sHandle = self.newFile(scTitle, nHandle) - + sHandle = self.newFile(scTitle, hNovelRoot) aDoc = NWDoc(self, sHandle) - aDoc.writeDocument("### %s\n\n" % scTitle) + aDoc.writeDocument(f"### {scTitle}\n\n% Synopsis: {scSynop}\n\n") + + # Create notes folders + noteTitles = { + nwItemClass.PLOT: self.tr("Main Plot"), + nwItemClass.CHARACTER: self.tr("Protagonist"), + nwItemClass.WORLD: self.tr("Main Location"), + } + + addNotes = projData.get("addNotes", False) + for newRoot in projData.get("addRoots", []): + if newRoot in nwItemClass: + rHandle = self.newRoot(newRoot) + if addNotes: + aHandle = self.newFile(noteTitles[newRoot], rHandle) + ntTag = simplified(noteTitles[newRoot]).replace(" ", "") + aDoc = NWDoc(self, aHandle) + aDoc.writeDocument(f"# {noteTitles[newRoot]}\n\n@tag: {ntTag}\n\n") + + # Also add the archive and trash folders + self.newRoot(nwItemClass.ARCHIVE) + self.trashFolder() # Finalise if popCustom or popMinimal: diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 0339ec5f..5d40aeae 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -37,7 +37,6 @@ from PyQt5.QtWidgets import ( from novelwriter.core import NWDoc from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwAlert -from novelwriter.constants import trConst, nwLabels logger = logging.getLogger(__name__) @@ -176,9 +175,7 @@ class GuiProjectTree(QTreeWidget): if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass): - tHandle = self.theProject.newRoot( - trConst(nwLabels.CLASS_NAME[itemClass]), itemClass - ) + tHandle = self.theProject.newRoot(itemClass) elif itemType in (nwItemType.FILE, nwItemType.FOLDER): diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index ad06cc59..724989f9 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -1440,9 +1440,9 @@ class GuiMain(QMainWindow): "popMinimal": newProj.field("popMinimal"), "popCustom": newProj.field("popCustom"), "addRoots": [], + "addNotes": False, "numChapters": 0, "numScenes": 0, - "chFolders": False, } if newProj.field("popCustom"): addRoots = [] @@ -1452,16 +1452,10 @@ class GuiMain(QMainWindow): addRoots.append(nwItemClass.CHARACTER) if newProj.field("addWorld"): addRoots.append(nwItemClass.WORLD) - if newProj.field("addTime"): - addRoots.append(nwItemClass.TIMELINE) - if newProj.field("addObject"): - addRoots.append(nwItemClass.OBJECT) - if newProj.field("addEntity"): - addRoots.append(nwItemClass.ENTITY) projData["addRoots"] = addRoots + projData["addNotes"] = newProj.field("addNotes") projData["numChapters"] = newProj.field("numChapters") projData["numScenes"] = newProj.field("numScenes") - projData["chFolders"] = newProj.field("chFolders") return projData diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py index e4cc6862..765445b9 100644 --- a/novelwriter/tools/projwizard.py +++ b/novelwriter/tools/projwizard.py @@ -31,12 +31,10 @@ from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QWizard, QWizardPage, QLabel, QVBoxLayout, QLineEdit, QPlainTextEdit, QPushButton, QFileDialog, QHBoxLayout, QRadioButton, QFormLayout, - QGroupBox, QGridLayout, QSpinBox + QGridLayout, QSpinBox ) -from novelwriter.enum import nwItemClass from novelwriter.common import makeFileNameSafe -from novelwriter.constants import trConst, nwLabels from novelwriter.gui.custom import QSwitch logger = logging.getLogger(__name__) @@ -98,10 +96,10 @@ class ProjWizardIntroPage(QWizardPage): self.setTitle(self.tr("Create New Project")) self.theText = QLabel(self.tr( - "Provide at least a working title. The working title should not " - "be change beyond this point as it is used by the application for " - "generating file names for for instance backups. The other fields " - "are optional and can be changed at any time in Project Settings." + "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) @@ -134,7 +132,7 @@ class ProjWizardIntroPage(QWizardPage): self.projAuthors.setPlaceholderText(self.tr("Optional. One name per line.")) self.mainForm = QFormLayout() - self.mainForm.addRow(self.tr("Working Title"), self.projName) + 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.projAuthors) self.mainForm.setVerticalSpacing(fS) @@ -324,68 +322,28 @@ class ProjWizardCustomPage(QWizardPage): self.setTitle(self.tr("Custom Project Options")) self.theText = QLabel(self.tr( - "Select which additional root folders to make, and how to populate " - "the Novel folder. If you don't want to add chapters or scenes, set " - "the values to 0. You can add scenes without chapters." + "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) - vS = self.mainConf.pxInt(12) + cM = self.mainConf.pxInt(12) + mH = self.mainConf.pxInt(26) + fS = self.mainConf.pxInt(4) # Root Folders - self.rootGroup = QGroupBox(self.tr("Additional Root Folders")) - self.rootForm = QGridLayout() - self.rootGroup.setLayout(self.rootForm) - - self.lblPlot = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.PLOT])) - ) - self.lblChar = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.CHARACTER])) - ) - self.lblWorld = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.WORLD])) - ) - self.lblTime = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.TIMELINE])) - ) - self.lblObject = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.OBJECT])) - ) - self.lblEntity = QLabel(self.tr("{0} folder").format( - trConst(nwLabels.CLASS_NAME[nwItemClass.ENTITY])) - ) - - self.addPlot = QSwitch() - self.addChar = QSwitch() - self.addWorld = QSwitch() - self.addTime = QSwitch() - self.addObject = QSwitch() - self.addEntity = QSwitch() + self.addPlot = QSwitch() + self.addChar = QSwitch() + self.addWorld = QSwitch() + self.addNotes = QSwitch() self.addPlot.setChecked(True) self.addChar.setChecked(True) - self.addWorld.setChecked(True) - - self.rootForm.addWidget(self.lblPlot, 0, 0) - self.rootForm.addWidget(self.lblChar, 1, 0) - self.rootForm.addWidget(self.lblWorld, 2, 0) - self.rootForm.addWidget(self.lblTime, 3, 0) - self.rootForm.addWidget(self.lblObject, 4, 0) - self.rootForm.addWidget(self.lblEntity, 5, 0) - self.rootForm.addWidget(self.addPlot, 0, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addChar, 1, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addWorld, 2, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addTime, 3, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addObject, 4, 1, 1, 1, Qt.AlignRight) - self.rootForm.addWidget(self.addEntity, 5, 1, 1, 1, Qt.AlignRight) - self.rootForm.setRowStretch(6, 1) - - # Novel Options - self.novelGroup = QGroupBox(self.tr("Populate Novel Folder")) - self.novelForm = QGridLayout() - self.novelGroup.setLayout(self.novelForm) + self.addWorld.setChecked(False) + self.addNotes.setChecked(False) + # Generate Content self.numChapters = QSpinBox() self.numChapters.setRange(0, 100) self.numChapters.setValue(5) @@ -394,37 +352,40 @@ class ProjWizardCustomPage(QWizardPage): self.numScenes.setRange(0, 200) self.numScenes.setValue(5) - self.chFolders = QSwitch() - self.chFolders.setChecked(True) - - self.novelForm.addWidget(QLabel(self.tr("Add chapters")), 0, 0) - self.novelForm.addWidget(QLabel(self.tr("Scenes (per chapter)")), 1, 0) - self.novelForm.addWidget(QLabel(self.tr("Add chapter folders")), 2, 0) - self.novelForm.addWidget(self.numChapters, 0, 1, 1, 1, Qt.AlignRight) - self.novelForm.addWidget(self.numScenes, 1, 1, 1, 1, Qt.AlignRight) - self.novelForm.addWidget(self.chFolders, 2, 1, 1, 1, Qt.AlignRight) - self.novelForm.setRowStretch(3, 1) + # 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("addTime", self.addTime) - self.registerField("addObject", self.addObject) - self.registerField("addEntity", self.addEntity) + self.registerField("addNotes", self.addNotes) self.registerField("numChapters", self.numChapters) self.registerField("numScenes", self.numScenes) - self.registerField("chFolders", self.chFolders) # Assemble - self.innerBox = QHBoxLayout() - self.innerBox.addWidget(self.rootGroup) - self.innerBox.addWidget(self.novelGroup) - self.outerBox = QVBoxLayout() - self.outerBox.setSpacing(vS) + self.outerBox.setSpacing(cM) self.outerBox.addWidget(self.theText) - self.outerBox.addLayout(self.innerBox) + self.outerBox.addLayout(self.addBox) self.outerBox.addStretch(1) self.setLayout(self.outerBox) @@ -441,15 +402,8 @@ class ProjWizardFinalPage(QWizardPage): self.mainConf = novelwriter.CONFIG self.theWizard = theWizard - self.setTitle(self.tr("Finished")) - self.theText = QLabel( - "

%s

%s

" % ( - self.tr("All done."), - self.tr("Press '{0}' to create the new project.").format( - self.tr("Done") if self.mainConf.osDarwin else self.tr("Finish") - ) - ) - ) + self.setTitle(self.tr("Summary")) + self.theText = QLabel("") self.theText.setWordWrap(True) # Assemble @@ -461,4 +415,51 @@ class ProjWizardFinalPage(QWizardPage): return + def initializePage(self): + """Update the summary information on the final page. + """ + QWizardPage.initializePage(self) + + 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 self.mainConf.osDarwin else self.tr("Finish") + ) + ) + ) + return + # END Class ProjWizardFinalPage diff --git a/tests/reference/coreProject_NewCustomA_nwProject.nwx b/tests/reference/coreProject_NewCustomA_nwProject.nwx index 14abf9e2..be4845bf 100644 --- a/tests/reference/coreProject_NewCustomA_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomA_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -29,110 +29,106 @@
- New + New Note Draft Finished - New + New Minor Major Main - + Novel - - - Plot - - - - Characters - - - - Locations - - - - Timeline - - - - Objects - - - - Entities - - + Title Page - - - Chapter 1 - - + Chapter 1 - + Scene 1.1 - + Scene 1.2 - + Scene 1.3 - - - Chapter 2 - - + Chapter 2 - + Scene 2.1 - + Scene 2.2 - + Scene 2.3 - - - Chapter 3 - - + Chapter 3 - + Scene 3.1 - + Scene 3.2 - + Scene 3.3 + + + Plot + + + + Main Plot + + + + Characters + + + + Protagonist + + + + Locations + + + + Main Location + + + + Archive + + + + Trash +
diff --git a/tests/reference/coreProject_NewCustomB_nwProject.nwx b/tests/reference/coreProject_NewCustomB_nwProject.nwx index bca6ea80..12f911cd 100644 --- a/tests/reference/coreProject_NewCustomB_nwProject.nwx +++ b/tests/reference/coreProject_NewCustomB_nwProject.nwx @@ -1,5 +1,5 @@ - + Test Custom Test Novel @@ -29,74 +29,82 @@
- New + New Note Draft Finished - New + New Minor Major Main - + Novel - - - Plot - - - - Characters - - - - Locations - - - - Timeline - - - - Objects - - - - Entities - - + Title Page - + Scene 1 - + Scene 2 - + Scene 3 - + Scene 4 - + Scene 5 - + Scene 6 + + + Plot + + + + Main Plot + + + + Characters + + + + Protagonist + + + + Locations + + + + Main Location + + + + Archive + + + + Trash +
diff --git a/tests/reference/coreProject_NewFile_nwProject.nwx b/tests/reference/coreProject_NewFile_nwProject.nwx index d253ebcc..19a2f4bf 100644 --- a/tests/reference/coreProject_NewFile_nwProject.nwx +++ b/tests/reference/coreProject_NewFile_nwProject.nwx @@ -1,8 +1,9 @@ - + New Project - + New Novel + Jane Doe 2 1 0 diff --git a/tests/reference/coreProject_NewMinimal_nwProject.nwx b/tests/reference/coreProject_NewMinimal_nwProject.nwx index a6711a84..422bb6b2 100644 --- a/tests/reference/coreProject_NewMinimal_nwProject.nwx +++ b/tests/reference/coreProject_NewMinimal_nwProject.nwx @@ -1,5 +1,5 @@ - + New Project @@ -44,33 +44,33 @@ Novel - - - Plot - - - - Characters - - - - World - - + Title Page - - - New Chapter - - + New Chapter - + New Scene + + + Plot + + + + Characters + + + + Locations + + + + Archive + diff --git a/tests/reference/coreProject_NewRoot_nwProject.nwx b/tests/reference/coreProject_NewRoot_nwProject.nwx index 2ab62301..cd25c1cf 100644 --- a/tests/reference/coreProject_NewRoot_nwProject.nwx +++ b/tests/reference/coreProject_NewRoot_nwProject.nwx @@ -1,8 +1,9 @@ - + New Project - + New Novel + Jane Doe 2 1 0 @@ -82,11 +83,11 @@ - Character + Characters - World + Locations @@ -94,15 +95,15 @@ - Object + Objects - Custom1 + Custom - Custom2 + Custom diff --git a/tests/reference/guiEditor_Main_Final_nwProject.nwx b/tests/reference/guiEditor_Main_Final_nwProject.nwx index c4ba847c..a47d454d 100644 --- a/tests/reference/guiEditor_Main_Final_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Final_nwProject.nwx @@ -1,9 +1,10 @@ - + New Project - - 5 + New Novel + Jane Doe + 4 2 3 @@ -15,8 +16,8 @@ True 000000000000f None - 126 - 99 + 129 + 102 27 @@ -45,7 +46,7 @@ Novel - + Title Page diff --git a/tests/reference/guiEditor_Main_Initial_nwProject.nwx b/tests/reference/guiEditor_Main_Initial_nwProject.nwx index 1a5fd5be..03313570 100644 --- a/tests/reference/guiEditor_Main_Initial_nwProject.nwx +++ b/tests/reference/guiEditor_Main_Initial_nwProject.nwx @@ -1,9 +1,10 @@ - + New Project - - 3 + New Novel + Jane Doe + 2 1 0 @@ -15,8 +16,8 @@ True None None - 6 - 6 + 9 + 9 0 @@ -45,7 +46,7 @@ Novel - + Title Page diff --git a/tests/reference/guiProjSettings_Dialog_nwProject.nwx b/tests/reference/guiProjSettings_Dialog_nwProject.nwx index 326c63e5..f12c1dc2 100644 --- a/tests/reference/guiProjSettings_Dialog_nwProject.nwx +++ b/tests/reference/guiProjSettings_Dialog_nwProject.nwx @@ -1,11 +1,11 @@ - + Project Name Project Title Jane Doe John Doh - 2 + 1 1 0 @@ -17,8 +17,8 @@ True None None - 6 - 6 + 9 + 9 0 B @@ -51,7 +51,7 @@ Novel - + Title Page diff --git a/tests/test_core/test_core_index.py b/tests/test_core/test_core_index.py index c3e6ef47..93ec35c6 100644 --- a/tests/test_core/test_core_index.py +++ b/tests/test_core/test_core_index.py @@ -280,7 +280,7 @@ def testCoreIndex_ScanText(nwMinimal, mockGUI): assert theIndex.scanText(xHandle, "Hello World!") is False # Create the archive root - aHandle = theProject.newRoot("Archive", nwItemClass.ARCHIVE) + aHandle = theProject.newRoot(nwItemClass.ARCHIVE) assert theProject.projTree[aHandle] is not None xItem.setParent(aHandle) theProject.projTree.updateItemData(xItem.itemHandle) diff --git a/tests/test_core/test_core_project.py b/tests/test_core/test_core_project.py index 55c18e65..e6e5092d 100644 --- a/tests/test_core/test_core_project.py +++ b/tests/test_core/test_core_project.py @@ -26,7 +26,7 @@ from shutil import copyfile from zipfile import ZipFile from lxml import etree -from tools import cmpFiles, writeFile, readFile +from tools import cmpFiles, writeFile, readFile, buildTestProject, XML_IGNORE from mock import causeOSError from novelwriter.core.project import NWProject @@ -67,7 +67,7 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.saveProject() is True assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert theProject.projChanged is False # Open a second time @@ -77,7 +77,7 @@ def testCoreProject_NewMinimal(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.saveProject() is True assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # END Test testCoreProject_NewMinimal @@ -103,13 +103,10 @@ def testCoreProject_NewCustomA(fncDir, outDir, refDir, mockGUI, mockRnd): nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, - nwItemClass.TIMELINE, - nwItemClass.OBJECT, - nwItemClass.ENTITY, ], + "addNotes": True, "numChapters": 3, "numScenes": 3, - "chFolders": True, } theProject = NWProject(mockGUI) @@ -118,7 +115,7 @@ def testCoreProject_NewCustomA(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # END Test testCoreProject_NewCustomA @@ -144,13 +141,10 @@ def testCoreProject_NewCustomB(fncDir, outDir, refDir, mockGUI, mockRnd): nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, - nwItemClass.TIMELINE, - nwItemClass.OBJECT, - nwItemClass.ENTITY, ], + "addNotes": True, "numChapters": 0, "numScenes": 6, - "chFolders": True, } theProject = NWProject(mockGUI) @@ -159,7 +153,7 @@ def testCoreProject_NewCustomB(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # END Test testCoreProject_NewCustomB @@ -258,28 +252,28 @@ def testCoreProject_NewRoot(fncDir, outDir, refDir, mockGUI, mockRnd): compFile = os.path.join(refDir, "coreProject_NewRoot_nwProject.nwx") theProject = NWProject(mockGUI) + buildTestProject(theProject, fncDir) - assert theProject.newProject({"projPath": fncDir}) is True assert theProject.setProjectPath(fncDir) is True assert theProject.saveProject() is True assert theProject.closeProject() is True assert theProject.openProject(projFile) is True - assert isinstance(theProject.newRoot("Novel", nwItemClass.NOVEL), str) - assert isinstance(theProject.newRoot("Plot", nwItemClass.PLOT), str) - assert isinstance(theProject.newRoot("Character", nwItemClass.CHARACTER), str) - assert isinstance(theProject.newRoot("World", nwItemClass.WORLD), str) - assert isinstance(theProject.newRoot("Timeline", nwItemClass.TIMELINE), str) - assert isinstance(theProject.newRoot("Object", nwItemClass.OBJECT), str) - assert isinstance(theProject.newRoot("Custom1", nwItemClass.CUSTOM), str) - assert isinstance(theProject.newRoot("Custom2", nwItemClass.CUSTOM), str) + assert isinstance(theProject.newRoot(nwItemClass.NOVEL), str) + assert isinstance(theProject.newRoot(nwItemClass.PLOT), str) + assert isinstance(theProject.newRoot(nwItemClass.CHARACTER), str) + assert isinstance(theProject.newRoot(nwItemClass.WORLD), str) + assert isinstance(theProject.newRoot(nwItemClass.TIMELINE), str) + assert isinstance(theProject.newRoot(nwItemClass.OBJECT), str) + assert isinstance(theProject.newRoot(nwItemClass.CUSTOM), str) + assert isinstance(theProject.newRoot(nwItemClass.CUSTOM), str) assert theProject.projChanged is True assert theProject.saveProject() is True assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert theProject.projChanged is False # END Test testCoreProject_NewRoot @@ -294,8 +288,8 @@ def testCoreProject_NewFile(fncDir, outDir, refDir, mockGUI, mockRnd): compFile = os.path.join(refDir, "coreProject_NewFile_nwProject.nwx") theProject = NWProject(mockGUI) + buildTestProject(theProject, fncDir) - assert theProject.newProject({"projPath": fncDir}) is True assert theProject.setProjectPath(fncDir) is True assert theProject.saveProject() is True assert theProject.closeProject() is True @@ -308,7 +302,7 @@ def testCoreProject_NewFile(fncDir, outDir, refDir, mockGUI, mockRnd): assert theProject.closeProject() is True copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) assert theProject.projChanged is False # END Test testCoreProject_NewFile @@ -489,7 +483,7 @@ def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir): assert theProject.saveProject() is True assert theProject.saveCount == saveCount + 1 assert theProject.autoCount == autoCount - assert cmpFiles(testFile, compFile, [2, 6, 7, 8, 9]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # Check that a second save creates a .bak file assert os.path.isfile(backFile) is True @@ -500,7 +494,7 @@ def testCoreProject_Save(monkeypatch, nwMinimal, mockGUI, refDir): assert theProject.saveProject(autoSave=True) is True assert theProject.saveCount == saveCount assert theProject.autoCount == autoCount + 1 - assert cmpFiles(testFile, compFile, [2, 6, 7, 8, 9]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) # Close test project assert theProject.closeProject() @@ -677,7 +671,7 @@ def testCoreProject_StatusImport(mockGUI, fncDir, mockRnd): """Test the status and importance flag handling. """ theProject = NWProject(mockGUI) - assert theProject.newProject({"projPath": fncDir}) is True + buildTestProject(theProject, fncDir) statusKeys = ["s000008", "s000009", "s00000a", "s00000b"] importKeys = ["i00000c", "i00000d", "i00000e", "i00000f"] @@ -798,7 +792,7 @@ def testCoreProject_Methods(monkeypatch, mockGUI, tmpDir, fncDir, mockRnd): """Test other project class methods and functions. """ theProject = NWProject(mockGUI) - assert theProject.newProject({"projPath": fncDir}) is True + buildTestProject(theProject, fncDir) # Setting project path assert theProject.setProjectPath(None) @@ -1178,10 +1172,6 @@ def testCoreProject_LegacyData(monkeypatch, mockGUI, fncDir): theProject = NWProject(mockGUI) theProject.setProjectPath(fncDir) - # assert theProject.newProject({"projPath": fncDir}) - # assert theProject.saveProject() - # assert theProject.closeProject() - # Check behaviour of deprecated files function on OSError tstFile = os.path.join(fncDir, "ToC.json") writeFile(tstFile, "stuff") diff --git a/tests/test_dialogs/test_dlg_docmerge.py b/tests/test_dialogs/test_dlg_docmerge.py index f635be4a..a82c77bd 100644 --- a/tests/test_dialogs/test_dlg_docmerge.py +++ b/tests/test_dialogs/test_dlg_docmerge.py @@ -23,7 +23,7 @@ import os import pytest from mock import causeOSError -from tools import getGuiItem, readFile, writeFile +from tools import getGuiItem, readFile, writeFile, buildTestProject from PyQt5.QtWidgets import QAction, QMessageBox, QDialog @@ -41,7 +41,7 @@ def testDlgMerge_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) # Create a new project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) # Handles for new objects hNovelRoot = "0000000000008" diff --git a/tests/test_dialogs/test_dlg_docsplit.py b/tests/test_dialogs/test_dlg_docsplit.py index 19988c0b..90e3375d 100644 --- a/tests/test_dialogs/test_dlg_docsplit.py +++ b/tests/test_dialogs/test_dlg_docsplit.py @@ -23,7 +23,7 @@ import os import pytest from mock import causeOSError -from tools import getGuiItem, readFile, writeFile +from tools import getGuiItem, readFile, writeFile, buildTestProject from PyQt5.QtWidgets import QAction, QMessageBox, QDialog @@ -42,7 +42,7 @@ def testDlgSplit_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Ok) # Create a new project - assert nwGUI.newProject({"projPath": fncProj}) is True + buildTestProject(nwGUI, fncProj) # Handles for new objects hNovelRoot = "0000000000008" diff --git a/tests/test_dialogs/test_dlg_itemeditor.py b/tests/test_dialogs/test_dlg_itemeditor.py index ebd71d6c..c221138e 100644 --- a/tests/test_dialogs/test_dlg_itemeditor.py +++ b/tests/test_dialogs/test_dlg_itemeditor.py @@ -21,7 +21,7 @@ along with this program. If not, see . import pytest -from tools import getGuiItem +from tools import getGuiItem, buildTestProject from PyQt5.QtWidgets import QAction, QDialog, QMessageBox @@ -48,7 +48,7 @@ def testDlgItemEditor_Dialog(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): assert nwGUI.editItem() is False # Create and Open Project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) tHandle = "000000000000f" # No Selection @@ -99,7 +99,7 @@ def testDlgItemEditor_Novel(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # Create Project and Open Document - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) tHandle = "000000000000f" assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New" @@ -156,7 +156,7 @@ def testDlgItemEditor_Note(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # Create Project and Open Document - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) assert nwGUI.theProject.statusItems.name(statusKeys[0]) == "New" assert nwGUI.theProject.statusItems.name(statusKeys[1]) == "Note" assert nwGUI.theProject.importItems.name(importKeys[0]) == "New" @@ -209,7 +209,7 @@ def testDlgItemEditor_Folder(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): monkeypatch.setattr(GuiProjectTree, "hasFocus", lambda *a: True) # Create Project and Open Document - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) # Edit a Folder itemEdit = GuiItemEditor(nwGUI, "000000000000d") diff --git a/tests/test_dialogs/test_dlg_projsettings.py b/tests/test_dialogs/test_dlg_projsettings.py index 54827cfd..f193194a 100644 --- a/tests/test_dialogs/test_dlg_projsettings.py +++ b/tests/test_dialogs/test_dlg_projsettings.py @@ -23,7 +23,7 @@ import os import pytest from shutil import copyfile -from tools import cmpFiles, getGuiItem +from tools import cmpFiles, getGuiItem, buildTestProject from PyQt5.QtGui import QColor from PyQt5.QtCore import Qt @@ -57,7 +57,7 @@ def testDlgProjSettings_Dialog( assert getGuiItem("GuiProjectSettings") is None # Create new project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) nwGUI.mainConf.backupPath = fncDir nwGUI.theProject.setSpellLang("en") @@ -81,7 +81,7 @@ def testDlgProjSettings_Dialog( # ============ assert projEdit.tabMain.editName.text() == "New Project" - assert projEdit.tabMain.editTitle.text() == "" + assert projEdit.tabMain.editTitle.text() == "New Novel" assert projEdit.tabMain.editAuthors.toPlainText() == "Jane Smith\nJohn Smith" assert projEdit.tabMain.spellLang.currentData() == "en" assert projEdit.tabMain.doBackup.isChecked() is False @@ -90,6 +90,7 @@ def testDlgProjSettings_Dialog( projEdit.tabMain.editName.setText("") for c in "Project Name": qtbot.keyClick(projEdit.tabMain.editName, c, delay=typeDelay) + projEdit.tabMain.editTitle.setText("") for c in "Project Title": qtbot.keyClick(projEdit.tabMain.editTitle, c, delay=typeDelay) diff --git a/tests/test_gui/test_gui_guimain.py b/tests/test_gui/test_gui_guimain.py index ddb4f09b..e0d7e2ec 100644 --- a/tests/test_gui/test_gui_guimain.py +++ b/tests/test_gui/test_gui_guimain.py @@ -23,7 +23,7 @@ import os import pytest from shutil import copyfile -from tools import cmpFiles +from tools import cmpFiles, buildTestProject, XML_IGNORE, writeFile from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QMessageBox, QDialog @@ -32,6 +32,7 @@ from novelwriter.gui import ( GuiDocEditor, GuiProjectTree, GuiNovelTree, GuiOutline ) from novelwriter.enum import nwItemType, nwWidget +from novelwriter.tools import GuiProjectWizard from novelwriter.dialogs.itemeditor import GuiItemEditor keyDelay = 2 @@ -70,15 +71,52 @@ def testGuiMain_ProjectBlocker(monkeypatch, nwGUI): # END Test testGuiMain_NoProject +@pytest.mark.gui +def testGuiMain_NewProject(monkeypatch, nwGUI, fncProj): + """Test creating a new project. + """ + monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) + monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) + + # 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: + nwGUI.hasProject = True + mp.setattr(QMessageBox, "question", lambda *a: QMessageBox.No) + assert nwGUI.newProject(projData={"projPath": fncProj}) is False + + # No project path + assert nwGUI.newProject(projData={}) is False + + # Project file already exists + projFile = os.path.join(fncProj, nwGUI.theProject.projFile) + writeFile(projFile, "Stuff") + assert nwGUI.newProject(projData={"projPath": fncProj}) is False + os.unlink(projFile) + + # An unreachable path should also fail + projPath = os.path.join(fncProj, "stuff", "stuff", "stuff") + assert nwGUI.newProject(projData={"projPath": projPath}) is False + + # This one should work just fine + assert nwGUI.newProject(projData={"projPath": fncProj}) is True + assert os.path.isfile(os.path.join(fncProj, nwGUI.theProject.projFile)) + assert os.path.isdir(os.path.join(fncProj, "content")) + +# END Test testGuiMain_NewProject + + @pytest.mark.gui def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """Test handling of project tree items based on GUI focus states. """ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) - assert nwGUI.newProject({"projPath": fncProj}) is True - assert nwGUI.saveProject() is True - # assert False + buildTestProject(nwGUI, fncProj) sHandle = "000000000000f" assert nwGUI.openSelectedItem() is False @@ -139,7 +177,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock monkeypatch.setattr(GuiDocEditor, "hasFocus", lambda *a: True) # Create new, save, close project - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) assert nwGUI.saveProject() assert nwGUI.closeProject() @@ -160,7 +198,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock testFile = os.path.join(outDir, "guiEditor_Main_Initial_nwProject.nwx") compFile = os.path.join(refDir, "guiEditor_Main_Initial_nwProject.nwx") copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) qtbot.wait(stepDelay) # qtbot.stopForInteraction() @@ -178,9 +216,9 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock assert nwGUI.theProject.projMeta == os.path.join(fncProj, "meta") assert nwGUI.theProject.projFile == "nwProject.nwx" assert nwGUI.theProject.projName == "New Project" - assert nwGUI.theProject.bookTitle == "" - assert len(nwGUI.theProject.bookAuthors) == 0 - assert not nwGUI.theProject.spellCheck + assert nwGUI.theProject.bookTitle == "New Novel" + assert len(nwGUI.theProject.bookAuthors) == 1 + assert nwGUI.theProject.spellCheck is False # Check that tree items have been created assert nwGUI.treeView._getTreeItem("0000000000008") is not None @@ -438,7 +476,7 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock testFile = os.path.join(outDir, "guiEditor_Main_Final_nwProject.nwx") compFile = os.path.join(refDir, "guiEditor_Main_Final_nwProject.nwx") copyfile(projFile, testFile) - assert cmpFiles(testFile, compFile, [2, 6, 7, 8]) + assert cmpFiles(testFile, compFile, ignoreStart=XML_IGNORE) projFile = os.path.join(fncProj, "content", "000000000000f.nwd") testFile = os.path.join(outDir, "guiEditor_Main_Final_000000000000f.nwd") @@ -467,3 +505,52 @@ def testGuiMain_Editing(qtbot, monkeypatch, nwGUI, fncProj, refDir, outDir, mock # qtbot.stopForInteraction() # END Test testGuiMain_Editing + + +@pytest.mark.gui +def testGuiMain_FocusFullMode(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): + """Test toggling focus mode in main window. + """ + monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) + + buildTestProject(nwGUI, fncProj) + assert nwGUI.isFocusMode is False + + # Focus Mode + # ========== + + # No document open, so not allowing focus mode + assert nwGUI.toggleFocusMode() is False + + # Open a file in editor and viewer + assert nwGUI.openDocument("000000000000f") + assert nwGUI.viewDocument("000000000000f") + + # Enable focus mode + assert nwGUI.toggleFocusMode() is True + assert nwGUI.treePane.isVisible() is False + assert nwGUI.statusBar.isVisible() is False + assert nwGUI.mainMenu.isVisible() is False + assert nwGUI.viewsBar.isVisible() is False + assert nwGUI.splitView.isVisible() is False + + # Disable focus mode + assert nwGUI.toggleFocusMode() is True + assert nwGUI.treePane.isVisible() is True + assert nwGUI.statusBar.isVisible() is True + assert nwGUI.mainMenu.isVisible() is True + assert nwGUI.viewsBar.isVisible() is True + assert nwGUI.splitView.isVisible() is True + + # Full Screen Mode + # ================ + + assert nwGUI.mainConf.isFullScreen is False + nwGUI.toggleFullScreenMode() + assert nwGUI.mainConf.isFullScreen is True + nwGUI.toggleFullScreenMode() + assert nwGUI.mainConf.isFullScreen is False + + # qtbot.stopForInteraction() + +# END Test testGuiMain_FocusFullMode diff --git a/tests/test_gui/test_gui_mainmenu.py b/tests/test_gui/test_gui_mainmenu.py index 815c8566..801abd68 100644 --- a/tests/test_gui/test_gui_mainmenu.py +++ b/tests/test_gui/test_gui_mainmenu.py @@ -26,7 +26,7 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QTextCursor, QTextBlock from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox -from tools import writeFile +from tools import writeFile, buildTestProject from novelwriter.gui.doceditor import GuiDocEditor from novelwriter.enum import nwDocAction, nwDocInsert @@ -465,7 +465,7 @@ def testGuiMenu_Insert(qtbot, monkeypatch, nwGUI, fncDir, fncProj, mockRnd): monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) assert nwGUI.treeView._getTreeItem("000000000000f") is not None assert nwGUI.openDocument("000000000000f") is True diff --git a/tests/test_gui/test_gui_projtree.py b/tests/test_gui/test_gui_projtree.py index af851138..5d3354f9 100644 --- a/tests/test_gui/test_gui_projtree.py +++ b/tests/test_gui/test_gui_projtree.py @@ -22,6 +22,8 @@ along with this program. If not, see . import pytest import os +from tools import buildTestProject + from PyQt5.QtWidgets import QAction, QMessageBox from novelwriter.guimain import GuiMain @@ -47,7 +49,7 @@ def testGuiProjTree_NewItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockRnd) # Create a project prjDir = os.path.join(fncDir, "project") - assert nwGUI.newProject({"projPath": prjDir}) is True + buildTestProject(nwGUI, prjDir) # No itemType set nwTree.clearSelection() @@ -155,7 +157,7 @@ def testGuiProjTree_MoveItems(qtbot, monkeypatch, nwGUI, fncDir, mockRnd): # Create a project prjDir = os.path.join(fncDir, "project") - assert nwGUI.newProject({"projPath": prjDir}) is True + buildTestProject(nwGUI, prjDir) # Move Documents # ============== @@ -283,7 +285,7 @@ def testGuiProjTree_DeleteItems(qtbot, caplog, monkeypatch, nwGUI, fncDir, mockR # Create a project prjDir = os.path.join(fncDir, "project") - assert nwGUI.newProject({"projPath": prjDir}) is True + buildTestProject(nwGUI, prjDir) # Try emptying the trash already now, when there is no trash folder assert nwTree.emptyTrash() is False diff --git a/tests/test_gui/test_gui_statusbar.py b/tests/test_gui/test_gui_statusbar.py index 8993a2e8..51e9c70b 100644 --- a/tests/test_gui/test_gui_statusbar.py +++ b/tests/test_gui/test_gui_statusbar.py @@ -22,6 +22,8 @@ along with this program. If not, see . import time import pytest +from tools import buildTestProject + from PyQt5.QtWidgets import QMessageBox from novelwriter.core import NWDoc @@ -34,7 +36,7 @@ def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): """ monkeypatch.setattr(QMessageBox, "question", lambda *a: QMessageBox.Yes) - assert nwGUI.newProject({"projPath": fncProj}) is True + buildTestProject(nwGUI, fncProj) cHandle = nwGUI.theProject.newFile("A Note", "000000000000a") newDoc = NWDoc(nwGUI.theProject, cHandle) newDoc.writeDocument("# A Note\n\n") @@ -89,10 +91,10 @@ def testGuiStatusBar_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): # Project Stats nwGUI.statusBar.mainConf.incNotesWCount = False nwGUI._updateStatusWordCount() - assert nwGUI.statusBar.statsText.text() == "Words: 6 (+6)" + assert nwGUI.statusBar.statsText.text() == "Words: 9 (+9)" nwGUI.statusBar.mainConf.incNotesWCount = True nwGUI._updateStatusWordCount() - assert nwGUI.statusBar.statsText.text() == "Words: 8 (+8)" + assert nwGUI.statusBar.statsText.text() == "Words: 11 (+11)" # qtbot.stopForInteraction() diff --git a/tests/test_tools/test_tools_lipsum.py b/tests/test_tools/test_tools_lipsum.py index 7d6c08f9..629deb56 100644 --- a/tests/test_tools/test_tools_lipsum.py +++ b/tests/test_tools/test_tools_lipsum.py @@ -21,7 +21,7 @@ along with this program. If not, see . import pytest -from tools import getGuiItem +from tools import getGuiItem, buildTestProject from PyQt5.QtWidgets import QAction, QMessageBox @@ -40,7 +40,7 @@ def testToolLipsum_Main(qtbot, monkeypatch, nwGUI, fncProj, mockRnd): assert getGuiItem("GuiLipsum") is None # Create a new project - assert nwGUI.newProject({"projPath": fncProj}) is True + buildTestProject(nwGUI, fncProj) assert nwGUI.openDocument("000000000000f") is True assert len(nwGUI.docEditor.getText()) == 15 diff --git a/tests/test_tools/test_tools_projwizard.py b/tests/test_tools/test_tools_projwizard.py index ef4c31cd..8839964e 100644 --- a/tests/test_tools/test_tools_projwizard.py +++ b/tests/test_tools/test_tools_projwizard.py @@ -205,14 +205,11 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType): customPage.addPlot.setChecked(True) customPage.addChar.setChecked(True) customPage.addWorld.setChecked(True) - customPage.addTime.setChecked(True) - customPage.addObject.setChecked(True) - customPage.addEntity.setChecked(True) + customPage.addNotes.setChecked(True) if prjType == "custom2": customPage.numChapters.setValue(0) customPage.numScenes.setValue(10) - customPage.chFolders.setChecked(False) qtbot.wait(stepDelay) qtbot.mouseClick(nwWiz.button(QWizard.NextButton), Qt.LeftButton) @@ -240,23 +237,20 @@ def testToolProjectWizard_Run(qtbot, monkeypatch, nwGUI, fncDir, prjType): nwItemClass.PLOT, nwItemClass.CHARACTER, nwItemClass.WORLD, - nwItemClass.TIMELINE, - nwItemClass.OBJECT, - nwItemClass.ENTITY, ] if prjType == "custom1": assert projData["numChapters"] == 5 assert projData["numScenes"] == 5 - assert projData["chFolders"] + assert projData["addNotes"] is True else: assert projData["numChapters"] == 0 assert projData["numScenes"] == 10 - assert not projData["chFolders"] + assert projData["addNotes"] is True else: assert projData["addRoots"] == [] assert projData["numChapters"] == 0 assert projData["numScenes"] == 0 - assert not projData["chFolders"] + assert projData["addNotes"] is False # Cleanup nwWiz.reject() diff --git a/tests/test_tools/test_tools_writingstats.py b/tests/test_tools/test_tools_writingstats.py index cffef9e6..b7358b20 100644 --- a/tests/test_tools/test_tools_writingstats.py +++ b/tests/test_tools/test_tools_writingstats.py @@ -23,8 +23,8 @@ import pytest import json import os -from tools import getGuiItem, writeFile from mock import causeOSError +from tools import getGuiItem, writeFile, buildTestProject from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QAction, QFileDialog, QMessageBox @@ -48,7 +48,7 @@ def testToolWritingStats_Main(qtbot, monkeypatch, nwGUI, fncDir, fncProj): monkeypatch.setattr(QMessageBox, "critical", lambda *a: QMessageBox.Yes) # Create a project to work on - assert nwGUI.newProject({"projPath": fncProj}) + buildTestProject(nwGUI, fncProj) qtbot.wait(100) assert nwGUI.saveProject() sessFile = os.path.join(fncProj, "meta", nwFiles.SESS_STATS) diff --git a/tests/tools.py b/tests/tools.py index bd417aae..fcdd3817 100644 --- a/tests/tools.py +++ b/tests/tools.py @@ -20,10 +20,13 @@ along with this program. If not, see . """ import os +import time import shutil from PyQt5.QtWidgets import qApp +XML_IGNORE = ("> By Jane DOe <<\n") + + aDoc = NWDoc(theProject, xHandle[7]) + aDoc.writeDocument("## %s\n\n" % theProject.tr("New Chapter")) + + aDoc = NWDoc(theProject, xHandle[8]) + aDoc.writeDocument("### %s\n\n" % theProject.tr("New Scene")) + + theProject.projOpened = time.time() + theProject.setProjectChanged(True) + theProject.saveProject(autoSave=True) + + if theGUI is not None: + theGUI.hasProject = True + theGUI.rebuildTrees() + theGUI.rebuildIndex(beQuiet=True) + + return