From 3125df95d3f9e56a342571703cb1ce1170f0f346 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sun, 26 Feb 2023 21:50:58 +0100 Subject: [PATCH 01/10] Update translations --- i18n/nw_base.ts | 18 ++++----- i18n/nw_de_DE.ts | 18 ++++----- i18n/nw_en_US.ts | 18 ++++----- i18n/nw_es_419.ts | 20 +++++----- i18n/nw_it_IT.ts | 18 ++++----- i18n/nw_nb_NO.ts | 18 ++++----- i18n/nw_nl_NL.ts | 93 ++++++++++++++++++++++++++--------------------- i18n/nw_pt_BR.ts | 18 ++++----- 8 files changed, 116 insertions(+), 105 deletions(-) diff --git a/i18n/nw_base.ts b/i18n/nw_base.ts index 6777e15d..5429ac32 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}'? 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}? From 357d1fa83bced4fd3b8d2fe85d273051b4a3b339 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 10 Mar 2023 16:47:47 +0100 Subject: [PATCH 02/10] Update docs theme from main branch --- docs/source/_static/custom.css | 15 +++++++- docs/source/_templates/sidebar-title.html | 3 ++ docs/source/conf.py | 47 +++++++++++------------ docs/source/index.rst | 6 ++- docs/source/int_customise.rst | 2 +- docs/source/int_introduction.rst | 12 +++--- docs/source/int_started.rst | 9 +++++ docs/source/requirements.txt | 5 ++- 8 files changed, 61 insertions(+), 38 deletions(-) create mode 100644 docs/source/_templates/sidebar-title.html diff --git a/docs/source/_static/custom.css b/docs/source/_static/custom.css index 4afdc4fc..5db9bebd 100644 --- a/docs/source/_static/custom.css +++ b/docs/source/_static/custom.css @@ -1,3 +1,14 @@ -body article section { - margin-top: 1.8em; +span.guilabel { + font-weight: 400; +} + +.nw-sidebar-title { + height: unset; + max-height: unset; + flex-direction: column; + justify-content: center; + gap: .25rem; + font-size: 1.25rem; + font-weight: normal; + text-align: center; } diff --git a/docs/source/_templates/sidebar-title.html b/docs/source/_templates/sidebar-title.html new file mode 100644 index 00000000..a9f2a58a --- /dev/null +++ b/docs/source/_templates/sidebar-title.html @@ -0,0 +1,3 @@ +{% if docstitle %} +

{{ docstitle }}

+{% endif %} diff --git a/docs/source/conf.py b/docs/source/conf.py index c2851227..03e1d9d7 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,7 +1,7 @@ -# -# Configuration file for the Sphinx documentation builder. -# Documentation: http://www.sphinx-doc.org/en/master/config -# +""" +Configuration file for the Sphinx documentation builder. +Documentation: http://www.sphinx-doc.org/en/master/config +""" # -- Imports ----------------------------------------------------------------- @@ -12,7 +12,7 @@ import datetime # -- Project Information ----------------------------------------------------- project = "novelWriter" -copyright = f"{datetime.date.today().year}, Veronica Berglyd Olsen" +copyright = f"{datetime.date.today().year}" author = "Veronica Berglyd Olsen" initFile = os.path.join( @@ -34,7 +34,7 @@ version = release.split("-")[0] os.environ["TZ"] = "Europe/Oslo" time.tzset() -needs_sphinx = "4.0" +needs_sphinx = "5.0" extensions = [] templates_path = ["_templates"] source_suffix = ".rst" @@ -45,23 +45,27 @@ exclude_patterns = [] # -- Options for HTML Output ------------------------------------------------- -html_theme = "furo" +html_theme = "sphinx_book_theme" +html_title = f"Version {release}" html_static_path = ["_static"] html_css_files = ["custom.css"] html_theme_options = { - "light_logo": "novelwriter-light.png", - "dark_logo": "novelwriter-dark.png", + "logo": { + "image_light": "_static/novelwriter-light.png", + "image_dark": "_static/novelwriter-dark.png", + }, + "show_toc_level": 2, + "show_navbar_depth": 1, + "repository_url": "https://github.com/vkbo/novelwriter", "navigation_with_keys": True, - "dark_css_variables": { - "admonition-font-size": "92%", - }, - "light_css_variables": { - "admonition-font-size": "92%", - }, + "use_repository_button": True, + "use_issues_button": True, + "pygment_light_style": "tango", + "pygment_dark_style": "dracula", +} +html_sidebars = { + "**": ["navbar-logo", "sidebar-title", "sbt-sidebar-nav"], } -html_title = f"
Documentation Version {release}
" -pygments_style = "tango" -pygments_dark_style = "native" # -- Options for HTMLHelp Output --------------------------------------------- @@ -111,12 +115,5 @@ texinfo_documents = [( # Bibliographic Dublin Core info. epub_title = project -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -# epub_identifier = "" - -# A unique identification for the text. -# epub_uid = "" - # A list of files that should not be packed into the epub file. epub_exclude_files = ["search.html"] diff --git a/docs/source/index.rst b/docs/source/index.rst index dfc2877c..c9ba0aa9 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -3,8 +3,9 @@ Documentation for novelWriter ############################# .. image:: images/novelwriter_logo.png + :class: dark-light :align: right - :width: 48 + :width: 64 | **For Release:** |release| | **Last Updated:** |today| @@ -17,6 +18,7 @@ editor that allows for easy organisation of text and notes, using human readable storage for robustness. .. figure:: images/screenshot_multi.png + :class: dark-light :align: center :width: 500 @@ -31,7 +33,7 @@ as well. novelWriter can also be run directly from the Python source, or install the pip tool. See :ref:`a_started` for more details. .. note:: - Version 1.3 introduced a few changes that will require you to make some minor modifications to + Release 1.5 introduced a few changes that will require you to make some minor modifications to some of the headings in your project. It should be fairly quick and straightforward. Please see the :ref:`a_prjfmt_1_3` section for more details. diff --git a/docs/source/int_customise.rst b/docs/source/int_customise.rst index 07b130b4..e2b6cc18 100644 --- a/docs/source/int_customise.rst +++ b/docs/source/int_customise.rst @@ -16,7 +16,7 @@ your own syntax themes, and install additional dictionaries. Spell Check Dictionaries ======================== -novelWriter uses Enchant_ as the spell checking tool. Depending on you operating system, it may or +novelWriter uses Enchant_ as the spell checking tool. Depending on your operating system, it may or may not load installed spell check dictionaries. Linux diff --git a/docs/source/int_introduction.rst b/docs/source/int_introduction.rst index 5eeffb7b..9b3bc4cf 100644 --- a/docs/source/int_introduction.rst +++ b/docs/source/int_introduction.rst @@ -68,12 +68,12 @@ Below are some key features of novelWriter. Screenshots =========== -**novelWriter with default theme:** +.. figure:: images/screenshot_default.png + :class: dark-light -.. image:: images/screenshot_default.png - :width: 800 + novelWriter with default theme -**novelWriter with dark theme:** +.. figure:: images/screenshot_dark.png + :class: dark-light -.. image:: images/screenshot_dark.png - :width: 800 + novelWriter with dark theme diff --git a/docs/source/int_started.rst b/docs/source/int_started.rst index 3b7007f8..dab20afd 100644 --- a/docs/source/int_started.rst +++ b/docs/source/int_started.rst @@ -89,6 +89,15 @@ Then run the update and install commands as for Ubuntu: You may need to use the Ubuntu 20.04 (focal) packages for Debian 11 or earlier. The newer Ubuntu packages use a different compression algorithm that may not be supported. +.. tip:: + + If you get an error message like ``gpg: failed to create temporary file`` when importing the key + from the Ubuntu keyserver, try creating the folder it fails on, and import the key again: + + .. code-block:: bash + + sudo mkdir /root/.gnupg/ + AppImage Releases ----------------- diff --git a/docs/source/requirements.txt b/docs/source/requirements.txt index 1896078f..19fc1423 100644 --- a/docs/source/requirements.txt +++ b/docs/source/requirements.txt @@ -1,4 +1,5 @@ -furo -sphinx>=4.0 +sphinx-book-theme +sphinx>=5.0 +sphinx-favicon pygments>=2.7 docutils>=0.17.1 From 8bada3c468cf24837ac24e31669202aadf2f36f2 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 20 Mar 2023 22:36:49 +0100 Subject: [PATCH 03/10] Clarify instructions on how to download dictionaries on Windows --- docs/source/int_customise.rst | 36 +++++++++++++++++++++++------------ novelwriter/gui/doceditor.py | 2 +- 2 files changed, 25 insertions(+), 13 deletions(-) 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/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() From 3a569e026834d4e4b95d37226568032c53fd5069 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 21 Mar 2023 09:17:09 +0100 Subject: [PATCH 04/10] Fix typo --- docs/source/int_howto.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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. From 00abb02ac1adc241de6086f922eced90c2ac5002 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 3 Apr 2023 21:31:07 +0200 Subject: [PATCH 05/10] Add the desktopFileName setting to the application for better support for Linux desktops --- novelwriter/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index ea2b02a5..6ad9fca5 100644 --- a/novelwriter/__init__.py +++ b/novelwriter/__init__.py @@ -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 From 740e3be74b120835909273a53d7b807869b324a8 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 3 Apr 2023 21:34:38 +0200 Subject: [PATCH 06/10] Fix project tree rename label (#1403) --- novelwriter/gui/projtree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index df29903b..380c9e92 100644 --- a/novelwriter/gui/projtree.py +++ b/novelwriter/gui/projtree.py @@ -1204,7 +1204,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: From 7cd5d2740f86b219e29887960b1be60567c9abdf Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 3 Apr 2023 21:34:58 +0200 Subject: [PATCH 07/10] Update base translation file --- i18n/nw_base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i18n/nw_base.ts b/i18n/nw_base.ts index 5429ac32..8bd79c2e 100644 --- a/i18n/nw_base.ts +++ b/i18n/nw_base.ts @@ -3405,7 +3405,7 @@ - Change Label + Rename From db1cda65c3c05ea8008ce69ed7ed0d4e1be7453f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Mon, 3 Apr 2023 22:06:57 +0200 Subject: [PATCH 08/10] Add check for root class before allowing adding novel documents in project tree new item (#1404) --- novelwriter/gui/projtree.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py index 380c9e92..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 From 3c7775aaa2b8bc05fac82b12abfd724ebd834d88 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:35:40 +0200 Subject: [PATCH 09/10] Remove dev code from main --- novelwriter/mbuild/__init__.py | 3 - novelwriter/mbuild/docbuild.py | 241 ------------------ tests/test_mbuild/test_mbuild_docbuild.py | 282 ---------------------- 3 files changed, 526 deletions(-) delete mode 100644 novelwriter/mbuild/__init__.py delete mode 100644 novelwriter/mbuild/docbuild.py delete mode 100644 tests/test_mbuild/test_mbuild_docbuild.py 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 From 835165f012751b70e79ee2d3bd28fff780775ea6 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Tue, 4 Apr 2023 17:44:25 +0200 Subject: [PATCH 10/10] Restore last version on main branch --- novelwriter/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py index 3bf21346..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"