diff --git a/docs/source/int_customise.rst b/docs/source/int_customise.rst index e2b6cc18..9cb4819c 100644 --- a/docs/source/int_customise.rst +++ b/docs/source/int_customise.rst @@ -19,22 +19,34 @@ Spell Check Dictionaries novelWriter uses Enchant_ as the spell checking tool. Depending on your operating system, it may or may not load installed spell check dictionaries. -Linux - On Linux, you generally only have to install hunspell or aspell dictionaries on your system like - you do for other applications. See your distro's documentation for how to do this. These - dictionaries should then show up as available spell check languages in novelWriter. +Linux and MacOS +--------------- + +On Linux and MacOS, you generally only have to install hunspell or aspell dictionaries on your +system like you do for other applications. See your distro or OS documentation for how to do this. +These dictionaries should then show up as available spell check languages in novelWriter. Windows - For Windows, English is included with the installation. For other languages you have to download - and add dictionaries yourself. You can find the various dictionaries on the `Free Desktop`_ - website. You should find a folder for your language, if it is available at all, and download the - files ending with ``.aff`` and ``.dic``. These files must then be copied to the following - location: +------- - ``C:\Users\\AppData\Local\enchant\hunspell`` +For Windows, English is included with the installation. For other languages you have to download +and add dictionaries yourself. You can find the various dictionaries on the `Free Desktop`_ +website. You should find a folder for your language, if it is available at all, and download the +files ending with ``.aff`` and ``.dic``. These files must then be copied to the following location: - This assumes your user profile is stored at ``C:\Users\``. The last one or two folders may - not exist, so you may need to create them. +``C:\Users\\AppData\Local\enchant\hunspell`` + +This assumes your user profile is stored at ``C:\Users\``. The last one or two folders may +not exist, so you may need to create them. + +.. note:: + + The Free Desktop link points to a repository, and what may look like file links inside the + dictionary folder are actually links to web pages. If you right-click and download those, you + get HTML files, not dictionaries! + + In order to download the actual dictionary files, right-click the "plain" label at the end of + each line and download that. .. _a_custom_theme: diff --git a/docs/source/int_howto.rst b/docs/source/int_howto.rst index 09f079fd..cccdf99d 100644 --- a/docs/source/int_howto.rst +++ b/docs/source/int_howto.rst @@ -51,7 +51,7 @@ Merge Multiple Documents Into One If you need to merge a set of documents in your project into a single document, you can achieve this by first making a new folder for just that purpose, and drag all the files you want merged into this folder. Then you can right click the folder, select :guilabel:`Transform` and -:guilabel:`Merge Documents in FOlder`. +:guilabel:`Merge Documents in Folder`. In the dialog that pops up, the documents will be in the same order as in the folder, but you can also rearrange them here of you wish. diff --git a/i18n/nw_base.ts b/i18n/nw_base.ts index 6777e15d..8bd79c2e 100644 --- a/i18n/nw_base.ts +++ b/i18n/nw_base.ts @@ -3352,44 +3352,44 @@ - + There is currently no Trash folder in this project. - + The Trash folder is already empty. - + Empty Trash - + Permanently delete {0} file(s) from Trash? - - + + Delete - + Move '{0}' to Trash? - + Root folders can only be deleted when they are empty. - + Permanently delete '{0}'? @@ -3405,7 +3405,7 @@ - Change Label + Rename diff --git a/i18n/nw_de_DE.ts b/i18n/nw_de_DE.ts index 42520e2a..f2b5b5df 100644 --- a/i18n/nw_de_DE.ts +++ b/i18n/nw_de_DE.ts @@ -3352,44 +3352,44 @@ Neuer Ordner - + There is currently no Trash folder in this project. Derzeit gibt es keinen Papierkorb für dieses Projekt. - + The Trash folder is already empty. Papierkorb ist bereits leer. - + Empty Trash Papierkorb leeren - + Permanently delete {0} file(s) from Trash? {0} Element(e) endgültig löschen? - - + + Delete Löschen - + Move '{0}' to Trash? „{0}“ in den Papierkorb verschieben? - + Root folders can only be deleted when they are empty. Hauptordner können nur gelöscht werden, wenn sie leer sind. - + Permanently delete '{0}'? „{0}“ endgültig löschen? diff --git a/i18n/nw_en_US.ts b/i18n/nw_en_US.ts index dc1986fc..8f7dfdee 100644 --- a/i18n/nw_en_US.ts +++ b/i18n/nw_en_US.ts @@ -3352,44 +3352,44 @@ New Folder - + There is currently no Trash folder in this project. There is currently no Trash folder in this project. - + The Trash folder is already empty. The Trash folder is already empty. - + Empty Trash Empty Trash - + Permanently delete {0} file(s) from Trash? Permanently delete {0} file(s) from Trash? - - + + Delete Delete - + Move '{0}' to Trash? Move '{0}' to Trash? - + Root folders can only be deleted when they are empty. Root folders can only be deleted when they are empty. - + Permanently delete '{0}'? Permanently delete '{0}'? diff --git a/i18n/nw_es_419.ts b/i18n/nw_es_419.ts index bf5ca215..25887cf4 100644 --- a/i18n/nw_es_419.ts +++ b/i18n/nw_es_419.ts @@ -1925,7 +1925,7 @@ Check Spelling - Comprobar Ortografía + Comprobar la Ortografía @@ -3352,44 +3352,44 @@ Nueva Carpeta - + There is currently no Trash folder in this project. No hay actualmente una carpeta Papelera en este proyecto. - + The Trash folder is already empty. La carpeta Papelera ya está vacía. - + Empty Trash Vaciar la Papelera - + Permanently delete {0} file(s) from Trash? ¿Eliminar {0} archivo(s) permanentemente de la Papelera? - - + + Delete Eliminar - + Move '{0}' to Trash? ¿Mover '{0}' a la Papelera? - + Root folders can only be deleted when they are empty. Las carpetas raíz sólo pueden eliminarse si están vacías. - + Permanently delete '{0}'? ¿Eliminar Permanentemente '{0}'? diff --git a/i18n/nw_it_IT.ts b/i18n/nw_it_IT.ts index e01cb77a..8a2ddc2f 100644 --- a/i18n/nw_it_IT.ts +++ b/i18n/nw_it_IT.ts @@ -3352,44 +3352,44 @@ Nuova cartella - + There is currently no Trash folder in this project. Al momento non c'è una cartella Cestino in questo progetto. - + The Trash folder is already empty. La cartella Cestino è già vuota. - + Empty Trash Svuota il cestino - + Permanently delete {0} file(s) from Trash? Eliminare definitivamente {0} file(s) dal cestino? - - + + Delete Elimina - + Move '{0}' to Trash? Spostare '{0}' nel Cestino? - + Root folders can only be deleted when they are empty. Le cartelle radice possono essere eliminate solo quando sono vuote. - + Permanently delete '{0}'? Eliminare definitivamente '{0}'? diff --git a/i18n/nw_nb_NO.ts b/i18n/nw_nb_NO.ts index 33c46f86..36c0db11 100644 --- a/i18n/nw_nb_NO.ts +++ b/i18n/nw_nb_NO.ts @@ -3352,44 +3352,44 @@ Ny mappe - + There is currently no Trash folder in this project. Det er for øyeblikket ingen papirkurv i dette prosjektet. - + The Trash folder is already empty. Papirkurven er allerede tom. - + Empty Trash Tøm papirkurven - + Permanently delete {0} file(s) from Trash? Vil du slette {0} filer i papirkurven for godt? - - + + Delete Slett - + Move '{0}' to Trash? Vil du flytte filen "{0}" til søpla? - + Root folders can only be deleted when they are empty. Rotmapper kan bare slettes når de er tomme. - + Permanently delete '{0}'? Slette filen "{0}" for godt? diff --git a/i18n/nw_nl_NL.ts b/i18n/nw_nl_NL.ts index 249938ab..30926801 100644 --- a/i18n/nw_nl_NL.ts +++ b/i18n/nw_nl_NL.ts @@ -757,32 +757,32 @@ GuiDocEditFooter - + Status Status - + Line: {0} ({1}) Regel: {0} ({1}) - + Words: {0} ({1}) Woorden: {0} ({1}) - + Document size is {0} bytes Document grootte is {0} bytes - + Words: {0} selected Woorden: {0} geselecteerd - + Character count: {0} Aantal tekens: {0} @@ -790,22 +790,22 @@ GuiDocEditHeader - + Edit document label Bewerk document label - + Search document Doorzoek document - + Toggle Focus Mode Schakel focus modus in/uit - + Close the document Sluit het document @@ -813,58 +813,58 @@ GuiDocEditSearch - - + + Search Zoek - + Replace Vervang - + Case Sensitive Hoofdlettergevoelig - + Whole Words Only Alleen hele woorden - + RegEx Mode RegEx modus - + Loop Search Zoekopdracht lus - + Search Next File Doorzoek volgend bestand - + Preserve Case Behoud hoofd/kleine letters - + Close Search Zoekopdracht afsluiten - + Find in current document Zoeken in huidige document - + Find and replace in current document Zoek en vervang in huidig document @@ -2050,55 +2050,66 @@ GuiNovelToolBar - + Outline of {0} Omlijning van {0} - + Novel Root Roman Hoofdmap - + Refresh Verversen - + Last Column Laatste Kolom - + Hidden Verborgen - + Point of View Character Perspectief Karakter - + Focus Character Focus Karakter - + Novel Plot Roman Plot - + + + Column Size + Kolom grootte + + + More Options Meer Opties + + + Maximum column size in % + Maximum kolom grootte in % + GuiNovelTree - + No meta data Geen metadata @@ -3341,44 +3352,44 @@ Nieuwe map - + There is currently no Trash folder in this project. Er is momenteel geen Prullenbak map in dit project. - + The Trash folder is already empty. De Prullenbak map is al leeg. - + Empty Trash Prullenbak legen - + Permanently delete {0} file(s) from Trash? {0} bestand(en) permanent verwijderen uit de prullenbak? - - + + Delete Verwijderen - + Move '{0}' to Trash? Verplaats '{0}' naar Prullenbak? - + Root folders can only be deleted when they are empty. Root mappen kunnen alleen verwijderd worden wanneer ze leeg zijn. - + Permanently delete '{0}'? '{0}' permanent verwijderen? diff --git a/i18n/nw_pt_BR.ts b/i18n/nw_pt_BR.ts index 7a3d9602..50e0998d 100644 --- a/i18n/nw_pt_BR.ts +++ b/i18n/nw_pt_BR.ts @@ -3352,44 +3352,44 @@ Novo Diretório - + There is currently no Trash folder in this project. Não exite um diretório de Lixeira neste projeto. - + The Trash folder is already empty. O diretório de Lixeira já está vazio. - + Empty Trash Esvaziar a Lixeira - + Permanently delete {0} file(s) from Trash? Permanentemente remover {0} arquivo(s) da Lixeira? - - + + Delete Excluir - + Move '{0}' to Trash? Mover '{0}' para a Lixeira? - + Root folders can only be deleted when they are empty. Os diretórios-raiz só podem ser excluídos quando estiverem vazios. - + Permanently delete '{0}'? Excluir permanentemente '{0}? diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index 5c94c480..6ad9fca5 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -59,9 +59,9 @@ __license__ = "GPLv3" __author__ = "Veronica Berglyd Olsen" __maintainer__ = "Veronica Berglyd Olsen" __email__ = "code@vkbo.net" -__version__ = "2.1-alpha0" -__hexversion__ = "0x020100a0" -__date__ = "2023-02-12" +__version__ = "2.0.6" +__hexversion__ = "0x020006f0" +__date__ = "2023-02-26" __status__ = "Stable" __domain__ = "novelwriter.io" __url__ = "https://novelwriter.io" @@ -246,6 +246,8 @@ def main(sysArgs=None): nwApp.setApplicationName(CONFIG.appName) nwApp.setApplicationVersion(__version__) nwApp.setOrganizationDomain(__domain__) + nwApp.setOrganizationName(__domain__) + nwApp.setDesktopFileName(CONFIG.appName) # Connect the exception handler before making the main GUI sys.excepthook = exceptionHandler diff --git a/novelwriter/gui/doceditor.py b/novelwriter/gui/doceditor.py index 361b236e..a303162b 100644 --- a/novelwriter/gui/doceditor.py +++ b/novelwriter/gui/doceditor.py @@ -1359,7 +1359,7 @@ class GuiDocEditor(QTextEdit): if self._docHandle is None or self._nwItem is None: return - logger.debug("User selectee %d words", wCount) + logger.debug("User selected %d words", wCount) self.docFooter.updateCounts(wCount=wCount, cCount=cCount) self.wcTimerSel.stop() diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index df29903b..82b3c3a1 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -38,6 +38,7 @@ from PyQt5.QtWidgets import ( QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget ) +from novelwriter.core.item import NWItem from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwAlert, nwWidget from novelwriter.constants import nwHeaders, nwUnicode, trConst, nwLabels @@ -108,6 +109,9 @@ class GuiProjectView(QWidget): self.keyContext.setContext(Qt.WidgetShortcut) self.keyContext.activated.connect(lambda: self.projTree.openContextOnSelected()) + # Signals + self.selectedItemChanged.connect(self.projBar._treeSelectionChanged) + # Function Mappings self.emptyTrash = self.projTree.emptyTrash self.requestDeleteItem = self.projTree.requestDeleteItem @@ -418,6 +422,23 @@ class GuiProjectToolBar(QWidget): return + ## + # Slots + ## + + @pyqtSlot(str) + def _treeSelectionChanged(self, tHandle): + """Toggle the visibility of the new item enties for novel + documents. They should only be visible if novel documents can + actually be added. + """ + nwItem = self.theProject.tree[tHandle] + allowDoc = isinstance(nwItem, NWItem) and nwItem.documentAllowed() + self.aAddEmpty.setVisible(allowDoc) + self.aAddChap.setVisible(allowDoc) + self.aAddScene.setVisible(allowDoc) + return + # END Class GuiProjectToolBar @@ -1204,7 +1225,7 @@ class GuiProjectTree(QTreeWidget): # Edit Item Settings # ================== - aLabel = ctxMenu.addAction(self.tr("Change Label")) + aLabel = ctxMenu.addAction(self.tr("Rename")) aLabel.triggered.connect(lambda: self.renameTreeItem(tHandle)) if isFile: diff --git a/novelwriter/mbuild/__init__.py b/novelwriter/mbuild/__init__.py deleted file mode 100644 index 5a2fd13d..00000000 --- a/novelwriter/mbuild/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" -novelWriter – Manuscript Build Init File -""" diff --git a/novelwriter/mbuild/docbuild.py b/novelwriter/mbuild/docbuild.py deleted file mode 100644 index a6ad864b..00000000 --- a/novelwriter/mbuild/docbuild.py +++ /dev/null @@ -1,241 +0,0 @@ -""" -novelWriter – Build Document Tool -================================= -A class to build one or more novelWriter files to a single document - -File History: -Created: 2022-12-01 [2.1b1] - -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 . -""" - -import logging -import novelwriter - -from PyQt5.QtGui import QFont, QFontInfo - -from novelwriter.error import formatException -from novelwriter.core.tomd import ToMarkdown -from novelwriter.core.toodt import ToOdt -from novelwriter.core.tohtml import ToHtml - -logger = logging.getLogger(__name__) - - -class NWBuildDocument: - - def __init__(self, project): - - self._conf = novelwriter.CONFIG - self._project = project - self._build = {} - self._documents = [] - self._error = None - - return - - ## - # Properties - ## - - @property - def error(self): - return self._error - - @property - def buildLength(self): - return len(self._documents) - - ## - # Setters - ## - - def setBuildConfig(self, config): - """Set the build config dictionary. - """ - self._build = config - return - - def addDocument(self, tHandle): - """Add a document to the build queue. - """ - self._documents.append(tHandle) - return - - ## - # Methods - ## - - def iterBuildOpenDocument(self, savePath, isFlat): - """Build an Open Document file. - """ - makeOdt = ToOdt(self._project, isFlat=isFlat) - self._setupBuild(makeOdt) - makeOdt.initDocument() - - for i, tHandle in enumerate(self._documents): - yield i, self._doBuild(makeOdt, tHandle) - - makeOdt.closeDocument() - - self._error = None - try: - if isFlat: - makeOdt.saveFlatXML(savePath) - else: - makeOdt.saveOpenDocText(savePath) - except Exception as exc: - self._error = formatException(exc) - - return - - def iterBuildHTML(self, savePath): - """Build an HTML file. - """ - makeHtml = ToHtml(self._project) - self._setupBuild(makeHtml) - - if self._build.get("process.replaceTabs", False): - makeHtml.replaceTabs() - - for i, tHandle in enumerate(self._documents): - yield i, self._doBuild(makeHtml, tHandle) - - self._error = None - try: - makeHtml.saveHTML5(savePath) - except Exception as exc: - self._error = formatException(exc) - - return - - def iterBuildMarkdown(self, savePath, extendedMd): - """Build a Markdown file. - """ - makeMd = ToMarkdown(self._project) - self._setupBuild(makeMd) - - if extendedMd: - makeMd.setGitHubMarkdown() - else: - makeMd.setStandardMarkdown() - - if self._build.get("process.replaceTabs", False): - makeMd.replaceTabs(nSpaces=4, spaceChar=" ") - - for i, tHandle in enumerate(self._documents): - yield i, self._doBuild(makeMd, tHandle) - - self._error = None - try: - makeMd.saveMarkdown(savePath) - except Exception as exc: - self._error = formatException(exc) - - return - - ## - # Internal Functions - ## - - def _setupBuild(self, bldObj): - """Configure the build object. - """ - # Get Settings - fmtTitle = self._build.get("format.fmtTitle", "%title%") - fmtChapter = self._build.get("format.fmtChapter", "%title%") - fmtUnnumbered = self._build.get("format.fmtUnnumbered", "%title%") - fmtScene = self._build.get("format.fmtScene", "%title%") - fmtSection = self._build.get("format.fmtSection", "%title%") - buildLang = self._build.get("format.buildLang", "en_GB") - hideScene = self._build.get("format.hideScene", False) - hideSection = self._build.get("format.hideSection", False) - textFont = self._build.get("format.textFont", self._conf.textFont) - textSize = self._build.get("format.textSize", self._conf.textSize) - lineHeight = self._build.get("format.lineHeight", 1.15) - justifyText = self._build.get("format.justifyText", False) - noStyling = self._build.get("format.noStyling", False) - replaceUCode = self._build.get("format.replaceUCode", False) - incSynopsis = self._build.get("filter.includeSynopsis", False) - incComments = self._build.get("filter.includeComments", False) - incKeywords = self._build.get("filter.includeKeywords", False) - includeBody = self._build.get("filter.includeBody", True) - - # The language lookup dict is reloaded if needed - self._project.setProjectLang(buildLang) - - # Get font information - fontInfo = QFontInfo(QFont(textFont, textSize)) - textFixed = fontInfo.fixedPitch() - - bldObj.setTitleFormat(fmtTitle) - bldObj.setChapterFormat(fmtChapter) - bldObj.setUnNumberedFormat(fmtUnnumbered) - bldObj.setSceneFormat(fmtScene, hideScene) - bldObj.setSectionFormat(fmtSection, hideSection) - - bldObj.setFont(textFont, textSize, textFixed) - bldObj.setJustify(justifyText) - bldObj.setLineHeight(lineHeight) - - bldObj.setSynopsis(incSynopsis) - bldObj.setComments(incComments) - bldObj.setKeywords(incKeywords) - bldObj.setBodyText(includeBody) - - if isinstance(bldObj, ToHtml): - bldObj.setStyles(not noStyling) - bldObj.setReplaceUnicode(replaceUCode) - - if isinstance(bldObj, ToOdt): - bldObj.setColourHeaders(not noStyling) - bldObj.setLanguage(buildLang) - - return - - def _doBuild(self, bldObj, tHandle): - """Build a single document and add it to the build object. - """ - self._error = None - tItem = self._project.tree[tHandle] - if tItem is None: - self._error = f"Build: Unknown item '{tHandle}'" - logger.error(self._error) - return False - - try: - if tItem.isRootType() and not tItem.isNovelLike(): - bldObj.addRootHeading(tItem.itemHandle) - bldObj.doConvert() - elif tItem.isFileType(): - bldObj.setText(tHandle) - bldObj.doPreProcessing() - bldObj.tokenizeText() - bldObj.doHeaders() - bldObj.doConvert() - bldObj.doPostProcessing() - else: - logger.info(f"Build: Skipping '{tHandle}'") - - except Exception: - self._error = f"Build: Failed to build '{tHandle}'" - logger.error(self._error) - return False - - return True - -# END Class NWBuildDocument diff --git a/tests/test_mbuild/test_mbuild_docbuild.py b/tests/test_mbuild/test_mbuild_docbuild.py deleted file mode 100644 index ca1dea4b..00000000 --- a/tests/test_mbuild/test_mbuild_docbuild.py +++ /dev/null @@ -1,282 +0,0 @@ -""" -novelWriter – Manuscript Builder Class Tests -============================================ - -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 . -""" - -import pytest - -from shutil import copyfile - -from mock import causeException, causeOSError -from tools import ODT_IGNORE, cmpFiles - -from novelwriter.core.project import NWProject -from novelwriter.mbuild.docbuild import NWBuildDocument - -BUILD_CONF = { - "format.fmtTitle": "Title: %title%", - "format.fmtChapter": "Chapter: %title%", - "format.fmtUnnumbered": "%title%", - "format.fmtScene": "Scene: %title%", - "format.fmtSection": "Section: %title%", - "format.buildLang": "en_GB", - "format.hideScene": False, - "format.hideSection": False, - "format.textFont": "Arial", - "format.textSize": 12, - "format.lineHeight": 1.5, - "format.justifyText": True, - "format.noStyling": False, - "format.replaceUCode": False, - "filter.includeSynopsis": True, - "filter.includeComments": True, - "filter.includeKeywords": True, - "filter.includeBody": True, - "process.replaceTabs": True, -} - - -@pytest.mark.core -def testMBuildDocBuild_OpenDocument(monkeypatch, mockGUI, prjLipsum, fncPath, tstPaths): - """Test builing an open document manuscript. - """ - theProject = NWProject(mockGUI) - theProject.openProject(prjLipsum) - - docBuild = NWBuildDocument(theProject) - docBuild.setBuildConfig(BUILD_CONF) - - for tItem in theProject.tree: - docBuild.addDocument(tItem.itemHandle) - - assert docBuild.buildLength == 21 - - # Check FODT Build - # ================ - - docFile = fncPath / "Lorem Ipsum.fodt" - tstFile = tstPaths.outDir / "mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt" - cmpFile = tstPaths.refDir / "mBuildDocBuild_OpenDocument_Lorem_Ipsum.fodt" - - count = 0 - error = [] - for _, success in docBuild.iterBuildOpenDocument(docFile, True): - count += 1 if success else 0 - if docBuild.error: - error.append(docBuild.error) - - assert count == 21 - assert error == [] - - copyfile(docFile, tstFile) - assert cmpFiles(tstFile, cmpFile, ignoreStart=ODT_IGNORE) - - # Check ODT Build - # =============== - - docFile = fncPath / "Lorem Ipsum.odt" - - count = 0 - error = [] - for _, success in docBuild.iterBuildOpenDocument(docFile, False): - count += 1 if success else 0 - if docBuild.error: - error.append(docBuild.error) - - assert count == 21 - assert error == [] - - assert docFile.is_file() - - # Check Error Handling - # ==================== - - with monkeypatch.context() as mp: - mp.setattr("builtins.open", causeOSError) - - docFile = fncPath / "Lorem Ipsum Err.fodt" - for _ in docBuild.iterBuildOpenDocument(docFile, True): - pass - - assert docBuild.error == "OSError: Mock OSError" - assert not docFile.is_file() - - # Check Build Issues - # ================== - - with monkeypatch.context() as mp: - mp.setattr("novelwriter.core.toodt.ToOdt.doConvert", causeException) - - docBuild.addDocument("0000000000000") - assert docBuild.buildLength == 22 - - count = 0 - error = [] - docFile = fncPath / "Lorem Ipsum Err.fodt" - for _, success in docBuild.iterBuildOpenDocument(docFile, True): - count += 1 if success else 0 - if docBuild.error: - error.append(docBuild.error) - - assert count == 3 - assert error == [ - "Build: Failed to build '7a992350f3eb6'", - "Build: Failed to build '8c58a65414c23'", - "Build: Failed to build '88d59a277361b'", - "Build: Failed to build 'db7e733775d4d'", - "Build: Failed to build 'fb609cd8319dc'", - "Build: Failed to build '88243afbe5ed8'", - "Build: Failed to build 'f96ec11c6a3da'", - "Build: Failed to build '846352075de7d'", - "Build: Failed to build '441420a886d82'", - "Build: Failed to build 'eb103bc70c90c'", - "Build: Failed to build 'f8c0562e50f1b'", - "Build: Failed to build '47666c91c7ccf'", - "Build: Failed to build '67a8707f2f249'", - "Build: Failed to build '4c4f28287af27'", - "Build: Failed to build '6c6afb1247750'", - "Build: Failed to build '2426c6f0ca922'", - "Build: Failed to build '60bdf227455cc'", - "Build: Failed to build '04468803b92e1'", - "Build: Unknown item '0000000000000'", - ] - -# END Test testMBuildDocBuild_OpenDocument - - -@pytest.mark.core -def testMBuildDocBuild_HTML(monkeypatch, mockGUI, prjLipsum, fncPath, tstPaths): - """Test builing an HTML manuscript. - """ - theProject = NWProject(mockGUI) - theProject.openProject(prjLipsum) - - docBuild = NWBuildDocument(theProject) - docBuild.setBuildConfig(BUILD_CONF) - - for tItem in theProject.tree: - docBuild.addDocument(tItem.itemHandle) - - assert docBuild.buildLength == 21 - - # Check HTML5 Build - # ================= - - docFile = fncPath / "Lorem Ipsum.htm" - tstFile = tstPaths.outDir / "mBuildDocBuild_HTML5_Lorem_Ipsum.htm" - cmpFile = tstPaths.refDir / "mBuildDocBuild_HTML5_Lorem_Ipsum.htm" - - count = 0 - error = [] - for _, success in docBuild.iterBuildHTML(docFile): - count += 1 if success else 0 - if docBuild.error: - error.append(docBuild.error) - - assert count == 21 - assert error == [] - - copyfile(docFile, tstFile) - assert cmpFiles(tstFile, cmpFile) - - # Check Error Handling - # ==================== - - with monkeypatch.context() as mp: - mp.setattr("builtins.open", causeOSError) - - docFile = fncPath / "Lorem Ipsum Err.htm" - for _ in docBuild.iterBuildHTML(docFile): - pass - - assert docBuild.error == "OSError: Mock OSError" - assert not docFile.is_file() - -# END Test testMBuildDocBuild_HTML - - -@pytest.mark.core -def testMBuildDocBuild_Markdown(monkeypatch, mockGUI, prjLipsum, fncPath, tstPaths): - """Test builing an Markdown manuscript. - """ - theProject = NWProject(mockGUI) - theProject.openProject(prjLipsum) - - docBuild = NWBuildDocument(theProject) - docBuild.setBuildConfig(BUILD_CONF) - - for tItem in theProject.tree: - docBuild.addDocument(tItem.itemHandle) - - assert docBuild.buildLength == 21 - - # Check Standard Markdown Build - # ============================= - - docFile = fncPath / "Lorem Ipsum Standard.md" - tstFile = tstPaths.outDir / "mBuildDocBuild_Standard_Markdown_Lorem_Ipsum.md" - cmpFile = tstPaths.refDir / "mBuildDocBuild_Standard_Markdown_Lorem_Ipsum.md" - - count = 0 - error = [] - for _, success in docBuild.iterBuildMarkdown(docFile, False): - count += 1 if success else 0 - if docBuild.error: - error.append(docBuild.error) - - assert count == 21 - assert error == [] - - copyfile(docFile, tstFile) - assert cmpFiles(tstFile, cmpFile) - - # Check Extended Markdown Build - # ============================= - - docFile = fncPath / "Lorem Ipsum Standard.md" - tstFile = tstPaths.outDir / "mBuildDocBuild_Extended_Markdown_Lorem_Ipsum.md" - cmpFile = tstPaths.refDir / "mBuildDocBuild_Extended_Markdown_Lorem_Ipsum.md" - - count = 0 - error = [] - for _, success in docBuild.iterBuildMarkdown(docFile, True): - count += 1 if success else 0 - if docBuild.error: - error.append(docBuild.error) - - assert count == 21 - assert error == [] - - copyfile(docFile, tstFile) - assert cmpFiles(tstFile, cmpFile) - - # Check Error Handling - # ==================== - - with monkeypatch.context() as mp: - mp.setattr("builtins.open", causeOSError) - - docFile = fncPath / "Lorem Ipsum Err.md" - for _ in docBuild.iterBuildMarkdown(docFile, False): - pass - - assert docBuild.error == "OSError: Mock OSError" - assert not docFile.is_file() - -# END Test testMBuildDocBuild_Markdown