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
@@ -0,0 +1,406 @@
|
|
1
|
+
"""
|
2
|
+
novelWriter – Project Index Data
|
3
|
+
================================
|
4
|
+
|
5
|
+
File History:
|
6
|
+
Created: 2022-05-28 [2.0rc1] IndexNode
|
7
|
+
Created: 2022-05-28 [2.0rc1] IndexHeading
|
8
|
+
Moved: 2025-02-22 [2.7b1] IndexNode
|
9
|
+
Moved: 2025-02-22 [2.7b1] IndexHeading
|
10
|
+
|
11
|
+
This file is a part of novelWriter
|
12
|
+
Copyright (C) 2025 Veronica Berglyd Olsen and novelWriter contributors
|
13
|
+
|
14
|
+
This program is free software: you can redistribute it and/or modify
|
15
|
+
it under the terms of the GNU General Public License as published by
|
16
|
+
the Free Software Foundation, either version 3 of the License, or
|
17
|
+
(at your option) any later version.
|
18
|
+
|
19
|
+
This program is distributed in the hope that it will be useful, but
|
20
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
21
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
22
|
+
General Public License for more details.
|
23
|
+
|
24
|
+
You should have received a copy of the GNU General Public License
|
25
|
+
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
26
|
+
"""
|
27
|
+
from __future__ import annotations
|
28
|
+
|
29
|
+
import logging
|
30
|
+
|
31
|
+
from typing import TYPE_CHECKING, Literal
|
32
|
+
|
33
|
+
from novelwriter import CONFIG
|
34
|
+
from novelwriter.common import checkInt, compact, isListInstance, isTitleTag
|
35
|
+
from novelwriter.constants import nwKeyWords, nwStyles
|
36
|
+
|
37
|
+
if TYPE_CHECKING:
|
38
|
+
from collections.abc import ItemsView, Sequence
|
39
|
+
|
40
|
+
from novelwriter.core.index import IndexCache
|
41
|
+
from novelwriter.core.item import NWItem
|
42
|
+
from novelwriter.enum import nwComment
|
43
|
+
|
44
|
+
logger = logging.getLogger(__name__)
|
45
|
+
|
46
|
+
T_NoteTypes = Literal["footnotes", "comments"]
|
47
|
+
|
48
|
+
TT_NONE = "T0000" # Default title key
|
49
|
+
NOTE_TYPES: list[T_NoteTypes] = ["footnotes", "comments"]
|
50
|
+
|
51
|
+
|
52
|
+
class IndexNode:
|
53
|
+
"""Core: Single Index Item Node Class
|
54
|
+
|
55
|
+
This object represents the index data of a project item (NWItem).
|
56
|
+
It holds a record of all the headings in the text, and the meta data
|
57
|
+
associated with each heading. It also holds a pointer to the project
|
58
|
+
item. The main heading level of the item is also held here since it
|
59
|
+
must be reset each time the item is re-indexed.
|
60
|
+
"""
|
61
|
+
|
62
|
+
__slots__ = ("_cache", "_count", "_handle", "_headings", "_item", "_notes")
|
63
|
+
|
64
|
+
def __init__(self, cache: IndexCache, tHandle: str, nwItem: NWItem) -> None:
|
65
|
+
self._cache = cache
|
66
|
+
self._handle = tHandle
|
67
|
+
self._item = nwItem
|
68
|
+
self._headings: dict[str, IndexHeading] = {TT_NONE: IndexHeading(self._cache, TT_NONE)}
|
69
|
+
self._notes: dict[str, set[str]] = {}
|
70
|
+
self._count = 0
|
71
|
+
return
|
72
|
+
|
73
|
+
def __repr__(self) -> str:
|
74
|
+
return f"<IndexNode handle='{self._handle}'>"
|
75
|
+
|
76
|
+
def __len__(self) -> int:
|
77
|
+
return len(self._headings)
|
78
|
+
|
79
|
+
def __getitem__(self, sTitle: str) -> IndexHeading | None:
|
80
|
+
return self._headings.get(sTitle, None)
|
81
|
+
|
82
|
+
def __contains__(self, sTitle: str) -> bool:
|
83
|
+
return sTitle in self._headings
|
84
|
+
|
85
|
+
##
|
86
|
+
# Properties
|
87
|
+
##
|
88
|
+
|
89
|
+
@property
|
90
|
+
def handle(self) -> str:
|
91
|
+
"""Return the item handle of the index item."""
|
92
|
+
return self._handle
|
93
|
+
|
94
|
+
@property
|
95
|
+
def item(self) -> NWItem:
|
96
|
+
"""Return the project item of the index item."""
|
97
|
+
return self._item
|
98
|
+
|
99
|
+
##
|
100
|
+
# Setters
|
101
|
+
##
|
102
|
+
|
103
|
+
def addHeading(self, tHeading: IndexHeading) -> None:
|
104
|
+
"""Add a heading to the item. Also remove the placeholder entry
|
105
|
+
if it exists.
|
106
|
+
"""
|
107
|
+
if TT_NONE in self._headings:
|
108
|
+
self._headings.pop(TT_NONE)
|
109
|
+
self._headings[tHeading.key] = tHeading
|
110
|
+
return
|
111
|
+
|
112
|
+
def setHeadingCounts(self, sTitle: str, cCount: int, wCount: int, pCount: int) -> None:
|
113
|
+
"""Set the character, word and paragraph count of a heading."""
|
114
|
+
if sTitle in self._headings:
|
115
|
+
self._headings[sTitle].setCounts([cCount, wCount, pCount])
|
116
|
+
return
|
117
|
+
|
118
|
+
def setHeadingComment(self, sTitle: str, comment: nwComment, key: str, text: str) -> None:
|
119
|
+
"""Set the comment text of a heading."""
|
120
|
+
if sTitle in self._headings:
|
121
|
+
self._headings[sTitle].setComment(comment.name, key, text)
|
122
|
+
return
|
123
|
+
|
124
|
+
def setHeadingTag(self, sTitle: str, tag: str) -> None:
|
125
|
+
"""Set the tag of a heading."""
|
126
|
+
if sTitle in self._headings:
|
127
|
+
self._headings[sTitle].setTag(tag)
|
128
|
+
return
|
129
|
+
|
130
|
+
def addHeadingRef(self, sTitle: str, tags: list[str], keyword: str) -> None:
|
131
|
+
"""Add a reference key and all its types to a heading."""
|
132
|
+
if sTitle in self._headings:
|
133
|
+
for tag in tags:
|
134
|
+
self._headings[sTitle].addReference(tag, keyword)
|
135
|
+
return
|
136
|
+
|
137
|
+
def addNoteKey(self, style: T_NoteTypes, key: str) -> None:
|
138
|
+
"""Add a note key to the index."""
|
139
|
+
if style not in self._notes:
|
140
|
+
self._notes[style] = set()
|
141
|
+
self._notes[style].add(key)
|
142
|
+
return
|
143
|
+
|
144
|
+
##
|
145
|
+
# Data Methods
|
146
|
+
##
|
147
|
+
|
148
|
+
def items(self) -> ItemsView[str, IndexHeading]:
|
149
|
+
"""Return IndexHeading items."""
|
150
|
+
return self._headings.items()
|
151
|
+
|
152
|
+
def headings(self) -> list[str]:
|
153
|
+
"""Return heading keys in sorted order."""
|
154
|
+
return sorted(self._headings.keys())
|
155
|
+
|
156
|
+
def allTags(self) -> list[str]:
|
157
|
+
"""Return a list of all tags in the current item."""
|
158
|
+
return [h.tag for h in self._headings.values() if h.tag]
|
159
|
+
|
160
|
+
def nextHeading(self) -> str:
|
161
|
+
"""Return the next heading key to be used."""
|
162
|
+
self._count += 1
|
163
|
+
return f"T{self._count:04d}"
|
164
|
+
|
165
|
+
def noteKeys(self, style: T_NoteTypes) -> set[str]:
|
166
|
+
"""Return a set of all note keys."""
|
167
|
+
return self._notes.get(style, set())
|
168
|
+
|
169
|
+
##
|
170
|
+
# Pack/Unpack
|
171
|
+
##
|
172
|
+
|
173
|
+
def packData(self) -> dict:
|
174
|
+
"""Pack the indexed item's data into a dictionary."""
|
175
|
+
data = {}
|
176
|
+
for sTitle, hItem in self._headings.items():
|
177
|
+
data[sTitle] = hItem.packData()
|
178
|
+
if self._notes:
|
179
|
+
data["document"] = {style: list(keys) for style, keys in self._notes.items()}
|
180
|
+
return data
|
181
|
+
|
182
|
+
def unpackData(self, data: dict) -> None:
|
183
|
+
"""Unpack an item entry from the data."""
|
184
|
+
for key, entry in data.items():
|
185
|
+
if isTitleTag(key):
|
186
|
+
heading = IndexHeading(self._cache, key)
|
187
|
+
heading.unpackData(entry)
|
188
|
+
self.addHeading(heading)
|
189
|
+
elif key == "document":
|
190
|
+
for style, keys in entry.items():
|
191
|
+
if style not in NOTE_TYPES:
|
192
|
+
raise ValueError("The notes style is invalid")
|
193
|
+
if not isListInstance(keys, str):
|
194
|
+
raise ValueError("The notes keys must be a list of strings")
|
195
|
+
self._notes[style] = set(keys)
|
196
|
+
else:
|
197
|
+
raise KeyError("Index node contains an invalid key")
|
198
|
+
return
|
199
|
+
|
200
|
+
|
201
|
+
class IndexHeading:
|
202
|
+
"""Core: Single Index Heading Class
|
203
|
+
|
204
|
+
This object represents a section of text in a project item
|
205
|
+
associated with a single (valid) heading. It holds a separate record
|
206
|
+
of all references made under the heading.
|
207
|
+
"""
|
208
|
+
|
209
|
+
__slots__ = (
|
210
|
+
"_cache", "_comments", "_counts", "_key", "_level", "_line", "_refs",
|
211
|
+
"_tag", "_title",
|
212
|
+
)
|
213
|
+
|
214
|
+
def __init__(
|
215
|
+
self, cache: IndexCache, key: str, line: int = 0,
|
216
|
+
level: str = "H0", title: str = "",
|
217
|
+
) -> None:
|
218
|
+
self._cache = cache
|
219
|
+
self._key = key
|
220
|
+
self._line = line
|
221
|
+
self._level = level
|
222
|
+
self._title = title
|
223
|
+
self._counts: tuple[int, int, int] = (0, 0, 0)
|
224
|
+
self._tag = ""
|
225
|
+
self._refs: dict[str, set[str]] = {}
|
226
|
+
self._comments: dict[str, str] = {}
|
227
|
+
return
|
228
|
+
|
229
|
+
def __repr__(self) -> str:
|
230
|
+
return f"<IndexHeading key='{self._key}'>"
|
231
|
+
|
232
|
+
##
|
233
|
+
# Properties
|
234
|
+
##
|
235
|
+
|
236
|
+
@property
|
237
|
+
def key(self) -> str:
|
238
|
+
return self._key
|
239
|
+
|
240
|
+
@property
|
241
|
+
def line(self) -> int:
|
242
|
+
return self._line
|
243
|
+
|
244
|
+
@property
|
245
|
+
def level(self) -> str:
|
246
|
+
return self._level
|
247
|
+
|
248
|
+
@property
|
249
|
+
def title(self) -> str:
|
250
|
+
return self._title
|
251
|
+
|
252
|
+
@property
|
253
|
+
def mainCount(self) -> int:
|
254
|
+
return self._counts[0 if CONFIG.useCharCount else 1]
|
255
|
+
|
256
|
+
@property
|
257
|
+
def charCount(self) -> int:
|
258
|
+
return self._counts[0]
|
259
|
+
|
260
|
+
@property
|
261
|
+
def wordCount(self) -> int:
|
262
|
+
return self._counts[1]
|
263
|
+
|
264
|
+
@property
|
265
|
+
def paraCount(self) -> int:
|
266
|
+
return self._counts[2]
|
267
|
+
|
268
|
+
@property
|
269
|
+
def synopsis(self) -> str:
|
270
|
+
return self._comments.get("summary", "")
|
271
|
+
|
272
|
+
@property
|
273
|
+
def comments(self) -> dict[str, str]:
|
274
|
+
return self._comments
|
275
|
+
|
276
|
+
@property
|
277
|
+
def tag(self) -> str:
|
278
|
+
return self._tag
|
279
|
+
|
280
|
+
@property
|
281
|
+
def references(self) -> dict[str, set[str]]:
|
282
|
+
return self._refs
|
283
|
+
|
284
|
+
##
|
285
|
+
# Setters
|
286
|
+
##
|
287
|
+
|
288
|
+
def setLevel(self, level: str) -> None:
|
289
|
+
"""Set the level of the heading if it's a valid value."""
|
290
|
+
if level in nwStyles.H_VALID:
|
291
|
+
self._level = level
|
292
|
+
return
|
293
|
+
|
294
|
+
def setLine(self, line: int) -> None:
|
295
|
+
"""Set the line number of a heading."""
|
296
|
+
self._line = max(0, checkInt(line, 0))
|
297
|
+
return
|
298
|
+
|
299
|
+
def setCounts(self, counts: Sequence[int]) -> None:
|
300
|
+
"""Set the character, word and paragraph count. Make sure the
|
301
|
+
value is an integer and is not smaller than 0.
|
302
|
+
"""
|
303
|
+
if len(counts) == 3:
|
304
|
+
self._counts = (
|
305
|
+
max(0, checkInt(counts[0], 0)),
|
306
|
+
max(0, checkInt(counts[1], 0)),
|
307
|
+
max(0, checkInt(counts[2], 0)),
|
308
|
+
)
|
309
|
+
return
|
310
|
+
|
311
|
+
def setComment(self, comment: str, key: str, text: str) -> None:
|
312
|
+
"""Set the text for a comment and make sure it is a string."""
|
313
|
+
match comment.lower():
|
314
|
+
case "short" | "synopsis" | "summary":
|
315
|
+
self._comments["summary"] = str(text)
|
316
|
+
case "story" if key:
|
317
|
+
self._cache.story.add(key)
|
318
|
+
self._comments[f"story.{key}"] = str(text)
|
319
|
+
case "note" if key:
|
320
|
+
self._cache.note.add(key)
|
321
|
+
self._comments[f"note.{key}"] = str(text)
|
322
|
+
return
|
323
|
+
|
324
|
+
def setTag(self, tag: str) -> None:
|
325
|
+
"""Set the tag for references, and make sure it is a string."""
|
326
|
+
self._tag = str(tag).lower()
|
327
|
+
return
|
328
|
+
|
329
|
+
def addReference(self, tag: str, keyword: str) -> None:
|
330
|
+
"""Add a record of a reference tag, and what keyword types it is
|
331
|
+
associated with.
|
332
|
+
"""
|
333
|
+
if keyword in nwKeyWords.VALID_KEYS:
|
334
|
+
tag = tag.lower()
|
335
|
+
if tag not in self._refs:
|
336
|
+
self._refs[tag] = set()
|
337
|
+
self._refs[tag].add(keyword)
|
338
|
+
return
|
339
|
+
|
340
|
+
##
|
341
|
+
# Getters
|
342
|
+
##
|
343
|
+
|
344
|
+
def getReferences(self) -> dict[str, list[str]]:
|
345
|
+
"""Extract all references for this heading."""
|
346
|
+
refs = {x: [] for x in nwKeyWords.VALID_KEYS}
|
347
|
+
for tag, types in self._refs.items():
|
348
|
+
for keyword in types:
|
349
|
+
if keyword in refs and (name := self._cache.tags.tagName(tag)):
|
350
|
+
refs[keyword].append(name)
|
351
|
+
return refs
|
352
|
+
|
353
|
+
def getReferencesByKeyword(self, keyword: str) -> list[str]:
|
354
|
+
"""Extract all references for this heading."""
|
355
|
+
refs = []
|
356
|
+
for tag, types in self._refs.items():
|
357
|
+
if keyword in types and (name := self._cache.tags.tagName(tag)):
|
358
|
+
refs.append(name)
|
359
|
+
return refs
|
360
|
+
|
361
|
+
##
|
362
|
+
# Data Methods
|
363
|
+
##
|
364
|
+
|
365
|
+
def packData(self) -> dict:
|
366
|
+
"""Pack the values into a dictionary for saving to cache."""
|
367
|
+
data = {}
|
368
|
+
data["meta"] = {
|
369
|
+
"level": self._level,
|
370
|
+
"title": self._title,
|
371
|
+
"line": self._line,
|
372
|
+
"tag": self._tag,
|
373
|
+
"counts": self._counts,
|
374
|
+
}
|
375
|
+
if self._refs:
|
376
|
+
data["refs"] = {k: ",".join(sorted(list(v))) for k, v in self._refs.items()}
|
377
|
+
if self._comments:
|
378
|
+
data.update(self._comments)
|
379
|
+
return data
|
380
|
+
|
381
|
+
def unpackData(self, data: dict) -> None:
|
382
|
+
"""Unpack a heading entry from a dictionary."""
|
383
|
+
for key, entry in data.items():
|
384
|
+
if key == "meta":
|
385
|
+
self.setLevel(entry.get("level", "H0"))
|
386
|
+
self._title = str(entry.get("title", ""))
|
387
|
+
self._tag = str(entry.get("tag", ""))
|
388
|
+
self.setLine(entry.get("line", 0))
|
389
|
+
self.setCounts(entry.get("counts", [0, 0, 0]))
|
390
|
+
elif key == "refs":
|
391
|
+
for tag, value in entry.items():
|
392
|
+
if not isinstance(tag, str):
|
393
|
+
raise ValueError("Heading reference key must be a string")
|
394
|
+
if not isinstance(value, str):
|
395
|
+
raise ValueError("Heading reference value must be a string")
|
396
|
+
for keyword in value.split(","):
|
397
|
+
if keyword in nwKeyWords.VALID_KEYS:
|
398
|
+
self.addReference(tag, keyword)
|
399
|
+
else:
|
400
|
+
raise ValueError("Heading reference contains an invalid keyword")
|
401
|
+
elif key == "summary" or key.startswith(("story", "note")):
|
402
|
+
comment, _, kind = str(key).partition(".")
|
403
|
+
self.setComment(comment, compact(kind), str(entry))
|
404
|
+
else:
|
405
|
+
raise KeyError("Unknown key in heading entry")
|
406
|
+
return
|
novelwriter/core/item.py
CHANGED
@@ -27,8 +27,6 @@ import logging
|
|
27
27
|
|
28
28
|
from typing import TYPE_CHECKING, Any
|
29
29
|
|
30
|
-
from PyQt5.QtGui import QFont, QIcon
|
31
|
-
|
32
30
|
from novelwriter import CONFIG, SHARED
|
33
31
|
from novelwriter.common import (
|
34
32
|
checkInt, isHandle, isItemClass, isItemLayout, isItemType, simplified,
|
@@ -37,7 +35,9 @@ from novelwriter.common import (
|
|
37
35
|
from novelwriter.constants import nwLabels, nwStyles, trConst
|
38
36
|
from novelwriter.enum import nwItemClass, nwItemLayout, nwItemType
|
39
37
|
|
40
|
-
if TYPE_CHECKING:
|
38
|
+
if TYPE_CHECKING:
|
39
|
+
from PyQt6.QtGui import QFont, QIcon
|
40
|
+
|
41
41
|
from novelwriter.core.project import NWProject
|
42
42
|
|
43
43
|
logger = logging.getLogger(__name__)
|
@@ -53,10 +53,10 @@ class NWItem:
|
|
53
53
|
"""
|
54
54
|
|
55
55
|
__slots__ = (
|
56
|
-
"
|
57
|
-
"
|
58
|
-
"
|
59
|
-
"
|
56
|
+
"_active", "_charCount", "_charInit", "_class", "_cursorPos",
|
57
|
+
"_expanded", "_handle", "_heading", "_import", "_layout", "_name",
|
58
|
+
"_order", "_paraCount", "_parent", "_project", "_root", "_status",
|
59
|
+
"_type", "_wordCount", "_wordInit",
|
60
60
|
)
|
61
61
|
|
62
62
|
def __init__(self, project: NWProject, handle: str) -> None:
|
@@ -81,7 +81,8 @@ class NWItem:
|
|
81
81
|
self._wordCount = 0 # Current word count
|
82
82
|
self._paraCount = 0 # Current paragraph count
|
83
83
|
self._cursorPos = 0 # Last cursor position
|
84
|
-
self.
|
84
|
+
self._wordInit = 0 # Initial character count
|
85
|
+
self._charInit = 0 # Initial word count
|
85
86
|
|
86
87
|
return
|
87
88
|
|
@@ -164,9 +165,13 @@ class NWItem:
|
|
164
165
|
def paraCount(self) -> int:
|
165
166
|
return self._paraCount
|
166
167
|
|
168
|
+
@property
|
169
|
+
def mainCount(self) -> int:
|
170
|
+
return self._charCount if CONFIG.useCharCount else self._wordCount
|
171
|
+
|
167
172
|
@property
|
168
173
|
def initCount(self) -> int:
|
169
|
-
return self.
|
174
|
+
return self._wordInit if CONFIG.useCharCount else self._charInit
|
170
175
|
|
171
176
|
@property
|
172
177
|
def cursorPos(self) -> int:
|
@@ -257,32 +262,34 @@ class NWItem:
|
|
257
262
|
self._paraCount = 0
|
258
263
|
self._cursorPos = 0
|
259
264
|
|
260
|
-
self.
|
265
|
+
self._wordInit = self._charCount
|
266
|
+
self._charInit = self._wordCount
|
261
267
|
|
262
268
|
return True
|
263
269
|
|
264
270
|
@classmethod
|
265
271
|
def duplicate(cls, source: NWItem, handle: str) -> NWItem:
|
266
272
|
"""Make a copy of an item."""
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
273
|
+
new = cls(source._project, handle)
|
274
|
+
new._name = source._name
|
275
|
+
new._parent = source._parent
|
276
|
+
new._root = source._root
|
277
|
+
new._order = source._order
|
278
|
+
new._type = source._type
|
279
|
+
new._class = source._class
|
280
|
+
new._layout = source._layout
|
281
|
+
new._status = source._status
|
282
|
+
new._import = source._import
|
283
|
+
new._active = source._active
|
284
|
+
new._expanded = source._expanded
|
285
|
+
new._heading = source._heading
|
286
|
+
new._charCount = source._charCount
|
287
|
+
new._wordCount = source._wordCount
|
288
|
+
new._paraCount = source._paraCount
|
289
|
+
new._cursorPos = source._cursorPos
|
290
|
+
new._wordInit = source._wordInit
|
291
|
+
new._charInit = source._charInit
|
292
|
+
return new
|
286
293
|
|
287
294
|
##
|
288
295
|
# Action Methods
|
@@ -293,6 +300,12 @@ class NWItem:
|
|
293
300
|
self._project.tree.refreshItems([self._handle])
|
294
301
|
return
|
295
302
|
|
303
|
+
def notifyNovelStructureChange(self) -> None:
|
304
|
+
"""Notify that the structure of a novel has changed."""
|
305
|
+
if self._root and self._class == nwItemClass.NOVEL:
|
306
|
+
self._project.tree.novelStructureChanged(self._root)
|
307
|
+
return
|
308
|
+
|
296
309
|
##
|
297
310
|
# Lookup Methods
|
298
311
|
##
|
@@ -350,11 +363,12 @@ class NWItem:
|
|
350
363
|
"""
|
351
364
|
if self.isFileType():
|
352
365
|
key = "checked" if self._active else "unchecked"
|
366
|
+
color = "green" if self._active else "red"
|
353
367
|
text = trConst(nwLabels.ACTIVE_NAME[key])
|
354
|
-
icon = SHARED.theme.getIcon(key)
|
368
|
+
icon = SHARED.theme.getIcon(key, color)
|
355
369
|
else:
|
356
370
|
text = ""
|
357
|
-
icon = SHARED.theme.getIcon("noncheckable")
|
371
|
+
icon = SHARED.theme.getIcon("noncheckable", "faded")
|
358
372
|
return text, icon
|
359
373
|
|
360
374
|
##
|
@@ -421,7 +435,11 @@ class NWItem:
|
|
421
435
|
"""
|
422
436
|
if self._parent is not None:
|
423
437
|
# Only update for child items
|
424
|
-
self.
|
438
|
+
if itemClass != self._class:
|
439
|
+
self.setClass(itemClass)
|
440
|
+
if self._type == nwItemType.FILE:
|
441
|
+
# Notify the index of the class change
|
442
|
+
self._project.index.setItemClass(self._handle, itemClass)
|
425
443
|
|
426
444
|
if self._layout == nwItemLayout.NO_LAYOUT:
|
427
445
|
# If no layout is set, pick one
|