novelWriter 2.7.1__tar.gz → 2.7.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {novelwriter-2.7.1 → novelwriter-2.7.3}/CHANGELOG.md +73 -3
- {novelwriter-2.7.1 → novelwriter-2.7.3}/PKG-INFO +3 -3
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelWriter.egg-info/PKG-INFO +3 -3
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelWriter.egg-info/SOURCES.txt +1 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/__init__.py +3 -3
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/manual.pdf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/manual_fr.pdf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/sample.zip +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/common.py +3 -2
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/config.py +2 -2
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/constants.py +12 -19
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/index.py +8 -6
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/indexdata.py +9 -3
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/preferences.py +38 -11
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/todocx.py +2 -2
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/tokenizer.py +45 -39
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/toqdoc.py +10 -8
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/docviewer.py +2 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/noveltree.py +1 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/manuscript.py +4 -7
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/manussettings.py +19 -15
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/types.py +1 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/pyproject.toml +5 -2
- novelwriter-2.7.3/setup/LICENSE-Apache-2.0.txt +202 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/CREDITS.md +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/LICENSE.md +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/MANIFEST.in +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/README.md +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelWriter.egg-info/dependency_links.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelWriter.egg-info/entry_points.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelWriter.egg-info/requires.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelWriter.egg-info/top_level.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_cs_CZ.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_en_US.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_es_419.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_cs_CZ.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_de_DE.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_en_GB.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_en_US.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_es_419.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_fr_FR.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_it_IT.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_ja_JP.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_nb_NO.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_nl_NL.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_nn_NO.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_pl_PL.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_pt_BR.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_ru_RU.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/i18n/project_zh_CN.json +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/font_awesome.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/material_filled_bold.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/material_filled_normal.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/material_filled_thin.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/material_rounded_bold.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/material_rounded_normal.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/material_rounded_thin.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/none.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/novelwriter.ico +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/novelwriter.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/remix_filled.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/remix_outline.icons +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/icons/x-novelwriter-project.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/images/novelwriter-text-dark.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/images/novelwriter-text-light.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/images/splash.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/images/welcome-dark.jpg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/images/welcome-light.jpg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/cyberpunk_night.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/default_dark.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/default_light.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/dracula.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/grey_dark.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/grey_light.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/light_owl.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/night_owl.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/snazzy.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/solarized_dark.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/solarized_light.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/tango.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/tomorrow.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/tomorrow_night.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/tomorrow_night_blue.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/tomorrow_night_bright.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/syntax/tomorrow_night_eighties.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/text/credits_en.htm +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/text/lipsum.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/cyberpunk_night.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/default.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/default_dark.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/default_light.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/dracula.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/snazzy.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/solarized_dark.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/assets/themes/solarized_light.conf +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/buildsettings.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/coretools.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/docbuild.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/document.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/item.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/itemmodel.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/novelmodel.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/options.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/project.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/projectdata.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/projectxml.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/sessions.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/spellcheck.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/status.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/storage.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/core/tree.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/about.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/docmerge.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/docsplit.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/editlabel.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/projectsettings.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/quotes.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/dialogs/wordlist.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/enum.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/error.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/configlayout.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/eventfilters.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/modified.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/novelselector.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/pagedsidebar.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/progressbars.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/statusled.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/switch.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/switchbox.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/extensions/versioninfo.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/shared.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/tohtml.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/tomarkdown.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/toodt.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/formats/toraw.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/doceditor.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/dochighlight.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/docviewerpanel.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/editordocument.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/itemdetails.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/mainmenu.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/outline.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/projtree.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/search.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/sidebar.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/statusbar.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/gui/theme.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/guimain.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/shared.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/splash.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/text/comments.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/text/counting.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/text/patterns.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/dictionaries.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/lipsum.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/manusbuild.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/noveldetails.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/welcome.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/novelwriter/tools/writingstats.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/pkgutils.py +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/appimage_launcher.sh +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/128x128/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/128x128/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/16x16/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/16x16/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/24x24/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/24x24/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/256x256/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/256x256/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/32x32/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/32x32/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/48x48/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/48x48/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/512x512/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/512x512/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/64x64/apps/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/64x64/mimetypes/application-x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/scalable/apps/novelwriter.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/hicolor/scalable/mimetypes/application-x-novelwriter-project.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/novelwriter.desktop +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/data/x-novelwriter-project.xml +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/compat +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/control +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/copyright +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/install +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/py3dist-overrides +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/rules +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/debian/source/format +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/description_pypi.md +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/description_short.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/icons/novelwriter.ico +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/icons/novelwriter.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/icons/novelwriter.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/icons/x-novelwriter-project.ico +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/icons/x-novelwriter-project.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/icons/x-novelwriter-project.svg +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/iss_license.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/App.entitlements +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/Info.plist.template +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/build.sh +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_128x128.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_128x128@2x.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_16x16.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_16x16@2x.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_256x256.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_256x256@2x.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_32x32.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_32x32@2x.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_512x512.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/macos/novelwriter.iconset/icon_512x512@2x.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/make_clean.sh +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/make_pip.sh +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/make_release.sh +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/novelwriter.appdata.xml +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/novelwriter_readme.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/novelwriter_text.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/screenshot.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/signpath_logo.png +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/win_setup_embed.iss +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/windows/CMakeLists.txt +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/windows/launcher.rc +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/windows/main.cpp +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/windows/make.ps1 +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/windows/novelWriter.exe +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup/windows/novelWriter.ico +0 -0
- {novelwriter-2.7.1 → novelwriter-2.7.3}/setup.cfg +0 -0
@@ -1,12 +1,82 @@
|
|
1
1
|
# novelWriter Changelog
|
2
2
|
|
3
|
+
## Version 2.7.3 [2025-07-07]
|
4
|
+
|
5
|
+
### Release Notes
|
6
|
+
|
7
|
+
This is a patch release that fixes a bug in, and makes a few improvement to, Preferences.
|
8
|
+
|
9
|
+
### Detailed Changelog
|
10
|
+
|
11
|
+
**Bugfixes**
|
12
|
+
|
13
|
+
* Fixes an issue where novelWriter would crash if a `%` was added to any of the free text settings
|
14
|
+
fields in Preferences. Issue #2455. PR #2456.
|
15
|
+
|
16
|
+
**Improvements**
|
17
|
+
|
18
|
+
* The "Dialogue line symbols" setting in Preferences now has an "Add" button with a dropdown menu
|
19
|
+
for all the symbols allowed in this field. Since virtually none of them are available on a
|
20
|
+
regular keyboard, this makes it easier to add them and more transparent which symbols are allowed
|
21
|
+
in the box. Issue #2453. PR #2457.
|
22
|
+
* The switch for the "Allow open-ended dialogue" setting in Preferences has been moved up one line
|
23
|
+
so it is clearer that it only applies to quoted dialogue, and not to the alternative dialogue
|
24
|
+
settings. Issue #2454. PR #2457.
|
25
|
+
|
26
|
+
**Packaging**
|
27
|
+
|
28
|
+
* Package license information has been updated to also list the licenses for the new icon themes.
|
29
|
+
Issue #2434. PRs #2435 and #2458.
|
30
|
+
|
31
|
+
----
|
32
|
+
|
33
|
+
## Version 2.7.2 [2025-06-24]
|
34
|
+
|
35
|
+
### Release Notes
|
36
|
+
|
37
|
+
This is a patch release that fixes several issues related to DocX and PDF manuscript documents,
|
38
|
+
improves how line breaks, alignment and indentation is processed, and fixes some issues with
|
39
|
+
displaying tags for novel documents on the user interface.
|
40
|
+
|
41
|
+
### Detailed Changelog
|
42
|
+
|
43
|
+
**Bugfixes**
|
44
|
+
|
45
|
+
* Fixed an issue where escaped markup characters were not replaced properly in DocX and PDF
|
46
|
+
documents, and in previews. Issue #2410. PR #2411.
|
47
|
+
* Fixed an issue where titles with line breaks in them would have page breaks applied to both lines
|
48
|
+
for preview and PDF documents. Issue #2415. PR #2416.
|
49
|
+
* Fixed an issue where the justified text setting would not be properly applied to a paragraph in a
|
50
|
+
manuscript document if there was a line break in the paragraph, but single line breaks were set
|
51
|
+
to be ignored. Issue #2426. PR #2427.
|
52
|
+
* Fixed an issue where the "Tag" field of the Outline View details panel remained blank even if a
|
53
|
+
tag was set for the novel document. Issue #2428. PR #2429.
|
54
|
+
|
55
|
+
**Improvements**
|
56
|
+
|
57
|
+
* When comments are enabled in the viewer, story comments should also be visible. A separate filter
|
58
|
+
button will be added for this in 2.8. PR #2420.
|
59
|
+
* When a paragraph has line breaks in it, the alignment tag will now override first line
|
60
|
+
indentation even if the alignment tag is not on the first line. This is more consistent with the
|
61
|
+
alignment behaviour for multi-line paragraphs in general. Issue #2425. PR #2427.
|
62
|
+
* Tags will now be shown in the Novel View tooltip pop-out under the triangle button, together with
|
63
|
+
all the other meta data collected about a document or heading. PR #2429.
|
64
|
+
|
65
|
+
**Documentation**
|
66
|
+
|
67
|
+
* The documentation on how alignment and first line indentation works in conjunction with
|
68
|
+
in-paragraph line breaks, the setting to keep or ignore such line breaks, and the forced line
|
69
|
+
break shortcode, has been improved. Issue #2425. PR #2427.
|
70
|
+
|
71
|
+
----
|
72
|
+
|
3
73
|
## Version 2.7.1 [2025-06-09]
|
4
74
|
|
5
75
|
### Release Notes
|
6
76
|
|
7
|
-
This is a patch release that fixes some issues with tags and references,
|
8
|
-
auto-complete menu on Windows, and issues with the AppImage on Linux. The Czech translation
|
9
|
-
2.7 has been completed.
|
77
|
+
This is a patch release that fixes some issues with tags and references, an issue with the
|
78
|
+
auto-complete menu on Windows, and some issues with the AppImage on Linux. The Czech translation
|
79
|
+
for 2.7 has also been completed.
|
10
80
|
|
11
81
|
### Detailed Changelog
|
12
82
|
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: novelWriter
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.3
|
4
4
|
Summary: A plain text editor for planning and writing novels
|
5
5
|
Author-email: Veronica Berglyd Olsen <code@vkbo.net>
|
6
|
-
License:
|
6
|
+
License-Expression: GPL-3.0-or-later AND Apache-2.0 AND CC-BY-4.0
|
7
7
|
Project-URL: Homepage, https://novelwriter.io
|
8
8
|
Project-URL: Documentation, https://docs.novelwriter.io
|
9
9
|
Project-URL: Repository, https://github.com/vkbo/novelWriter
|
@@ -14,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
17
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
18
17
|
Classifier: Development Status :: 5 - Production/Stable
|
19
18
|
Classifier: Operating System :: OS Independent
|
20
19
|
Classifier: Intended Audience :: End Users/Desktop
|
@@ -23,6 +22,7 @@ Classifier: Topic :: Text Editors
|
|
23
22
|
Requires-Python: >=3.10
|
24
23
|
Description-Content-Type: text/markdown
|
25
24
|
License-File: LICENSE.md
|
25
|
+
License-File: setup/LICENSE-Apache-2.0.txt
|
26
26
|
Requires-Dist: pyqt6>=6.4
|
27
27
|
Requires-Dist: pyenchant>=3.0.0
|
28
28
|
Dynamic: license-file
|
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: novelWriter
|
3
|
-
Version: 2.7.
|
3
|
+
Version: 2.7.3
|
4
4
|
Summary: A plain text editor for planning and writing novels
|
5
5
|
Author-email: Veronica Berglyd Olsen <code@vkbo.net>
|
6
|
-
License:
|
6
|
+
License-Expression: GPL-3.0-or-later AND Apache-2.0 AND CC-BY-4.0
|
7
7
|
Project-URL: Homepage, https://novelwriter.io
|
8
8
|
Project-URL: Documentation, https://docs.novelwriter.io
|
9
9
|
Project-URL: Repository, https://github.com/vkbo/novelWriter
|
@@ -14,7 +14,6 @@ Classifier: Programming Language :: Python :: 3.11
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
15
15
|
Classifier: Programming Language :: Python :: 3.13
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
17
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
18
17
|
Classifier: Development Status :: 5 - Production/Stable
|
19
18
|
Classifier: Operating System :: OS Independent
|
20
19
|
Classifier: Intended Audience :: End Users/Desktop
|
@@ -23,6 +22,7 @@ Classifier: Topic :: Text Editors
|
|
23
22
|
Requires-Python: >=3.10
|
24
23
|
Description-Content-Type: text/markdown
|
25
24
|
License-File: LICENSE.md
|
25
|
+
License-File: setup/LICENSE-Apache-2.0.txt
|
26
26
|
Requires-Dist: pyqt6>=6.4
|
27
27
|
Requires-Dist: pyenchant>=3.0.0
|
28
28
|
Dynamic: license-file
|
@@ -167,6 +167,7 @@ novelwriter/tools/manussettings.py
|
|
167
167
|
novelwriter/tools/noveldetails.py
|
168
168
|
novelwriter/tools/welcome.py
|
169
169
|
novelwriter/tools/writingstats.py
|
170
|
+
setup/LICENSE-Apache-2.0.txt
|
170
171
|
setup/appimage_launcher.sh
|
171
172
|
setup/description_pypi.md
|
172
173
|
setup/description_short.txt
|
@@ -49,9 +49,9 @@ __license__ = "GPLv3"
|
|
49
49
|
__author__ = "Veronica Berglyd Olsen"
|
50
50
|
__maintainer__ = "Veronica Berglyd Olsen"
|
51
51
|
__email__ = "code@vkbo.net"
|
52
|
-
__version__ = "2.7.
|
53
|
-
__hexversion__ = "
|
54
|
-
__date__ = "2025-
|
52
|
+
__version__ = "2.7.3"
|
53
|
+
__hexversion__ = "0x020703f0"
|
54
|
+
__date__ = "2025-07-07"
|
55
55
|
__status__ = "Stable"
|
56
56
|
__domain__ = "novelwriter.io"
|
57
57
|
|
Binary file
|
Binary file
|
Binary file
|
@@ -680,11 +680,12 @@ class NWConfigParser(ConfigParser):
|
|
680
680
|
"""Common: Adapted Config Parser
|
681
681
|
|
682
682
|
This is a subclass of the standard config parser that adds type safe
|
683
|
-
helper functions, and support for lists.
|
683
|
+
helper functions, and support for lists. It also turns off
|
684
|
+
interpolation, which would require % symbols to be escaped (#2455).
|
684
685
|
"""
|
685
686
|
|
686
687
|
def __init__(self) -> None:
|
687
|
-
super().__init__()
|
688
|
+
super().__init__(interpolation=None)
|
688
689
|
return
|
689
690
|
|
690
691
|
def rdStr(self, section: str, option: str, default: str) -> str:
|
@@ -44,7 +44,7 @@ from novelwriter.common import (
|
|
44
44
|
NWConfigParser, checkInt, checkPath, describeFont, fontMatcher,
|
45
45
|
formatTimeStamp, processDialogSymbols, simplified
|
46
46
|
)
|
47
|
-
from novelwriter.constants import nwFiles,
|
47
|
+
from novelwriter.constants import nwFiles, nwQuotes, nwUnicode
|
48
48
|
from novelwriter.error import formatException, logException
|
49
49
|
|
50
50
|
if TYPE_CHECKING:
|
@@ -892,7 +892,7 @@ class Config:
|
|
892
892
|
"""
|
893
893
|
self.splashMessage(f"Initialising {kind} font: {font.family()}")
|
894
894
|
metrics = QFontMetrics(font)
|
895
|
-
for char in
|
895
|
+
for char in nwUnicode.UI_SYMBOLS:
|
896
896
|
if not metrics.inFont(char): # type: ignore
|
897
897
|
logger.warning("No glyph U+%04x in font", ord(char)) # pragma: no cover
|
898
898
|
return
|
@@ -586,21 +586,14 @@ class nwUnicode:
|
|
586
586
|
U_TIMES = "\u00d7" # Multiplication sign
|
587
587
|
U_DIVIDE = "\u00f7" # Division sign
|
588
588
|
|
589
|
-
# Arrows
|
590
|
-
U_UTRI = "\u25b2" # Up-pointing triangle
|
591
|
-
U_UTRIS = "\u25b4" # Up-pointing triangle, small
|
592
|
-
U_RTRI = "\u25b6" # Right-pointing triangle
|
593
|
-
U_RTRIS = "\u25b8" # Right-pointing triangle, small
|
594
|
-
U_DTRI = "\u25bc" # Down-pointing triangle
|
595
|
-
U_DTRIS = "\u25be" # Down-pointing triangle, small
|
596
|
-
U_LTRI = "\u25c0" # Left-pointing triangle
|
597
|
-
U_LTRIS = "\u25c2" # Left-pointing triangle, small
|
598
|
-
|
599
589
|
# Special
|
600
590
|
U_UNKN = "\ufffd" # Unknown character
|
601
591
|
U_NAC1 = "\ufffe" # Not a character
|
602
592
|
U_NAC2 = "\uffff" # Not a character
|
603
593
|
|
594
|
+
# Placeholders
|
595
|
+
U_LBREAK = "\u21b2" # Downwards Arrow With Tip Leftwards
|
596
|
+
|
604
597
|
# HTML Equivalents
|
605
598
|
# ================
|
606
599
|
|
@@ -655,15 +648,15 @@ class nwUnicode:
|
|
655
648
|
H_TIMES = "×"
|
656
649
|
H_DIVIDE = "÷"
|
657
650
|
|
658
|
-
#
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
651
|
+
# Unicode symbols expected to be used on the UI
|
652
|
+
UI_SYMBOLS: Final[list[str]] = [
|
653
|
+
U_QUOT, U_APOS, U_LAQUO, U_RAQUO, U_LSQUO, U_RSQUO, U_SBQUO, U_SUQUO,
|
654
|
+
U_LDQUO, U_RDQUO, U_BDQUO, U_UDQUO, U_LSAQUO, U_RSAQUO, U_BDRQUO,
|
655
|
+
U_LCQUO, U_RCQUO, U_LWCQUO, U_RWCQUO, U_FGDASH, U_ENDASH, U_EMDASH,
|
656
|
+
U_HBAR, U_HELLIP, U_MAPOS, U_PRIME, U_DPRIME, U_NBSP, U_THSP, U_THNBSP,
|
657
|
+
U_ENSP, U_EMSP, U_MMSP, U_CHECK, U_CROSS, U_BULL, U_TRBULL, U_HYBULL,
|
658
|
+
U_FLOWER, U_PERMIL, U_DEGREE, U_MINUS, U_TIMES, U_DIVIDE, U_LBREAK,
|
659
|
+
]
|
667
660
|
|
668
661
|
|
669
662
|
class nwHtmlUnicode:
|
@@ -708,17 +708,19 @@ class Index:
|
|
708
708
|
return 0, 0, 0
|
709
709
|
|
710
710
|
def getReferences(self, tHandle: str, sTitle: str | None = None) -> dict[str, list[str]]:
|
711
|
-
"""Extract all references made in a file, and
|
712
|
-
section.
|
711
|
+
"""Extract all tags and references made in a file, and
|
712
|
+
optionally title section.
|
713
713
|
"""
|
714
|
-
|
714
|
+
refs = {x: [] for x in nwKeyWords.VALID_KEYS}
|
715
715
|
for rTitle, hItem in self._itemIndex.iterItemHeaders(tHandle):
|
716
716
|
if sTitle is None or sTitle == rTitle:
|
717
717
|
for aTag, refTypes in hItem.references.items():
|
718
718
|
for refType in refTypes:
|
719
|
-
if refType in
|
720
|
-
|
721
|
-
|
719
|
+
if refType in refs:
|
720
|
+
refs[refType].append(self._tagsIndex.tagName(aTag))
|
721
|
+
if tag := hItem.tag:
|
722
|
+
refs[nwKeyWords.TAG_KEY] = [self._tagsIndex.tagName(tag)]
|
723
|
+
return refs
|
722
724
|
|
723
725
|
def getReferenceForHeader(self, tHandle: str, nHead: int, keyClass: str) -> list[str]:
|
724
726
|
"""Get the display names for a tags class for insertion into a
|
@@ -342,20 +342,26 @@ class IndexHeading:
|
|
342
342
|
##
|
343
343
|
|
344
344
|
def getReferences(self) -> dict[str, list[str]]:
|
345
|
-
"""Extract all references for this heading."""
|
345
|
+
"""Extract all tags and references for this heading."""
|
346
346
|
refs = {x: [] for x in nwKeyWords.VALID_KEYS}
|
347
347
|
for tag, types in self._refs.items():
|
348
348
|
for keyword in types:
|
349
349
|
if keyword in refs and (name := self._cache.tags.tagName(tag)):
|
350
350
|
refs[keyword].append(name)
|
351
|
+
if name := self._cache.tags.tagName(self._tag):
|
352
|
+
refs[nwKeyWords.TAG_KEY] = [name]
|
351
353
|
return refs
|
352
354
|
|
353
355
|
def getReferencesByKeyword(self, keyword: str) -> list[str]:
|
354
356
|
"""Extract all references for this heading."""
|
355
357
|
refs = []
|
356
|
-
|
357
|
-
if
|
358
|
+
if keyword == nwKeyWords.TAG_KEY:
|
359
|
+
if name := self._cache.tags.tagName(self._tag):
|
358
360
|
refs.append(name)
|
361
|
+
else:
|
362
|
+
for tag, types in self._refs.items():
|
363
|
+
if keyword in types and (name := self._cache.tags.tagName(tag)):
|
364
|
+
refs.append(name)
|
359
365
|
return refs
|
360
366
|
|
361
367
|
##
|
@@ -29,7 +29,7 @@ import logging
|
|
29
29
|
from PyQt6.QtCore import Qt, pyqtSignal, pyqtSlot
|
30
30
|
from PyQt6.QtGui import QAction, QCloseEvent, QKeyEvent, QKeySequence
|
31
31
|
from PyQt6.QtWidgets import (
|
32
|
-
QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout, QLineEdit,
|
32
|
+
QCompleter, QDialogButtonBox, QFileDialog, QHBoxLayout, QLineEdit, QMenu,
|
33
33
|
QPushButton, QVBoxLayout, QWidget
|
34
34
|
)
|
35
35
|
|
@@ -600,6 +600,7 @@ class GuiPreferences(NDialog):
|
|
600
600
|
self.sidebar.addButton(title, section)
|
601
601
|
self.mainForm.addGroupLabel(title, section)
|
602
602
|
|
603
|
+
# Dialogue Quotes
|
603
604
|
self.dialogStyle = NComboBox(self)
|
604
605
|
self.dialogStyle.addItem(self.tr("None"), 0)
|
605
606
|
self.dialogStyle.addItem(self.tr("Single Quotes"), 1)
|
@@ -611,6 +612,15 @@ class GuiPreferences(NDialog):
|
|
611
612
|
self.tr("Applies to the selected quote styles.")
|
612
613
|
)
|
613
614
|
|
615
|
+
# Open-Ended Dialogue
|
616
|
+
self.allowOpenDial = NSwitch(self)
|
617
|
+
self.allowOpenDial.setChecked(CONFIG.allowOpenDial)
|
618
|
+
self.mainForm.addRow(
|
619
|
+
self.tr("Allow open-ended dialogue"), self.allowOpenDial,
|
620
|
+
self.tr("Highlight dialogue line with no closing quote.")
|
621
|
+
)
|
622
|
+
|
623
|
+
# Alternative Dialogue
|
614
624
|
self.altDialogOpen = QLineEdit(self)
|
615
625
|
self.altDialogOpen.setMaxLength(4)
|
616
626
|
self.altDialogOpen.setFixedWidth(boxFixed)
|
@@ -628,23 +638,30 @@ class GuiPreferences(NDialog):
|
|
628
638
|
self.tr("Custom highlighting of dialogue text.")
|
629
639
|
)
|
630
640
|
|
631
|
-
|
632
|
-
self.
|
633
|
-
|
634
|
-
|
635
|
-
self.
|
636
|
-
|
641
|
+
# Dialogue Line
|
642
|
+
self.mnLineSymbols = QMenu(self)
|
643
|
+
for symbol in nwQuotes.ALLOWED:
|
644
|
+
label = trConst(nwQuotes.SYMBOLS.get(symbol, nwQuotes.DASHES.get(symbol, "None")))
|
645
|
+
self.mnLineSymbols.addAction(
|
646
|
+
f"[ {symbol } ] {label}",
|
647
|
+
lambda symbol=symbol: self._insertDialogLineSymbol(symbol)
|
648
|
+
)
|
637
649
|
|
638
650
|
self.dialogLine = QLineEdit(self)
|
639
|
-
self.dialogLine.
|
640
|
-
self.dialogLine.setFixedWidth(boxFixed)
|
651
|
+
self.dialogLine.setMinimumWidth(100)
|
641
652
|
self.dialogLine.setAlignment(QtAlignCenter)
|
642
|
-
self.dialogLine.setText(CONFIG.dialogLine)
|
653
|
+
self.dialogLine.setText(" ".join(CONFIG.dialogLine))
|
654
|
+
|
655
|
+
self.dialogLineButton = NIconToolButton(self, iSz, "add", "green")
|
656
|
+
self.dialogLineButton.setMenu(self.mnLineSymbols)
|
657
|
+
|
643
658
|
self.mainForm.addRow(
|
644
659
|
self.tr("Dialogue line symbols"), self.dialogLine,
|
645
|
-
self.tr("Lines starting with any of these symbols are dialogue.")
|
660
|
+
self.tr("Lines starting with any of these symbols are dialogue."),
|
661
|
+
button=self.dialogLineButton
|
646
662
|
)
|
647
663
|
|
664
|
+
# Narrator Break
|
648
665
|
self.narratorBreak = NComboBox(self)
|
649
666
|
self.narratorDialog = NComboBox(self)
|
650
667
|
for key, value in nwQuotes.DASHES.items():
|
@@ -664,6 +681,7 @@ class GuiPreferences(NDialog):
|
|
664
681
|
self.tr("Alternates dialogue highlighting within any paragraph.")
|
665
682
|
)
|
666
683
|
|
684
|
+
# Emphasis
|
667
685
|
self.highlightEmph = NSwitch(self)
|
668
686
|
self.highlightEmph.setChecked(CONFIG.highlightEmph)
|
669
687
|
self.mainForm.addRow(
|
@@ -671,6 +689,7 @@ class GuiPreferences(NDialog):
|
|
671
689
|
self.tr("Applies to the document editor only.")
|
672
690
|
)
|
673
691
|
|
692
|
+
# Additional Spaces
|
674
693
|
self.showMultiSpaces = NSwitch(self)
|
675
694
|
self.showMultiSpaces.setChecked(CONFIG.showMultiSpaces)
|
676
695
|
self.mainForm.addRow(
|
@@ -906,6 +925,14 @@ class GuiPreferences(NDialog):
|
|
906
925
|
self.askBeforeBackup.setEnabled(state)
|
907
926
|
return
|
908
927
|
|
928
|
+
@pyqtSlot(str)
|
929
|
+
def _insertDialogLineSymbol(self, symbol: str) -> None:
|
930
|
+
"""Insert a symbol in the dialogue line box."""
|
931
|
+
current = self.dialogLine.text()
|
932
|
+
values = processDialogSymbols(f"{current} {symbol}")
|
933
|
+
self.dialogLine.setText(" ".join(values))
|
934
|
+
return
|
935
|
+
|
909
936
|
@pyqtSlot(bool)
|
910
937
|
def _toggleAutoReplaceMain(self, state: bool) -> None:
|
911
938
|
"""Toggle switches controlled by the auto replace switch."""
|
@@ -37,7 +37,7 @@ from PyQt6.QtCore import QMargins, QSize
|
|
37
37
|
from novelwriter import __version__
|
38
38
|
from novelwriter.common import firstFloat, xmlElement, xmlSubElem
|
39
39
|
from novelwriter.constants import nwHeadFmt, nwStyles
|
40
|
-
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt
|
40
|
+
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
|
41
41
|
from novelwriter.formats.tokenizer import Tokenizer
|
42
42
|
from novelwriter.types import QtHexRgb
|
43
43
|
|
@@ -480,7 +480,7 @@ class ToDocX(Tokenizer):
|
|
480
480
|
xmlSubElem(rPr, _wTag("color"), attrib={W_VAL: _docXCol(color)})
|
481
481
|
|
482
482
|
if isinstance(text, str):
|
483
|
-
for segment in RX_TEXT.split(text):
|
483
|
+
for segment in RX_TEXT.split(stripEscape(text)):
|
484
484
|
if segment == "\n":
|
485
485
|
xmlSubElem(xR, _wTag("br"))
|
486
486
|
elif segment == "\t":
|
@@ -495,12 +495,10 @@ class Tokenizer(ABC):
|
|
495
495
|
def doPreProcessing(self) -> None:
|
496
496
|
"""Run pre-processing jobs before the text is tokenized."""
|
497
497
|
# Process the user's auto-replace dictionary
|
498
|
-
if
|
499
|
-
|
500
|
-
for
|
501
|
-
|
502
|
-
xRep = re.compile("|".join([re.escape(k) for k in repDict.keys()]), flags=re.DOTALL)
|
503
|
-
self._text = xRep.sub(lambda x: repDict[x.group(0)], self._text)
|
498
|
+
if entry := self._project.data.autoReplace:
|
499
|
+
replace = {f"<{k}>": v for k, v in entry.items()}
|
500
|
+
rxRep = re.compile("|".join([re.escape(k) for k in replace]), flags=re.DOTALL)
|
501
|
+
self._text = rxRep.sub(lambda x: replace[x.group(0)], self._text)
|
504
502
|
return
|
505
503
|
|
506
504
|
def tokenizeText(self) -> None:
|
@@ -882,31 +880,21 @@ class Tokenizer(ABC):
|
|
882
880
|
if nBlock[0] != BlockTyp.TEXT:
|
883
881
|
# Next block is not text, so we add the buffer to blocks
|
884
882
|
nLines = len(pLines)
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
# turned off, and the block is not aligned, we add the
|
889
|
-
# text indentation flag
|
890
|
-
cStyle |= BlockFmt.IND_T
|
883
|
+
tFmt: T_Formats = []
|
884
|
+
pTxt = ""
|
885
|
+
cStyle = BlockFmt.NONE
|
891
886
|
|
892
887
|
if nLines == 1:
|
893
|
-
# The paragraph contains a single line
|
894
|
-
|
895
|
-
# enabled, and there is no alignment, we apply it.
|
896
|
-
if doJustify and not cStyle & BlockFmt.ALIGNED:
|
897
|
-
cStyle |= BlockFmt.JUSTIFY
|
898
|
-
|
888
|
+
# The paragraph contains a single line
|
889
|
+
tFmt = pLines[0][3]
|
899
890
|
pTxt = pLines[0][2].translate(transMapB)
|
900
|
-
|
901
|
-
BlockTyp.TEXT, pLines[0][1], pTxt, pLines[0][3], cStyle
|
902
|
-
))
|
891
|
+
cStyle = pLines[0][4]
|
903
892
|
|
904
893
|
elif nLines > 1:
|
905
894
|
# The paragraph contains multiple lines, so we need to
|
906
895
|
# join them according to the line break policy, and
|
907
896
|
# recompute all the formatting markers
|
908
897
|
tTxt = ""
|
909
|
-
tFmt: T_Formats = []
|
910
898
|
for aBlock in pLines:
|
911
899
|
tLen = len(tTxt)
|
912
900
|
tTxt += f"{aBlock[2]}{lineSep}"
|
@@ -914,6 +902,18 @@ class Tokenizer(ABC):
|
|
914
902
|
cStyle |= aBlock[4]
|
915
903
|
|
916
904
|
pTxt = tTxt[:-1].translate(transMapB)
|
905
|
+
|
906
|
+
if nLines:
|
907
|
+
isAligned = cStyle & BlockFmt.ALIGNED
|
908
|
+
if firstIndent and not (self._noIndent or isAligned):
|
909
|
+
# If paragraph indentation is enabled, not temporarily
|
910
|
+
# turned off, and the block is not aligned, we add the
|
911
|
+
# text indentation flag
|
912
|
+
cStyle |= BlockFmt.IND_T
|
913
|
+
|
914
|
+
if doJustify and not isAligned:
|
915
|
+
cStyle |= BlockFmt.JUSTIFY
|
916
|
+
|
917
917
|
sBlocks.append((
|
918
918
|
BlockTyp.TEXT, pLines[0][1], pTxt, tFmt, cStyle
|
919
919
|
))
|
@@ -1170,12 +1170,18 @@ class Tokenizer(ABC):
|
|
1170
1170
|
|
1171
1171
|
class HeadingFormatter:
|
1172
1172
|
|
1173
|
-
def __init__(
|
1173
|
+
def __init__(
|
1174
|
+
self,
|
1175
|
+
project: NWProject,
|
1176
|
+
chapter: int = 0,
|
1177
|
+
scene: int = 0,
|
1178
|
+
absolute: int = 0,
|
1179
|
+
) -> None:
|
1174
1180
|
self._project = project
|
1175
1181
|
self._handle = None
|
1176
|
-
self.
|
1177
|
-
self.
|
1178
|
-
self.
|
1182
|
+
self._chapter = chapter
|
1183
|
+
self._scene = scene
|
1184
|
+
self._absolute = absolute
|
1179
1185
|
return
|
1180
1186
|
|
1181
1187
|
def setHandle(self, tHandle: str | None) -> None:
|
@@ -1185,42 +1191,42 @@ class HeadingFormatter:
|
|
1185
1191
|
|
1186
1192
|
def incChapter(self) -> None:
|
1187
1193
|
"""Increment the chapter counter."""
|
1188
|
-
self.
|
1194
|
+
self._chapter += 1
|
1189
1195
|
return
|
1190
1196
|
|
1191
1197
|
def incScene(self) -> None:
|
1192
1198
|
"""Increment the scene counters."""
|
1193
|
-
self.
|
1194
|
-
self.
|
1199
|
+
self._scene += 1
|
1200
|
+
self._absolute += 1
|
1195
1201
|
return
|
1196
1202
|
|
1197
1203
|
def resetAll(self) -> None:
|
1198
1204
|
"""Reset all counters."""
|
1199
|
-
self.
|
1200
|
-
self.
|
1201
|
-
self.
|
1205
|
+
self._chapter = 0
|
1206
|
+
self._scene = 0
|
1207
|
+
self._absolute = 0
|
1202
1208
|
return
|
1203
1209
|
|
1204
1210
|
def resetScene(self) -> None:
|
1205
1211
|
"""Reset the chapter scene counter."""
|
1206
|
-
self.
|
1212
|
+
self._scene = 0
|
1207
1213
|
return
|
1208
1214
|
|
1209
1215
|
def apply(self, hFormat: str, text: str, nHead: int) -> str:
|
1210
1216
|
"""Apply formatting to a specific heading."""
|
1211
1217
|
hFormat = hFormat.replace(nwHeadFmt.TITLE, text)
|
1212
1218
|
hFormat = hFormat.replace(nwHeadFmt.BR, "\n")
|
1213
|
-
hFormat = hFormat.replace(nwHeadFmt.CH_NUM, str(self.
|
1214
|
-
hFormat = hFormat.replace(nwHeadFmt.SC_NUM, str(self.
|
1215
|
-
hFormat = hFormat.replace(nwHeadFmt.SC_ABS, str(self.
|
1219
|
+
hFormat = hFormat.replace(nwHeadFmt.CH_NUM, str(self._chapter))
|
1220
|
+
hFormat = hFormat.replace(nwHeadFmt.SC_NUM, str(self._scene))
|
1221
|
+
hFormat = hFormat.replace(nwHeadFmt.SC_ABS, str(self._absolute))
|
1216
1222
|
if nwHeadFmt.CH_WORD in hFormat:
|
1217
|
-
chWord = self._project.localLookup(self.
|
1223
|
+
chWord = self._project.localLookup(self._chapter)
|
1218
1224
|
hFormat = hFormat.replace(nwHeadFmt.CH_WORD, chWord)
|
1219
1225
|
if nwHeadFmt.CH_ROML in hFormat:
|
1220
|
-
chRom = numberToRoman(self.
|
1226
|
+
chRom = numberToRoman(self._chapter, toLower=True)
|
1221
1227
|
hFormat = hFormat.replace(nwHeadFmt.CH_ROML, chRom)
|
1222
1228
|
if nwHeadFmt.CH_ROMU in hFormat:
|
1223
|
-
chRom = numberToRoman(self.
|
1229
|
+
chRom = numberToRoman(self._chapter, toLower=False)
|
1224
1230
|
hFormat = hFormat.replace(nwHeadFmt.CH_ROMU, chRom)
|
1225
1231
|
|
1226
1232
|
if nwHeadFmt.CHAR_POV in hFormat or nwHeadFmt.CHAR_FOCUS in hFormat:
|
@@ -36,12 +36,13 @@ from PyQt6.QtPrintSupport import QPrinter
|
|
36
36
|
|
37
37
|
from novelwriter import __version__
|
38
38
|
from novelwriter.constants import nwStyles, nwUnicode
|
39
|
-
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt
|
39
|
+
from novelwriter.formats.shared import BlockFmt, BlockTyp, T_Formats, TextFmt, stripEscape
|
40
40
|
from novelwriter.formats.tokenizer import HEADINGS, Tokenizer
|
41
41
|
from novelwriter.types import (
|
42
42
|
QtAlignAbsolute, QtAlignCenter, QtAlignJustify, QtAlignLeft, QtAlignRight,
|
43
|
-
QtKeepAnchor, QtMoveAnchor, QtPageBreakAfter,
|
44
|
-
QtPropLineHeight, QtTransparent, QtVAlignNormal,
|
43
|
+
QtKeepAnchor, QtMoveAnchor, QtPageBreakAfter, QtPageBreakAuto,
|
44
|
+
QtPageBreakBefore, QtPropLineHeight, QtTransparent, QtVAlignNormal,
|
45
|
+
QtVAlignSub, QtVAlignSuper
|
45
46
|
)
|
46
47
|
|
47
48
|
if TYPE_CHECKING:
|
@@ -253,8 +254,10 @@ class ToQTextDocument(Tokenizer):
|
|
253
254
|
|
254
255
|
elif tType in HEADINGS:
|
255
256
|
bFmt, cFmt = self._genHeadStyle(tType, tMeta, bFmt)
|
256
|
-
|
257
|
-
|
257
|
+
for tPart in tText.split("\n"):
|
258
|
+
newBlock(cursor, bFmt)
|
259
|
+
cursor.insertText(tPart, cFmt)
|
260
|
+
bFmt.setPageBreakPolicy(QtPageBreakAuto)
|
258
261
|
|
259
262
|
elif tType == BlockTyp.SEP:
|
260
263
|
newBlock(cursor, bFmt)
|
@@ -343,7 +346,7 @@ class ToQTextDocument(Tokenizer):
|
|
343
346
|
for pos, fmt, data in tFmt:
|
344
347
|
|
345
348
|
# Insert buffer with previous format
|
346
|
-
cursor.insertText(temp[start:pos], cFmt)
|
349
|
+
cursor.insertText(stripEscape(temp[start:pos]), cFmt)
|
347
350
|
|
348
351
|
# Construct next format
|
349
352
|
if fmt == TextFmt.B_B:
|
@@ -425,13 +428,12 @@ class ToQTextDocument(Tokenizer):
|
|
425
428
|
if field := data.partition(":")[2]:
|
426
429
|
self._usedFields.append((cursor.position(), field))
|
427
430
|
cursor.insertText("0", cFmt)
|
428
|
-
pass
|
429
431
|
|
430
432
|
# Move pos for next pass
|
431
433
|
start = pos
|
432
434
|
|
433
435
|
# Insert whatever is left in the buffer
|
434
|
-
cursor.insertText(temp[start:], cFmt)
|
436
|
+
cursor.insertText(stripEscape(temp[start:]), cFmt)
|
435
437
|
|
436
438
|
return
|
437
439
|
|
@@ -228,6 +228,8 @@ class GuiDocViewer(QTextBrowser):
|
|
228
228
|
qDoc.setTheme(self._docTheme)
|
229
229
|
qDoc.initDocument()
|
230
230
|
qDoc.setKeywords(True)
|
231
|
+
qDoc.setCommentType(nwComment.NOTE, CONFIG.viewComments)
|
232
|
+
qDoc.setCommentType(nwComment.STORY, CONFIG.viewComments)
|
231
233
|
qDoc.setCommentType(nwComment.PLAIN, CONFIG.viewComments)
|
232
234
|
qDoc.setCommentType(nwComment.SYNOPSIS, CONFIG.viewSynopsis)
|
233
235
|
qDoc.setCommentType(nwComment.SHORT, CONFIG.viewSynopsis)
|