novelWriter 2.6.3__py3-none-any.whl → 2.7__py3-none-any.whl
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/__init__.py +98 -75
- novelwriter/assets/i18n/nw_cs_CZ.qm +0 -0
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_en_US.qm +0 -0
- novelwriter/assets/i18n/nw_es_419.qm +0 -0
- novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
- novelwriter/assets/i18n/nw_pl_PL.qm +0 -0
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
- novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +3 -1
- novelwriter/assets/i18n/project_en_GB.json +2 -0
- novelwriter/assets/i18n/project_en_US.json +2 -0
- novelwriter/assets/i18n/project_it_IT.json +2 -0
- novelwriter/assets/i18n/project_ja_JP.json +2 -0
- novelwriter/assets/i18n/project_nb_NO.json +2 -0
- novelwriter/assets/i18n/project_nn_NO.json +5 -0
- novelwriter/assets/i18n/project_pl_PL.json +2 -0
- novelwriter/assets/i18n/project_pt_BR.json +2 -0
- novelwriter/assets/i18n/project_ru_RU.json +2 -0
- novelwriter/assets/i18n/project_zh_CN.json +2 -0
- novelwriter/assets/icons/font_awesome.icons +109 -0
- novelwriter/assets/icons/material_filled_bold.icons +109 -0
- novelwriter/assets/icons/material_filled_normal.icons +109 -0
- novelwriter/assets/icons/material_filled_thin.icons +109 -0
- novelwriter/assets/icons/material_rounded_bold.icons +109 -0
- novelwriter/assets/icons/material_rounded_normal.icons +109 -0
- novelwriter/assets/icons/material_rounded_thin.icons +109 -0
- novelwriter/assets/icons/remix_filled.icons +109 -0
- novelwriter/assets/icons/remix_outline.icons +109 -0
- novelwriter/assets/images/splash.png +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/{manual_fr_FR.pdf → manual_fr.pdf} +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +1 -1
- novelwriter/assets/syntax/snazzy.conf +3 -3
- novelwriter/assets/text/credits_en.htm +12 -6
- novelwriter/assets/themes/cyberpunk_night.conf +23 -7
- novelwriter/assets/themes/default_dark.conf +20 -4
- novelwriter/assets/themes/default_light.conf +21 -5
- novelwriter/assets/themes/dracula.conf +20 -4
- novelwriter/assets/themes/snazzy.conf +48 -0
- novelwriter/assets/themes/solarized_dark.conf +24 -8
- novelwriter/assets/themes/solarized_light.conf +22 -6
- novelwriter/common.py +43 -27
- novelwriter/config.py +201 -139
- novelwriter/constants.py +67 -36
- novelwriter/core/buildsettings.py +26 -17
- novelwriter/core/coretools.py +52 -41
- novelwriter/core/docbuild.py +20 -13
- novelwriter/core/document.py +2 -2
- novelwriter/core/index.py +166 -432
- novelwriter/core/indexdata.py +406 -0
- novelwriter/core/item.py +50 -32
- novelwriter/core/itemmodel.py +43 -38
- novelwriter/core/novelmodel.py +225 -0
- novelwriter/core/options.py +1 -1
- novelwriter/core/project.py +24 -25
- novelwriter/core/projectdata.py +47 -29
- novelwriter/core/projectxml.py +18 -8
- novelwriter/core/sessions.py +32 -15
- novelwriter/core/spellcheck.py +4 -3
- novelwriter/core/status.py +12 -15
- novelwriter/core/storage.py +1 -1
- novelwriter/core/tree.py +55 -13
- novelwriter/dialogs/about.py +19 -22
- novelwriter/dialogs/docmerge.py +23 -24
- novelwriter/dialogs/docsplit.py +26 -26
- novelwriter/dialogs/editlabel.py +19 -20
- novelwriter/dialogs/preferences.py +143 -69
- novelwriter/dialogs/projectsettings.py +51 -54
- novelwriter/dialogs/quotes.py +14 -19
- novelwriter/dialogs/wordlist.py +25 -30
- novelwriter/enum.py +8 -0
- novelwriter/error.py +16 -16
- novelwriter/extensions/configlayout.py +24 -20
- novelwriter/extensions/eventfilters.py +9 -5
- novelwriter/extensions/modified.py +34 -15
- novelwriter/extensions/novelselector.py +18 -5
- novelwriter/extensions/pagedsidebar.py +39 -49
- novelwriter/extensions/progressbars.py +10 -8
- novelwriter/extensions/statusled.py +6 -13
- novelwriter/extensions/switch.py +31 -41
- novelwriter/extensions/switchbox.py +8 -3
- novelwriter/extensions/versioninfo.py +4 -4
- novelwriter/formats/shared.py +1 -1
- novelwriter/formats/todocx.py +14 -10
- novelwriter/formats/tohtml.py +7 -5
- novelwriter/formats/tokenizer.py +37 -33
- novelwriter/formats/tomarkdown.py +6 -2
- novelwriter/formats/toodt.py +27 -22
- novelwriter/formats/toqdoc.py +19 -14
- novelwriter/formats/toraw.py +6 -2
- novelwriter/gui/doceditor.py +314 -305
- novelwriter/gui/dochighlight.py +46 -45
- novelwriter/gui/docviewer.py +102 -104
- novelwriter/gui/docviewerpanel.py +47 -51
- novelwriter/gui/editordocument.py +8 -5
- novelwriter/gui/itemdetails.py +11 -14
- novelwriter/gui/mainmenu.py +146 -145
- novelwriter/gui/noveltree.py +246 -406
- novelwriter/gui/outline.py +141 -72
- novelwriter/gui/projtree.py +139 -132
- novelwriter/gui/search.py +34 -31
- novelwriter/gui/sidebar.py +13 -18
- novelwriter/gui/statusbar.py +27 -21
- novelwriter/gui/theme.py +554 -436
- novelwriter/guimain.py +56 -38
- novelwriter/shared.py +32 -23
- novelwriter/splash.py +74 -0
- novelwriter/text/comments.py +70 -0
- novelwriter/text/patterns.py +4 -4
- novelwriter/tools/dictionaries.py +20 -29
- novelwriter/tools/lipsum.py +18 -18
- novelwriter/tools/manusbuild.py +39 -42
- novelwriter/tools/manuscript.py +102 -115
- novelwriter/tools/manussettings.py +129 -102
- novelwriter/tools/noveldetails.py +60 -72
- novelwriter/tools/welcome.py +57 -75
- novelwriter/tools/writingstats.py +112 -102
- novelwriter/types.py +5 -7
- {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/METADATA +6 -6
- novelwriter-2.7.dist-info/RECORD +162 -0
- {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/WHEEL +1 -1
- novelWriter-2.6.3.dist-info/RECORD +0 -363
- novelwriter/assets/icons/typicons_dark/README.md +0 -29
- novelwriter/assets/icons/typicons_dark/icons.conf +0 -134
- novelwriter/assets/icons/typicons_dark/mixed_copy.svg +0 -4
- novelwriter/assets/icons/typicons_dark/mixed_document-chapter.svg +0 -12
- novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_document-note.svg +0 -12
- novelwriter/assets/icons/typicons_dark/mixed_document-scene.svg +0 -12
- novelwriter/assets/icons/typicons_dark/mixed_document-section.svg +0 -12
- novelwriter/assets/icons/typicons_dark/mixed_document-title.svg +0 -12
- novelwriter/assets/icons/typicons_dark/mixed_edit.svg +0 -4
- novelwriter/assets/icons/typicons_dark/mixed_import.svg +0 -5
- novelwriter/assets/icons/typicons_dark/mixed_input-checked.svg +0 -5
- novelwriter/assets/icons/typicons_dark/mixed_input-none.svg +0 -5
- novelwriter/assets/icons/typicons_dark/mixed_input-unchecked.svg +0 -5
- novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_search-replace.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +0 -6
- novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +0 -6
- novelwriter/assets/icons/typicons_dark/nw_deco-h0.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h1.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h2.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h3.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-h4.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_deco-noveltree-more.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_font.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_panel.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_quote.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_search-case.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_search-preserve.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_search-regex.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_search-word.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +0 -6
- novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +0 -6
- novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +0 -7
- novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +0 -4
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +0 -6
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +0 -7
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +0 -7
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +0 -7
- novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +0 -5
- novelwriter/assets/icons/typicons_dark/typ_arrow-down-thick-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_arrow-forward.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_arrow-maximise.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_arrow-minimise.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_arrow-repeat-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_book-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_book.svg +0 -6
- novelwriter/assets/icons/typicons_dark/typ_bookmark.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_calendar.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_cancel-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_cancel.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_chart-bar-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_chevron-down.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_chevron-left.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_chevron-right.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_chevron-up.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_cog.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_delete-full.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_delete.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_directions-full.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_document-add.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_document-text.svg +0 -8
- novelwriter/assets/icons/typicons_dark/typ_document.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_export-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_export.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_eye.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_flag.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_folder-open.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_folder.svg +0 -5
- novelwriter/assets/icons/typicons_dark/typ_globe-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_key.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_lightbulb-full.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_location.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_media-pause-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_media-record-outline.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_media-record.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_minus.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_pencil.svg +0 -5
- novelwriter/assets/icons/typicons_dark/typ_pin-outline.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_pin.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_plus.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_puzzle-outline.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_puzzle.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_refresh.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_search.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_star.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_stopwatch-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_th-dot-menu.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_th-list-grey.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_th-list.svg +0 -9
- novelwriter/assets/icons/typicons_dark/typ_times.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_trash.svg +0 -5
- novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +0 -4
- novelwriter/assets/icons/typicons_dark/typ_user.svg +0 -5
- novelwriter/assets/icons/typicons_dark/typ_warning-full.svg +0 -4
- novelwriter/assets/icons/typicons_light/README.md +0 -29
- novelwriter/assets/icons/typicons_light/icons.conf +0 -134
- novelwriter/assets/icons/typicons_light/mixed_copy.svg +0 -4
- novelwriter/assets/icons/typicons_light/mixed_document-chapter.svg +0 -12
- novelwriter/assets/icons/typicons_light/mixed_document-new.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_document-note.svg +0 -12
- novelwriter/assets/icons/typicons_light/mixed_document-scene.svg +0 -12
- novelwriter/assets/icons/typicons_light/mixed_document-section.svg +0 -12
- novelwriter/assets/icons/typicons_light/mixed_document-title.svg +0 -12
- novelwriter/assets/icons/typicons_light/mixed_edit.svg +0 -4
- novelwriter/assets/icons/typicons_light/mixed_import.svg +0 -5
- novelwriter/assets/icons/typicons_light/mixed_input-checked.svg +0 -5
- novelwriter/assets/icons/typicons_light/mixed_input-none.svg +0 -5
- novelwriter/assets/icons/typicons_light/mixed_input-unchecked.svg +0 -5
- novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_search-replace.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_size-height.svg +0 -6
- novelwriter/assets/icons/typicons_light/mixed_size-width.svg +0 -6
- novelwriter/assets/icons/typicons_light/nw_deco-h0.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h1.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h2.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h3.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-h4.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-note.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_deco-noveltree-more.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_font.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_panel.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_quote.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_search-case.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_search-preserve.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_search-regex.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_search-word.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +0 -6
- novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +0 -6
- novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +0 -7
- novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +0 -6
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +0 -7
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +0 -7
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +0 -7
- novelwriter/assets/icons/typicons_light/nw_toolbar.svg +0 -5
- novelwriter/assets/icons/typicons_light/typ_arrow-down-thick-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-forward.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-maximise.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-minimise.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_arrow-repeat-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_book-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_book.svg +0 -6
- novelwriter/assets/icons/typicons_light/typ_bookmark.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_calendar.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_cancel-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_cancel.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_chart-bar-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_chevron-down.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_chevron-left.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_chevron-right.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_chevron-up.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_cog.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_delete-full.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_delete.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_directions-full.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_document-add.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_document-text.svg +0 -5
- novelwriter/assets/icons/typicons_light/typ_document.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_export-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_export.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_eye.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_flag.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_folder-open.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_folder.svg +0 -5
- novelwriter/assets/icons/typicons_light/typ_globe-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_key.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_lightbulb-full.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_location.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_media-pause-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_media-record-outline.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_media-record.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_minus.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_pencil.svg +0 -5
- novelwriter/assets/icons/typicons_light/typ_pin-outline.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_pin.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_plus.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_puzzle-outline.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_puzzle.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_refresh.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_search-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_search.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_star.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_stopwatch-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_th-dot-menu.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_th-list-grey.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_th-list.svg +0 -9
- novelwriter/assets/icons/typicons_light/typ_times.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_trash.svg +0 -5
- novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +0 -4
- novelwriter/assets/icons/typicons_light/typ_user.svg +0 -5
- novelwriter/assets/icons/typicons_light/typ_warning-full.svg +0 -4
- {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info/licenses}/LICENSE.md +0 -0
- {novelWriter-2.6.3.dist-info → novelwriter-2.7.dist-info}/top_level.txt +0 -0
novelwriter/constants.py
CHANGED
@@ -23,7 +23,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
23
23
|
"""
|
24
24
|
from __future__ import annotations
|
25
25
|
|
26
|
-
from
|
26
|
+
from typing import Final
|
27
|
+
|
28
|
+
from PyQt6.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
|
27
29
|
|
28
30
|
from novelwriter.enum import (
|
29
31
|
nwBuildFmt, nwComment, nwItemClass, nwItemLayout, nwOutline, nwStatusShape
|
@@ -99,7 +101,7 @@ class nwShortcode:
|
|
99
101
|
FOOTNOTE_B = "[footnote:"
|
100
102
|
FIELD_B = "[field:"
|
101
103
|
|
102
|
-
COMMENT_STYLES = {
|
104
|
+
COMMENT_STYLES: Final[dict[nwComment, str]] = {
|
103
105
|
nwComment.FOOTNOTE: "[footnote:{0}]",
|
104
106
|
nwComment.COMMENT: "[comment:{0}]",
|
105
107
|
}
|
@@ -110,13 +112,13 @@ class nwShortcode:
|
|
110
112
|
class nwStyles:
|
111
113
|
|
112
114
|
H_VALID = ("H0", "H1", "H2", "H3", "H4")
|
113
|
-
H_LEVEL = {"H0": 0, "H1": 1, "H2": 2, "H3": 3, "H4": 4}
|
114
|
-
H_SIZES = {0: 2.50, 1: 2.00, 2: 1.75, 3: 1.50, 4: 1.25}
|
115
|
+
H_LEVEL: Final[dict[str, int]] = {"H0": 0, "H1": 1, "H2": 2, "H3": 3, "H4": 4}
|
116
|
+
H_SIZES: Final[dict[int, float]] = {0: 2.50, 1: 2.00, 2: 1.75, 3: 1.50, 4: 1.25}
|
115
117
|
|
116
118
|
T_NORMAL = 1.0
|
117
119
|
T_SMALL = 0.8
|
118
120
|
|
119
|
-
T_LABEL = {
|
121
|
+
T_LABEL: Final[dict[str, str]] = {
|
120
122
|
"H0": QT_TRANSLATE_NOOP("Constant", "Title"),
|
121
123
|
"H1": QT_TRANSLATE_NOOP("Constant", "Heading 1 (Partition)"),
|
122
124
|
"H2": QT_TRANSLATE_NOOP("Constant", "Heading 2 (Chapter)"),
|
@@ -125,7 +127,7 @@ class nwStyles:
|
|
125
127
|
"TT": QT_TRANSLATE_NOOP("Constant", "Text Paragraph"),
|
126
128
|
"SP": QT_TRANSLATE_NOOP("Constant", "Scene Separator"),
|
127
129
|
}
|
128
|
-
T_MARGIN = {
|
130
|
+
T_MARGIN: Final[dict[str, tuple[float, float]]] = {
|
129
131
|
"H0": (1.50, 0.60), # Title margins (top, bottom)
|
130
132
|
"H1": (1.50, 0.60), # Heading 1 margins (top, bottom)
|
131
133
|
"H2": (1.50, 0.60), # Heading 2 margins (top, bottom)
|
@@ -174,20 +176,20 @@ class nwKeyWords:
|
|
174
176
|
MENTION_KEY = "@mention"
|
175
177
|
|
176
178
|
# Note: The order here affects the order of menu entries
|
177
|
-
ALL_KEYS = [
|
179
|
+
ALL_KEYS: Final[list[str]] = [
|
178
180
|
TAG_KEY, POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
|
179
181
|
OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY, STORY_KEY, MENTION_KEY,
|
180
182
|
]
|
181
|
-
CAN_CREATE = [
|
183
|
+
CAN_CREATE: Final[list[str]] = [
|
182
184
|
POV_KEY, FOCUS_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, WORLD_KEY,
|
183
185
|
OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY,
|
184
186
|
]
|
185
187
|
|
186
188
|
# Set of Valid Keys
|
187
|
-
VALID_KEYS = set(ALL_KEYS)
|
189
|
+
VALID_KEYS: Final[set[str]] = set(ALL_KEYS)
|
188
190
|
|
189
191
|
# Map from Keys to Item Class
|
190
|
-
KEY_CLASS = {
|
192
|
+
KEY_CLASS: Final[dict[str, nwItemClass]] = {
|
191
193
|
POV_KEY: nwItemClass.CHARACTER,
|
192
194
|
FOCUS_KEY: nwItemClass.CHARACTER,
|
193
195
|
CHAR_KEY: nwItemClass.CHARACTER,
|
@@ -203,7 +205,7 @@ class nwKeyWords:
|
|
203
205
|
|
204
206
|
class nwLists:
|
205
207
|
|
206
|
-
USER_CLASSES = [
|
208
|
+
USER_CLASSES: Final[list[nwItemClass]] = [
|
207
209
|
nwItemClass.CHARACTER,
|
208
210
|
nwItemClass.PLOT,
|
209
211
|
nwItemClass.WORLD,
|
@@ -229,7 +231,7 @@ class nwStats:
|
|
229
231
|
WORDS_TITLE = "titleWords"
|
230
232
|
|
231
233
|
# Note: The order here affects the order of menu entries
|
232
|
-
ALL_FIELDS = [
|
234
|
+
ALL_FIELDS: Final[list[str]] = [
|
233
235
|
WORDS, WORDS_TEXT, WORDS_TITLE,
|
234
236
|
CHARS, CHARS_TEXT, CHARS_TITLE,
|
235
237
|
WCHARS_ALL, WCHARS_TEXT, WCHARS_TITLE,
|
@@ -239,7 +241,7 @@ class nwStats:
|
|
239
241
|
|
240
242
|
class nwLabels:
|
241
243
|
|
242
|
-
CLASS_NAME = {
|
244
|
+
CLASS_NAME: Final[dict[nwItemClass, str]] = {
|
243
245
|
nwItemClass.NO_CLASS: QT_TRANSLATE_NOOP("Constant", "None"),
|
244
246
|
nwItemClass.NOVEL: QT_TRANSLATE_NOOP("Constant", "Novel"),
|
245
247
|
nwItemClass.PLOT: QT_TRANSLATE_NOOP("Constant", "Plot"),
|
@@ -253,7 +255,7 @@ class nwLabels:
|
|
253
255
|
nwItemClass.TEMPLATE: QT_TRANSLATE_NOOP("Constant", "Templates"),
|
254
256
|
nwItemClass.TRASH: QT_TRANSLATE_NOOP("Constant", "Trash"),
|
255
257
|
}
|
256
|
-
CLASS_ICON = {
|
258
|
+
CLASS_ICON: Final[dict[nwItemClass, str]] = {
|
257
259
|
nwItemClass.NO_CLASS: "cls_none",
|
258
260
|
nwItemClass.NOVEL: "cls_novel",
|
259
261
|
nwItemClass.PLOT: "cls_plot",
|
@@ -267,12 +269,12 @@ class nwLabels:
|
|
267
269
|
nwItemClass.TEMPLATE: "cls_template",
|
268
270
|
nwItemClass.TRASH: "cls_trash",
|
269
271
|
}
|
270
|
-
LAYOUT_NAME = {
|
272
|
+
LAYOUT_NAME: Final[dict[nwItemLayout, str]] = {
|
271
273
|
nwItemLayout.NO_LAYOUT: QT_TRANSLATE_NOOP("Constant", "None"),
|
272
274
|
nwItemLayout.DOCUMENT: QT_TRANSLATE_NOOP("Constant", "Novel Document"),
|
273
275
|
nwItemLayout.NOTE: QT_TRANSLATE_NOOP("Constant", "Project Note"),
|
274
276
|
}
|
275
|
-
ITEM_DESCRIPTION = {
|
277
|
+
ITEM_DESCRIPTION: Final[dict[str, str]] = {
|
276
278
|
"none": QT_TRANSLATE_NOOP("Constant", "None"),
|
277
279
|
"root": QT_TRANSLATE_NOOP("Constant", "Root Folder"),
|
278
280
|
"folder": QT_TRANSLATE_NOOP("Constant", "Folder"),
|
@@ -283,11 +285,11 @@ class nwLabels:
|
|
283
285
|
"doc_h4": QT_TRANSLATE_NOOP("Constant", "Novel Section"),
|
284
286
|
"note": QT_TRANSLATE_NOOP("Constant", "Project Note"),
|
285
287
|
}
|
286
|
-
ACTIVE_NAME = {
|
288
|
+
ACTIVE_NAME: Final[dict[str, str]] = {
|
287
289
|
"checked": QT_TRANSLATE_NOOP("Constant", "Active"),
|
288
290
|
"unchecked": QT_TRANSLATE_NOOP("Constant", "Inactive"),
|
289
291
|
}
|
290
|
-
KEY_NAME = {
|
292
|
+
KEY_NAME: Final[dict[str, str]] = {
|
291
293
|
nwKeyWords.TAG_KEY: QT_TRANSLATE_NOOP("Constant", "Tag"),
|
292
294
|
nwKeyWords.POV_KEY: QT_TRANSLATE_NOOP("Constant", "Point of View"),
|
293
295
|
nwKeyWords.FOCUS_KEY: QT_TRANSLATE_NOOP("Constant", "Focus"),
|
@@ -301,7 +303,7 @@ class nwLabels:
|
|
301
303
|
nwKeyWords.STORY_KEY: QT_TRANSLATE_NOOP("Constant", "Story"),
|
302
304
|
nwKeyWords.MENTION_KEY: QT_TRANSLATE_NOOP("Constant", "Mentions"),
|
303
305
|
}
|
304
|
-
KEY_SHORTCUT = {
|
306
|
+
KEY_SHORTCUT: Final[dict[str, str]] = {
|
305
307
|
nwKeyWords.TAG_KEY: "Ctrl+K, G",
|
306
308
|
nwKeyWords.POV_KEY: "Ctrl+K, V",
|
307
309
|
nwKeyWords.FOCUS_KEY: "Ctrl+K, F",
|
@@ -315,7 +317,7 @@ class nwLabels:
|
|
315
317
|
nwKeyWords.STORY_KEY: "Ctrl+K, N",
|
316
318
|
nwKeyWords.MENTION_KEY: "Ctrl+K, M",
|
317
319
|
}
|
318
|
-
OUTLINE_COLS = {
|
320
|
+
OUTLINE_COLS: Final[dict[nwOutline, str]] = {
|
319
321
|
nwOutline.TITLE: QT_TRANSLATE_NOOP("Constant", "Title"),
|
320
322
|
nwOutline.LEVEL: QT_TRANSLATE_NOOP("Constant", "Level"),
|
321
323
|
nwOutline.LABEL: QT_TRANSLATE_NOOP("Constant", "Document"),
|
@@ -337,7 +339,7 @@ class nwLabels:
|
|
337
339
|
nwOutline.MENTION: KEY_NAME[nwKeyWords.MENTION_KEY],
|
338
340
|
nwOutline.SYNOP: QT_TRANSLATE_NOOP("Constant", "Synopsis"),
|
339
341
|
}
|
340
|
-
STATS_NAME = {
|
342
|
+
STATS_NAME: Final[dict[str, str]] = {
|
341
343
|
nwStats.CHARS: QT_TRANSLATE_NOOP("Stats", "Characters"),
|
342
344
|
nwStats.CHARS_TEXT: QT_TRANSLATE_NOOP("Stats", "Characters in Text"),
|
343
345
|
nwStats.CHARS_TITLE: QT_TRANSLATE_NOOP("Stats", "Characters in Headings"),
|
@@ -350,7 +352,11 @@ class nwLabels:
|
|
350
352
|
nwStats.WORDS_TEXT: QT_TRANSLATE_NOOP("Stats", "Words in Text"),
|
351
353
|
nwStats.WORDS_TITLE: QT_TRANSLATE_NOOP("Stats", "Words in Headings"),
|
352
354
|
}
|
353
|
-
|
355
|
+
STATS_DISPLAY: Final[dict[str, str]] = {
|
356
|
+
nwStats.CHARS: QT_TRANSLATE_NOOP("Stats", "Characters: {0} ({1})"),
|
357
|
+
nwStats.WORDS: QT_TRANSLATE_NOOP("Stats", "Words: {0} ({1})"),
|
358
|
+
}
|
359
|
+
BUILD_FMT: Final[dict[nwBuildFmt, str]] = {
|
354
360
|
nwBuildFmt.ODT: QT_TRANSLATE_NOOP("Constant", "Open Document (.odt)"),
|
355
361
|
nwBuildFmt.FODT: QT_TRANSLATE_NOOP("Constant", "Flat Open Document (.fodt)"),
|
356
362
|
nwBuildFmt.DOCX: QT_TRANSLATE_NOOP("Constant", "Microsoft Word Document (.docx)"),
|
@@ -362,7 +368,7 @@ class nwLabels:
|
|
362
368
|
nwBuildFmt.J_HTML: QT_TRANSLATE_NOOP("Constant", "JSON + HTML 5 (.json)"),
|
363
369
|
nwBuildFmt.J_NWD: QT_TRANSLATE_NOOP("Constant", "JSON + novelWriter Markup (.json)"),
|
364
370
|
}
|
365
|
-
BUILD_EXT = {
|
371
|
+
BUILD_EXT: Final[dict[nwBuildFmt, str]] = {
|
366
372
|
nwBuildFmt.ODT: ".odt",
|
367
373
|
nwBuildFmt.FODT: ".fodt",
|
368
374
|
nwBuildFmt.DOCX: ".docx",
|
@@ -374,7 +380,7 @@ class nwLabels:
|
|
374
380
|
nwBuildFmt.J_HTML: ".json",
|
375
381
|
nwBuildFmt.J_NWD: ".json",
|
376
382
|
}
|
377
|
-
SHAPES_PLAIN = {
|
383
|
+
SHAPES_PLAIN: Final[dict[nwStatusShape, str]] = {
|
378
384
|
nwStatusShape.SQUARE: QT_TRANSLATE_NOOP("Constant", "Square"),
|
379
385
|
nwStatusShape.TRIANGLE: QT_TRANSLATE_NOOP("Constant", "Triangle"),
|
380
386
|
nwStatusShape.NABLA: QT_TRANSLATE_NOOP("Constant", "Nabla"),
|
@@ -384,42 +390,42 @@ class nwLabels:
|
|
384
390
|
nwStatusShape.STAR: QT_TRANSLATE_NOOP("Constant", "Star"),
|
385
391
|
nwStatusShape.PACMAN: QT_TRANSLATE_NOOP("Constant", "Pacman"),
|
386
392
|
}
|
387
|
-
SHAPES_CIRCLE = {
|
393
|
+
SHAPES_CIRCLE: Final[dict[nwStatusShape, str]] = {
|
388
394
|
nwStatusShape.CIRCLE_Q: QT_TRANSLATE_NOOP("Constant", "1/4 Circle"),
|
389
395
|
nwStatusShape.CIRCLE_H: QT_TRANSLATE_NOOP("Constant", "Half Circle"),
|
390
396
|
nwStatusShape.CIRCLE_T: QT_TRANSLATE_NOOP("Constant", "3/4 Circle"),
|
391
397
|
nwStatusShape.CIRCLE: QT_TRANSLATE_NOOP("Constant", "Full Circle"),
|
392
398
|
}
|
393
|
-
SHAPES_BARS = {
|
399
|
+
SHAPES_BARS: Final[dict[nwStatusShape, str]] = {
|
394
400
|
nwStatusShape.BARS_1: QT_TRANSLATE_NOOP("Constant", "1 Bar"),
|
395
401
|
nwStatusShape.BARS_2: QT_TRANSLATE_NOOP("Constant", "2 Bars"),
|
396
402
|
nwStatusShape.BARS_3: QT_TRANSLATE_NOOP("Constant", "3 Bars"),
|
397
403
|
nwStatusShape.BARS_4: QT_TRANSLATE_NOOP("Constant", "4 Bars"),
|
398
404
|
}
|
399
|
-
SHAPES_BLOCKS = {
|
405
|
+
SHAPES_BLOCKS: Final[dict[nwStatusShape, str]] = {
|
400
406
|
nwStatusShape.BLOCK_1: QT_TRANSLATE_NOOP("Constant", "1 Block"),
|
401
407
|
nwStatusShape.BLOCK_2: QT_TRANSLATE_NOOP("Constant", "2 Blocks"),
|
402
408
|
nwStatusShape.BLOCK_3: QT_TRANSLATE_NOOP("Constant", "3 Blocks"),
|
403
409
|
nwStatusShape.BLOCK_4: QT_TRANSLATE_NOOP("Constant", "4 Blocks"),
|
404
410
|
}
|
405
|
-
FILE_FILTERS = {
|
411
|
+
FILE_FILTERS: Final[dict[str, str]] = {
|
406
412
|
"*.txt": QT_TRANSLATE_NOOP("Constant", "Text files"),
|
407
413
|
"*.md": QT_TRANSLATE_NOOP("Constant", "Markdown files"),
|
408
414
|
"*.nwd": QT_TRANSLATE_NOOP("Constant", "novelWriter files"),
|
409
415
|
"*.csv": QT_TRANSLATE_NOOP("Constant", "CSV files"),
|
410
416
|
"*": QT_TRANSLATE_NOOP("Constant", "All files"),
|
411
417
|
}
|
412
|
-
UNIT_NAME = {
|
418
|
+
UNIT_NAME: Final[dict[str, str]] = {
|
413
419
|
"mm": QT_TRANSLATE_NOOP("Constant", "Millimetres"),
|
414
420
|
"cm": QT_TRANSLATE_NOOP("Constant", "Centimetres"),
|
415
421
|
"in": QT_TRANSLATE_NOOP("Constant", "Inches"),
|
416
422
|
}
|
417
|
-
UNIT_SCALE = {
|
423
|
+
UNIT_SCALE: Final[dict[str, float]] = {
|
418
424
|
"mm": 1.0,
|
419
425
|
"cm": 10.0,
|
420
426
|
"in": 25.4,
|
421
427
|
}
|
422
|
-
PAPER_NAME = {
|
428
|
+
PAPER_NAME: Final[dict[str, str]] = {
|
423
429
|
"A4": QT_TRANSLATE_NOOP("Constant", "A4"),
|
424
430
|
"A5": QT_TRANSLATE_NOOP("Constant", "A5"),
|
425
431
|
"A6": QT_TRANSLATE_NOOP("Constant", "A6"),
|
@@ -427,7 +433,7 @@ class nwLabels:
|
|
427
433
|
"Letter": QT_TRANSLATE_NOOP("Constant", "US Letter"),
|
428
434
|
"Custom": QT_TRANSLATE_NOOP("Constant", "Custom"),
|
429
435
|
}
|
430
|
-
PAPER_SIZE = {
|
436
|
+
PAPER_SIZE: Final[dict[str, tuple[float, float]]] = {
|
431
437
|
"A4": (210.0, 297.0),
|
432
438
|
"A5": (148.0, 210.0),
|
433
439
|
"A6": (105.0, 148.0),
|
@@ -435,6 +441,18 @@ class nwLabels:
|
|
435
441
|
"Letter": (215.9, 279.4),
|
436
442
|
"Custom": (-1.0, -1.0),
|
437
443
|
}
|
444
|
+
THEME_COLORS: Final[dict[str, str]] = {
|
445
|
+
"theme": QT_TRANSLATE_NOOP("Constant", "Theme Colours"),
|
446
|
+
"default": QT_TRANSLATE_NOOP("Constant", "Foreground Colour"),
|
447
|
+
"faded": QT_TRANSLATE_NOOP("Constant", "Faded Colour"),
|
448
|
+
"red": QT_TRANSLATE_NOOP("Constant", "Red"),
|
449
|
+
"orange": QT_TRANSLATE_NOOP("Constant", "Orange"),
|
450
|
+
"yellow": QT_TRANSLATE_NOOP("Constant", "Yellow"),
|
451
|
+
"green": QT_TRANSLATE_NOOP("Constant", "Green"),
|
452
|
+
"aqua": QT_TRANSLATE_NOOP("Constant", "Aqua"),
|
453
|
+
"blue": QT_TRANSLATE_NOOP("Constant", "Blue"),
|
454
|
+
"purple": QT_TRANSLATE_NOOP("Constant", "Purple"),
|
455
|
+
}
|
438
456
|
|
439
457
|
|
440
458
|
class nwHeadFmt:
|
@@ -450,7 +468,7 @@ class nwHeadFmt:
|
|
450
468
|
CHAR_POV = "{Char:POV}"
|
451
469
|
CHAR_FOCUS = "{Char:Focus}"
|
452
470
|
|
453
|
-
PAGE_HEADERS = [
|
471
|
+
PAGE_HEADERS: Final[list[str]] = [
|
454
472
|
TITLE, CH_NUM, CH_WORD, CH_ROMU, CH_ROML, SC_NUM, SC_ABS,
|
455
473
|
CHAR_POV, CHAR_FOCUS
|
456
474
|
]
|
@@ -466,7 +484,7 @@ class nwQuotes:
|
|
466
484
|
"""Allowed quotation marks.
|
467
485
|
Source: https://en.wikipedia.org/wiki/Quotation_mark
|
468
486
|
"""
|
469
|
-
SYMBOLS = {
|
487
|
+
SYMBOLS: Final[dict[str, str]] = {
|
470
488
|
"\u0027": QT_TRANSLATE_NOOP("Constant", "Straight single quotation mark"),
|
471
489
|
"\u0022": QT_TRANSLATE_NOOP("Constant", "Straight double quotation mark"),
|
472
490
|
|
@@ -491,6 +509,19 @@ class nwQuotes:
|
|
491
509
|
"\u300f": QT_TRANSLATE_NOOP("Constant", "Right white corner bracket"),
|
492
510
|
}
|
493
511
|
|
512
|
+
DASHES: Final[dict[str, str]] = {
|
513
|
+
"": QT_TRANSLATE_NOOP("Constant", "None"),
|
514
|
+
"\u2013": QT_TRANSLATE_NOOP("Constant", "Short dash"),
|
515
|
+
"\u2014": QT_TRANSLATE_NOOP("Constant", "Long dash"),
|
516
|
+
"\u2015": QT_TRANSLATE_NOOP("Constant", "Horizontal bar"),
|
517
|
+
}
|
518
|
+
|
519
|
+
ALLOWED: Final[list[str]] = [
|
520
|
+
"\u0027", "\u0022", "\u2018", "\u2019", "\u201a", "\u201b", "\u201c", "\u201d", "\u201e",
|
521
|
+
"\u201f", "\u2e42", "\u2039", "\u203a", "\u00ab", "\u00bb", "\u300c", "\u300d", "\u300e",
|
522
|
+
"\u300f", "\u2013", "\u2014", "\u2015",
|
523
|
+
]
|
524
|
+
|
494
525
|
|
495
526
|
class nwUnicode:
|
496
527
|
"""Supported unicode character constants and their HTML equivalents."""
|
@@ -631,9 +662,9 @@ class nwUnicode:
|
|
631
662
|
H_LTRIS = "◂"
|
632
663
|
|
633
664
|
|
634
|
-
class nwHtmlUnicode
|
665
|
+
class nwHtmlUnicode:
|
635
666
|
|
636
|
-
U_TO_H = {
|
667
|
+
U_TO_H: Final[dict[str, str]] = {
|
637
668
|
# Quotes
|
638
669
|
nwUnicode.U_QUOT: nwUnicode.H_QUOT,
|
639
670
|
nwUnicode.U_APOS: nwUnicode.H_APOS,
|
@@ -28,11 +28,11 @@ import json
|
|
28
28
|
import logging
|
29
29
|
import uuid
|
30
30
|
|
31
|
-
from collections.abc import Iterable
|
32
31
|
from enum import Enum
|
33
32
|
from pathlib import Path
|
33
|
+
from typing import TYPE_CHECKING
|
34
34
|
|
35
|
-
from
|
35
|
+
from PyQt6.QtCore import QT_TRANSLATE_NOOP, QCoreApplication
|
36
36
|
|
37
37
|
from novelwriter import CONFIG
|
38
38
|
from novelwriter.common import checkUuid, isHandle, jsonEncode
|
@@ -41,13 +41,18 @@ from novelwriter.core.project import NWProject
|
|
41
41
|
from novelwriter.enum import nwBuildFmt
|
42
42
|
from novelwriter.error import logException
|
43
43
|
|
44
|
+
if TYPE_CHECKING:
|
45
|
+
from collections.abc import Iterable
|
46
|
+
|
44
47
|
logger = logging.getLogger(__name__)
|
45
48
|
|
49
|
+
T_BuildValue = str | int | float | bool
|
50
|
+
|
46
51
|
# The Settings Template
|
47
52
|
# =====================
|
48
53
|
# Each entry contains a tuple on the form: (type, default)
|
49
54
|
|
50
|
-
SETTINGS_TEMPLATE: dict[str, tuple[type,
|
55
|
+
SETTINGS_TEMPLATE: dict[str, tuple[type, T_BuildValue]] = {
|
51
56
|
"filter.includeNovel": (bool, True),
|
52
57
|
"filter.includeNotes": (bool, False),
|
53
58
|
"filter.includeInactive": (bool, False),
|
@@ -73,6 +78,8 @@ SETTINGS_TEMPLATE: dict[str, tuple[type, str | int | float | bool]] = {
|
|
73
78
|
"headings.breakScene": (bool, False),
|
74
79
|
"text.includeSynopsis": (bool, False),
|
75
80
|
"text.includeComments": (bool, False),
|
81
|
+
"text.includeStory": (bool, False),
|
82
|
+
"text.includeNotes": (bool, False),
|
76
83
|
"text.includeKeywords": (bool, False),
|
77
84
|
"text.includeBodyText": (bool, True),
|
78
85
|
"text.ignoredKeywords": (str, ""),
|
@@ -139,6 +146,8 @@ SETTINGS_LABELS = {
|
|
139
146
|
"text.grpContent": QT_TRANSLATE_NOOP("Builds", "Text Content"),
|
140
147
|
"text.includeSynopsis": QT_TRANSLATE_NOOP("Builds", "Include Synopsis"),
|
141
148
|
"text.includeComments": QT_TRANSLATE_NOOP("Builds", "Include Comments"),
|
149
|
+
"text.includeStory": QT_TRANSLATE_NOOP("Builds", "Include Story Structure"),
|
150
|
+
"text.includeNotes": QT_TRANSLATE_NOOP("Builds", "Include Manuscript Notes"),
|
142
151
|
"text.includeKeywords": QT_TRANSLATE_NOOP("Builds", "Include Keywords"),
|
143
152
|
"text.includeBodyText": QT_TRANSLATE_NOOP("Builds", "Include Body Text"),
|
144
153
|
"text.ignoredKeywords": QT_TRANSLATE_NOOP("Builds", "Ignore These Keywords"),
|
@@ -185,7 +194,6 @@ SETTINGS_LABELS = {
|
|
185
194
|
}
|
186
195
|
|
187
196
|
RENAMED = {
|
188
|
-
"odt.addColours": "doc.addColours",
|
189
197
|
"odt.pageHeader": "doc.pageHeader",
|
190
198
|
"odt.pageCountOffset": "doc.pageCountOffset",
|
191
199
|
}
|
@@ -226,9 +234,9 @@ class BuildSettings:
|
|
226
234
|
@classmethod
|
227
235
|
def fromDict(cls, data: dict) -> BuildSettings:
|
228
236
|
"""Create a build settings object from a dict."""
|
229
|
-
|
230
|
-
|
231
|
-
return
|
237
|
+
new = cls()
|
238
|
+
new.unpack(data)
|
239
|
+
return new
|
232
240
|
|
233
241
|
##
|
234
242
|
# Properties
|
@@ -293,12 +301,12 @@ class BuildSettings:
|
|
293
301
|
def getInt(self, key: str) -> int:
|
294
302
|
"""Type safe value access for integers."""
|
295
303
|
value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1])
|
296
|
-
return int(value) if isinstance(value,
|
304
|
+
return int(value) if isinstance(value, int | float) else 0
|
297
305
|
|
298
306
|
def getFloat(self, key: str) -> float:
|
299
307
|
"""Type safe value access for floats."""
|
300
308
|
value = self._settings.get(key, SETTINGS_TEMPLATE.get(key, (None, None))[1])
|
301
|
-
return float(value) if isinstance(value,
|
309
|
+
return float(value) if isinstance(value, int | float) else 0.0
|
302
310
|
|
303
311
|
##
|
304
312
|
# Setters
|
@@ -379,10 +387,10 @@ class BuildSettings:
|
|
379
387
|
self._changed = True
|
380
388
|
return
|
381
389
|
|
382
|
-
def setValue(self, key: str, value:
|
390
|
+
def setValue(self, key: str, value: T_BuildValue) -> None:
|
383
391
|
"""Set a specific value for a build setting."""
|
384
392
|
if (d := SETTINGS_TEMPLATE.get(key)) and len(d) == 2 and isinstance(value, d[0]):
|
385
|
-
self._changed
|
393
|
+
self._changed |= (value != self._settings[key])
|
386
394
|
self._settings[key] = value
|
387
395
|
return
|
388
396
|
|
@@ -503,7 +511,8 @@ class BuildSettings:
|
|
503
511
|
self._settings = {k: v[1] for k, v in SETTINGS_TEMPLATE.items()}
|
504
512
|
if isinstance(settings, dict):
|
505
513
|
for key, value in settings.items():
|
506
|
-
|
514
|
+
if isinstance(key, str) and isinstance(value, T_BuildValue):
|
515
|
+
self.setValue(RENAMED.get(key, key), value)
|
507
516
|
|
508
517
|
self._changed = False
|
509
518
|
|
@@ -512,11 +521,11 @@ class BuildSettings:
|
|
512
521
|
@classmethod
|
513
522
|
def duplicate(cls, source: BuildSettings) -> BuildSettings:
|
514
523
|
"""Make a copy of another build."""
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
return
|
524
|
+
new = cls()
|
525
|
+
new.unpack(source.pack())
|
526
|
+
new._uuid = str(uuid.uuid4())
|
527
|
+
new._name = f"{source.name} 2"
|
528
|
+
return new
|
520
529
|
|
521
530
|
|
522
531
|
class BuildCollection:
|
novelwriter/core/coretools.py
CHANGED
@@ -30,20 +30,24 @@ import logging
|
|
30
30
|
import re
|
31
31
|
import shutil
|
32
32
|
|
33
|
-
from collections.abc import Iterable
|
34
33
|
from functools import partial
|
35
34
|
from pathlib import Path
|
35
|
+
from typing import TYPE_CHECKING
|
36
36
|
from zipfile import ZipFile, is_zipfile
|
37
37
|
|
38
|
-
from
|
38
|
+
from PyQt6.QtCore import QCoreApplication
|
39
39
|
|
40
40
|
from novelwriter import CONFIG, SHARED
|
41
41
|
from novelwriter.common import isHandle, minmax, simplified
|
42
42
|
from novelwriter.constants import nwConst, nwFiles, nwItemClass, nwStats
|
43
|
-
from novelwriter.core.item import NWItem
|
44
43
|
from novelwriter.core.project import NWProject
|
45
44
|
from novelwriter.core.storage import NWStorageCreate
|
46
45
|
|
46
|
+
if TYPE_CHECKING:
|
47
|
+
from collections.abc import Iterable
|
48
|
+
|
49
|
+
from novelwriter.core.item import NWItem
|
50
|
+
|
47
51
|
logger = logging.getLogger(__name__)
|
48
52
|
|
49
53
|
|
@@ -284,7 +288,7 @@ class DocDuplicator:
|
|
284
288
|
class DocSearch:
|
285
289
|
|
286
290
|
def __init__(self) -> None:
|
287
|
-
self._regEx = re.compile("")
|
291
|
+
self._regEx = re.compile(r"")
|
288
292
|
self._opts = re.UNICODE | re.IGNORECASE
|
289
293
|
self._words = False
|
290
294
|
self._escape = True
|
@@ -379,10 +383,12 @@ class ProjectBuilder:
|
|
379
383
|
"""Build or copy a project from a data dictionary."""
|
380
384
|
if isinstance(data, dict):
|
381
385
|
path = data.get("path", None) or None
|
382
|
-
if
|
386
|
+
if author := data.get("author"):
|
387
|
+
CONFIG.setLastAuthor(author)
|
388
|
+
if isinstance(path, str | Path):
|
383
389
|
self._path = Path(path).resolve()
|
384
|
-
if data.get("sample"
|
385
|
-
return self._extractSampleProject(self._path)
|
390
|
+
if data.get("sample"):
|
391
|
+
return self._extractSampleProject(self._path, data)
|
386
392
|
elif data.get("template"):
|
387
393
|
return self._copyProject(self._path, data)
|
388
394
|
else:
|
@@ -412,20 +418,21 @@ class ProjectBuilder:
|
|
412
418
|
|
413
419
|
self._path = project.storage.storagePath
|
414
420
|
|
415
|
-
|
416
|
-
|
421
|
+
trName = self.tr("New Project")
|
422
|
+
trAuthor = self.tr("Author Name")
|
423
|
+
trTitlePage = self.tr("Title Page")
|
417
424
|
|
418
425
|
# Settings
|
419
426
|
project.data.setUuid(None)
|
420
|
-
project.data.setName(data.get("name",
|
421
|
-
project.data.setAuthor(data.get("author",
|
427
|
+
project.data.setName(data.get("name", trName))
|
428
|
+
project.data.setAuthor(data.get("author", trAuthor))
|
422
429
|
project.data.setLanguage(CONFIG.guiLocale)
|
423
430
|
project.setDefaultStatusImport()
|
424
431
|
project.session.startSession()
|
425
432
|
|
426
433
|
# Add Root Folders
|
427
434
|
hNovelRoot = project.newRoot(nwItemClass.NOVEL)
|
428
|
-
hTitlePage = project.newFile(
|
435
|
+
hTitlePage = project.newFile(trTitlePage, hNovelRoot)
|
429
436
|
|
430
437
|
# Generate Title Page
|
431
438
|
aDoc = project.storage.getDocument(hTitlePage)
|
@@ -442,25 +449,21 @@ class ProjectBuilder:
|
|
442
449
|
"\n"
|
443
450
|
">> {count}: [field:{field}] <<\n"
|
444
451
|
).format(
|
445
|
-
author=project.data.author or
|
446
|
-
address=self.tr("Address"),
|
447
|
-
title=project.data.name or
|
452
|
+
author=project.data.author or trAuthor,
|
453
|
+
address=self.tr("Address Line"),
|
454
|
+
title=project.data.name or trName,
|
448
455
|
by=self.tr("By"),
|
449
456
|
count=self.tr("Word Count"),
|
450
457
|
field=nwStats.WORDS_TEXT,
|
451
458
|
))
|
452
459
|
|
453
|
-
# Create a project structure based on selected root folders
|
454
|
-
# and a number of chapters and scenes selected in the
|
455
|
-
# wizard's custom page.
|
456
|
-
|
457
460
|
# Create chapters and scenes
|
458
461
|
numChapters = data.get("chapters", 0)
|
459
462
|
numScenes = data.get("scenes", 0)
|
460
463
|
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
+
trChSynop = self.tr("Summary of the chapter.")
|
465
|
+
trScSynop = self.tr("Summary of the scene.")
|
466
|
+
trNoteDesc = self.tr("A short description.")
|
464
467
|
|
465
468
|
# Create chapters
|
466
469
|
if numChapters > 0:
|
@@ -468,7 +471,7 @@ class ProjectBuilder:
|
|
468
471
|
chTitle = self.tr("Chapter {0}").format(f"{ch+1:d}")
|
469
472
|
cHandle = project.newFile(chTitle, hNovelRoot)
|
470
473
|
aDoc = project.storage.getDocument(cHandle)
|
471
|
-
aDoc.writeDocument(f"## {chTitle}\n\n%Synopsis: {
|
474
|
+
aDoc.writeDocument(f"## {chTitle}\n\n%Synopsis: {trChSynop}\n\n")
|
472
475
|
|
473
476
|
# Create chapter scenes
|
474
477
|
if numScenes > 0 and cHandle:
|
@@ -476,7 +479,7 @@ class ProjectBuilder:
|
|
476
479
|
scTitle = self.tr("Scene {0}").format(f"{ch+1:d}.{sc+1:d}")
|
477
480
|
sHandle = project.newFile(scTitle, cHandle)
|
478
481
|
aDoc = project.storage.getDocument(sHandle)
|
479
|
-
aDoc.writeDocument(f"### {scTitle}\n\n%Synopsis: {
|
482
|
+
aDoc.writeDocument(f"### {scTitle}\n\n%Synopsis: {trScSynop}\n\n")
|
480
483
|
|
481
484
|
# Create scenes (no chapters)
|
482
485
|
elif numScenes > 0:
|
@@ -484,7 +487,7 @@ class ProjectBuilder:
|
|
484
487
|
scTitle = self.tr("Scene {0}").format(f"{sc+1:d}")
|
485
488
|
sHandle = project.newFile(scTitle, hNovelRoot)
|
486
489
|
aDoc = project.storage.getDocument(sHandle)
|
487
|
-
aDoc.writeDocument(f"### {scTitle}\n\n%Synopsis: {
|
490
|
+
aDoc.writeDocument(f"### {scTitle}\n\n%Synopsis: {trScSynop}\n\n")
|
488
491
|
|
489
492
|
# Create notes folders
|
490
493
|
noteTitles = {
|
@@ -504,12 +507,12 @@ class ProjectBuilder:
|
|
504
507
|
aDoc.writeDocument(
|
505
508
|
f"# {noteTitles[newRoot]}\n\n"
|
506
509
|
f"@tag: {ntTag}\n\n"
|
507
|
-
f"%Short: {
|
510
|
+
f"%Short: {trNoteDesc}\n\n"
|
508
511
|
)
|
509
512
|
|
510
513
|
# Also add the archive and trash folders
|
511
514
|
project.newRoot(nwItemClass.ARCHIVE)
|
512
|
-
project.tree.trash # Triggers the creation of Trash
|
515
|
+
_ = project.tree.trash # Triggers the creation of Trash
|
513
516
|
|
514
517
|
project.saveProject()
|
515
518
|
project.closeProject()
|
@@ -559,23 +562,11 @@ class ProjectBuilder:
|
|
559
562
|
return False
|
560
563
|
|
561
564
|
# Open the copied project and update settings
|
562
|
-
|
563
|
-
project.openProject(dstPath)
|
564
|
-
project.data.setUuid("") # Creates a fresh uuid
|
565
|
-
project.data.setName(data.get("name", "None"))
|
566
|
-
project.data.setAuthor(data.get("author", ""))
|
567
|
-
project.data.setSpellCheck(True)
|
568
|
-
project.data.setSpellLang(None)
|
569
|
-
project.data.setDoBackup(True)
|
570
|
-
project.data.setSaveCount(0)
|
571
|
-
project.data.setAutoCount(0)
|
572
|
-
project.data.setEditTime(0)
|
573
|
-
project.saveProject()
|
574
|
-
project.closeProject()
|
565
|
+
self._resetProject(dstPath, data)
|
575
566
|
|
576
567
|
return True
|
577
568
|
|
578
|
-
def _extractSampleProject(self, path: Path) -> bool:
|
569
|
+
def _extractSampleProject(self, path: Path, data: dict) -> bool:
|
579
570
|
"""Make a copy of the sample project by extracting the
|
580
571
|
sample.zip file to the new path.
|
581
572
|
"""
|
@@ -589,6 +580,7 @@ class ProjectBuilder:
|
|
589
580
|
if (sample := CONFIG.assetPath("sample.zip")).is_file():
|
590
581
|
try:
|
591
582
|
shutil.unpack_archive(sample, path)
|
583
|
+
self._resetProject(path, data)
|
592
584
|
except Exception as exc:
|
593
585
|
SHARED.error(self.tr("Failed to create a new example project."), exc=exc)
|
594
586
|
return False
|
@@ -601,3 +593,22 @@ class ProjectBuilder:
|
|
601
593
|
return False
|
602
594
|
|
603
595
|
return True
|
596
|
+
|
597
|
+
def _resetProject(self, path: Path, data: dict) -> None:
|
598
|
+
"""Open a project and reset/update its settings."""
|
599
|
+
project = NWProject()
|
600
|
+
project.openProject(path)
|
601
|
+
project.data.setUuid("") # Creates a fresh uuid
|
602
|
+
if name := data.get("name", ""):
|
603
|
+
project.data.setName(name)
|
604
|
+
if author := data.get("author", ""):
|
605
|
+
project.data.setAuthor(author)
|
606
|
+
project.data.setSpellCheck(True)
|
607
|
+
project.data.setSpellLang(None)
|
608
|
+
project.data.setDoBackup(True)
|
609
|
+
project.data.setSaveCount(0)
|
610
|
+
project.data.setAutoCount(0)
|
611
|
+
project.data.setEditTime(0)
|
612
|
+
project.saveProject()
|
613
|
+
project.closeProject()
|
614
|
+
return
|