novelWriter 2.6.2__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 +92 -56
- 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 +15 -18
- novelwriter/gui/mainmenu.py +147 -146
- novelwriter/gui/noveltree.py +246 -406
- novelwriter/gui/outline.py +145 -76
- 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 +114 -127
- 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.2.dist-info → novelwriter-2.7.dist-info}/METADATA +6 -6
- novelwriter-2.7.dist-info/RECORD +162 -0
- {novelWriter-2.6.2.dist-info → novelwriter-2.7.dist-info}/WHEEL +1 -1
- novelWriter-2.6.2.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.2.dist-info → novelwriter-2.7.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.6.2.dist-info → novelwriter-2.7.dist-info/licenses}/LICENSE.md +0 -0
- {novelWriter-2.6.2.dist-info → novelwriter-2.7.dist-info}/top_level.txt +0 -0
novelwriter/gui/projtree.py
CHANGED
@@ -32,15 +32,15 @@ import logging
|
|
32
32
|
|
33
33
|
from enum import Enum
|
34
34
|
|
35
|
-
from
|
36
|
-
from
|
37
|
-
from
|
38
|
-
QAbstractItemView,
|
35
|
+
from PyQt6.QtCore import QModelIndex, QPoint, Qt, pyqtSignal, pyqtSlot
|
36
|
+
from PyQt6.QtGui import QAction, QIcon, QMouseEvent, QPainter, QPalette, QShortcut
|
37
|
+
from PyQt6.QtWidgets import (
|
38
|
+
QAbstractItemView, QFrame, QHBoxLayout, QLabel, QMenu,
|
39
39
|
QStyleOptionViewItem, QTreeView, QVBoxLayout, QWidget
|
40
40
|
)
|
41
41
|
|
42
42
|
from novelwriter import CONFIG, SHARED
|
43
|
-
from novelwriter.common import qtLambda
|
43
|
+
from novelwriter.common import qtAddAction, qtAddMenu, qtLambda
|
44
44
|
from novelwriter.constants import nwLabels, nwStyles, nwUnicode, trConst
|
45
45
|
from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter
|
46
46
|
from novelwriter.core.item import NWItem
|
@@ -244,9 +244,9 @@ class GuiProjectToolBar(QWidget):
|
|
244
244
|
self.projTree = projView.projTree
|
245
245
|
|
246
246
|
iSz = SHARED.theme.baseIconSize
|
247
|
-
mPx = CONFIG.pxInt(2)
|
248
247
|
|
249
248
|
self.setContentsMargins(0, 0, 0, 0)
|
249
|
+
self.setBackgroundRole(QPalette.ColorRole.Base)
|
250
250
|
self.setAutoFillBackground(True)
|
251
251
|
|
252
252
|
# Widget Label
|
@@ -254,48 +254,54 @@ class GuiProjectToolBar(QWidget):
|
|
254
254
|
self.viewLabel.setFont(SHARED.theme.guiFontB)
|
255
255
|
self.viewLabel.setContentsMargins(0, 0, 0, 0)
|
256
256
|
self.viewLabel.setSizePolicy(QtSizeExpanding, QtSizeExpanding)
|
257
|
+
self.projTree.setAccessibleName(self.viewLabel.text())
|
257
258
|
|
258
259
|
# Quick Links
|
259
260
|
self.mQuick = QMenu(self)
|
260
261
|
|
261
262
|
self.tbQuick = NIconToolButton(self, iSz)
|
262
|
-
self.tbQuick.setToolTip("
|
263
|
+
self.tbQuick.setToolTip("{0} [Ctrl+L]".format(self.tr("Quick Links")))
|
263
264
|
self.tbQuick.setShortcut("Ctrl+L")
|
264
265
|
self.tbQuick.setMenu(self.mQuick)
|
265
266
|
|
266
267
|
# Move Buttons
|
267
268
|
self.tbMoveU = NIconToolButton(self, iSz)
|
268
|
-
self.tbMoveU.setToolTip("
|
269
|
+
self.tbMoveU.setToolTip("{0} [Ctrl+Up]".format(self.tr("Move Up")))
|
269
270
|
self.tbMoveU.clicked.connect(self.projTree.moveItemUp)
|
270
271
|
|
271
272
|
self.tbMoveD = NIconToolButton(self, iSz)
|
272
|
-
self.tbMoveD.setToolTip("
|
273
|
+
self.tbMoveD.setToolTip("{0} [Ctrl+Down]".format(self.tr("Move Down")))
|
273
274
|
self.tbMoveD.clicked.connect(self.projTree.moveItemDown)
|
274
275
|
|
275
276
|
# Add Item Menu
|
276
277
|
self.mAdd = QMenu(self)
|
277
278
|
|
278
|
-
self.
|
279
|
-
self.
|
280
|
-
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=
|
279
|
+
self.aAddScene = qtAddAction(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["doc_h3"]))
|
280
|
+
self.aAddScene.triggered.connect(
|
281
|
+
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=3, isNote=False)
|
281
282
|
)
|
282
283
|
|
283
|
-
self.aAddChap = self.mAdd
|
284
|
+
self.aAddChap = qtAddAction(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["doc_h2"]))
|
284
285
|
self.aAddChap.triggered.connect(
|
285
286
|
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=2, isNote=False)
|
286
287
|
)
|
287
288
|
|
288
|
-
self.
|
289
|
-
self.
|
290
|
-
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=
|
289
|
+
self.aAddPart = qtAddAction(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["doc_h1"]))
|
290
|
+
self.aAddPart.triggered.connect(
|
291
|
+
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=1, isNote=False)
|
292
|
+
)
|
293
|
+
|
294
|
+
self.aAddEmpty = qtAddAction(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["document"]))
|
295
|
+
self.aAddEmpty.triggered.connect(
|
296
|
+
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=0, isNote=False)
|
291
297
|
)
|
292
298
|
|
293
|
-
self.aAddNote = self.mAdd
|
299
|
+
self.aAddNote = qtAddAction(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["note"]))
|
294
300
|
self.aAddNote.triggered.connect(
|
295
301
|
qtLambda(self.projTree.newTreeItem, nwItemType.FILE, hLevel=1, isNote=True)
|
296
302
|
)
|
297
303
|
|
298
|
-
self.aAddFolder = self.mAdd
|
304
|
+
self.aAddFolder = qtAddAction(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["folder"]))
|
299
305
|
self.aAddFolder.triggered.connect(
|
300
306
|
qtLambda(self.projTree.newTreeItem, nwItemType.FOLDER)
|
301
307
|
)
|
@@ -305,24 +311,24 @@ class GuiProjectToolBar(QWidget):
|
|
305
311
|
self.mTemplates.menuItemTriggered.connect(lambda h: self.newDocumentFromTemplate.emit(h))
|
306
312
|
self.mAdd.addMenu(self.mTemplates)
|
307
313
|
|
308
|
-
self.mAddRoot = self.mAdd
|
314
|
+
self.mAddRoot = qtAddMenu(self.mAdd, trConst(nwLabels.ITEM_DESCRIPTION["root"]))
|
309
315
|
self._buildRootMenu()
|
310
316
|
|
311
317
|
self.tbAdd = NIconToolButton(self, iSz)
|
312
|
-
self.tbAdd.setToolTip("
|
318
|
+
self.tbAdd.setToolTip("{0} [Ctrl+N]".format(self.tr("Add Item")))
|
313
319
|
self.tbAdd.setShortcut("Ctrl+N")
|
314
320
|
self.tbAdd.setMenu(self.mAdd)
|
315
321
|
|
316
322
|
# More Options Menu
|
317
323
|
self.mMore = QMenu(self)
|
318
324
|
|
319
|
-
self.aExpand = self.mMore
|
325
|
+
self.aExpand = qtAddAction(self.mMore, self.tr("Expand All"))
|
320
326
|
self.aExpand.triggered.connect(self.projTree.expandAll)
|
321
327
|
|
322
|
-
self.aCollapse = self.mMore
|
328
|
+
self.aCollapse = qtAddAction(self.mMore, self.tr("Collapse All"))
|
323
329
|
self.aCollapse.triggered.connect(self.projTree.collapseAll)
|
324
330
|
|
325
|
-
self.aEmptyTrash = self.mMore
|
331
|
+
self.aEmptyTrash = qtAddAction(self.mMore, self.tr("Empty Trash"))
|
326
332
|
self.aEmptyTrash.triggered.connect(self.projTree.emptyTrash)
|
327
333
|
|
328
334
|
self.tbMore = NIconToolButton(self, iSz)
|
@@ -337,7 +343,7 @@ class GuiProjectToolBar(QWidget):
|
|
337
343
|
self.outerBox.addWidget(self.tbMoveD)
|
338
344
|
self.outerBox.addWidget(self.tbAdd)
|
339
345
|
self.outerBox.addWidget(self.tbMore)
|
340
|
-
self.outerBox.setContentsMargins(
|
346
|
+
self.outerBox.setContentsMargins(4, 2, 0, 2)
|
341
347
|
self.outerBox.setSpacing(0)
|
342
348
|
|
343
349
|
self.setLayout(self.outerBox)
|
@@ -353,10 +359,6 @@ class GuiProjectToolBar(QWidget):
|
|
353
359
|
|
354
360
|
def updateTheme(self) -> None:
|
355
361
|
"""Update theme elements."""
|
356
|
-
qPalette = self.palette()
|
357
|
-
qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
|
358
|
-
self.setPalette(qPalette)
|
359
|
-
|
360
362
|
buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
|
361
363
|
self.tbQuick.setStyleSheet(buttonStyle)
|
362
364
|
self.tbMoveU.setStyleSheet(buttonStyle)
|
@@ -364,17 +366,18 @@ class GuiProjectToolBar(QWidget):
|
|
364
366
|
self.tbAdd.setStyleSheet(buttonStyle)
|
365
367
|
self.tbMore.setStyleSheet(buttonStyle)
|
366
368
|
|
367
|
-
self.tbQuick.setThemeIcon("
|
368
|
-
self.tbMoveU.setThemeIcon("
|
369
|
-
self.tbMoveD.setThemeIcon("
|
370
|
-
self.tbAdd.setThemeIcon("add")
|
371
|
-
self.tbMore.setThemeIcon("
|
369
|
+
self.tbQuick.setThemeIcon("bookmarks", "blue")
|
370
|
+
self.tbMoveU.setThemeIcon("chevron_up", "blue")
|
371
|
+
self.tbMoveD.setThemeIcon("chevron_down", "blue")
|
372
|
+
self.tbAdd.setThemeIcon("add", "green")
|
373
|
+
self.tbMore.setThemeIcon("more_vertical")
|
372
374
|
|
373
|
-
self.
|
374
|
-
self.aAddChap.setIcon(SHARED.theme.getIcon("
|
375
|
-
self.
|
376
|
-
self.
|
377
|
-
self.
|
375
|
+
self.aAddScene.setIcon(SHARED.theme.getIcon("prj_scene", "scene"))
|
376
|
+
self.aAddChap.setIcon(SHARED.theme.getIcon("prj_chapter", "chapter"))
|
377
|
+
self.aAddPart.setIcon(SHARED.theme.getIcon("prj_title", "title"))
|
378
|
+
self.aAddEmpty.setIcon(SHARED.theme.getIcon("prj_document", "file"))
|
379
|
+
self.aAddNote.setIcon(SHARED.theme.getIcon("prj_note", "note"))
|
380
|
+
self.aAddFolder.setIcon(SHARED.theme.getIcon("prj_folder", "folder"))
|
378
381
|
|
379
382
|
self.buildTemplatesMenu()
|
380
383
|
self.buildQuickLinksMenu()
|
@@ -393,9 +396,9 @@ class GuiProjectToolBar(QWidget):
|
|
393
396
|
logger.debug("Rebuilding quick links menu")
|
394
397
|
self.mQuick.clear()
|
395
398
|
for tHandle, nwItem in SHARED.project.tree.iterRoots(None):
|
396
|
-
action = self.mQuick
|
399
|
+
action = qtAddAction(self.mQuick, nwItem.itemName)
|
397
400
|
action.setData(tHandle)
|
398
|
-
action.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass]))
|
401
|
+
action.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass], "root"))
|
399
402
|
action.triggered.connect(
|
400
403
|
qtLambda(self.projView.setSelectedHandle, tHandle, doScroll=True)
|
401
404
|
)
|
@@ -429,9 +432,10 @@ class GuiProjectToolBar(QWidget):
|
|
429
432
|
"""
|
430
433
|
nwItem = SHARED.project.tree[tHandle]
|
431
434
|
allowDoc = isinstance(nwItem, NWItem) and nwItem.documentAllowed()
|
432
|
-
self.aAddEmpty.setVisible(allowDoc)
|
433
|
-
self.aAddChap.setVisible(allowDoc)
|
434
435
|
self.aAddScene.setVisible(allowDoc)
|
436
|
+
self.aAddChap.setVisible(allowDoc)
|
437
|
+
self.aAddPart.setVisible(allowDoc)
|
438
|
+
self.aAddEmpty.setVisible(allowDoc)
|
435
439
|
return
|
436
440
|
|
437
441
|
##
|
@@ -441,8 +445,8 @@ class GuiProjectToolBar(QWidget):
|
|
441
445
|
def _buildRootMenu(self) -> None:
|
442
446
|
"""Build the rood folder menu."""
|
443
447
|
def addClass(itemClass: nwItemClass) -> None:
|
444
|
-
aNew = self.mAddRoot
|
445
|
-
aNew.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass]))
|
448
|
+
aNew = qtAddAction(self.mAddRoot, trConst(nwLabels.CLASS_NAME[itemClass]))
|
449
|
+
aNew.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[itemClass], "root"))
|
446
450
|
aNew.triggered.connect(
|
447
451
|
qtLambda(self.projTree.newTreeItem, nwItemType.ROOT, itemClass)
|
448
452
|
)
|
@@ -507,7 +511,6 @@ class GuiProjectTree(QTreeView):
|
|
507
511
|
self.customContextMenuRequested.connect(self.openContextMenu)
|
508
512
|
|
509
513
|
# Connect signals
|
510
|
-
self.clicked.connect(self._onSingleClick)
|
511
514
|
self.doubleClicked.connect(self._onDoubleClick)
|
512
515
|
self.collapsed.connect(self._onNodeCollapsed)
|
513
516
|
self.expanded.connect(self._onNodeExpanded)
|
@@ -521,7 +524,6 @@ class GuiProjectTree(QTreeView):
|
|
521
524
|
|
522
525
|
def initSettings(self) -> None:
|
523
526
|
"""Set or update tree widget settings."""
|
524
|
-
# Scroll bars
|
525
527
|
if CONFIG.hideVScroll:
|
526
528
|
self.setVerticalScrollBarPolicy(QtScrollAlwaysOff)
|
527
529
|
else:
|
@@ -558,21 +560,26 @@ class GuiProjectTree(QTreeView):
|
|
558
560
|
|
559
561
|
def loadModel(self) -> None:
|
560
562
|
"""Load and prepare a new project model."""
|
563
|
+
if selectModelOld := self.selectionModel():
|
564
|
+
selectModelOld.disconnect()
|
565
|
+
|
561
566
|
self.setModel(SHARED.project.tree.model)
|
562
567
|
|
563
568
|
# Lock the column sizes
|
564
569
|
iPx = SHARED.theme.baseIconHeight
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
570
|
+
|
571
|
+
if header := self.header():
|
572
|
+
header.setStretchLastSection(False)
|
573
|
+
header.setMinimumSectionSize(iPx + 6)
|
574
|
+
header.setSectionResizeMode(ProjectNode.C_NAME, QtHeaderStretch)
|
575
|
+
header.setSectionResizeMode(ProjectNode.C_COUNT, QtHeaderToContents)
|
576
|
+
header.setSectionResizeMode(ProjectNode.C_ACTIVE, QtHeaderFixed)
|
577
|
+
header.setSectionResizeMode(ProjectNode.C_STATUS, QtHeaderFixed)
|
578
|
+
header.resizeSection(ProjectNode.C_ACTIVE, iPx + 6)
|
579
|
+
header.resizeSection(ProjectNode.C_STATUS, iPx + 6)
|
580
|
+
|
581
|
+
if selectModelNew := self.selectionModel():
|
582
|
+
selectModelNew.currentChanged.connect(self._onSelectionChange)
|
576
583
|
|
577
584
|
self.restoreExpandedState()
|
578
585
|
|
@@ -612,12 +619,12 @@ class GuiProjectTree(QTreeView):
|
|
612
619
|
tHandle = None
|
613
620
|
if itemType == nwItemType.ROOT and isinstance(itemClass, nwItemClass):
|
614
621
|
|
615
|
-
|
622
|
+
sPos = -1
|
616
623
|
if (node := self._getNode(self.currentIndex())) and (itemRoot := node.item.itemRoot):
|
617
624
|
if root := SHARED.project.tree.nodes.get(itemRoot):
|
618
|
-
|
625
|
+
sPos = root.row() + 1
|
619
626
|
|
620
|
-
tHandle = SHARED.project.newRoot(itemClass,
|
627
|
+
tHandle = SHARED.project.newRoot(itemClass, sPos)
|
621
628
|
self.restoreExpandedState()
|
622
629
|
|
623
630
|
elif itemType in (nwItemType.FILE, nwItemType.FOLDER):
|
@@ -630,52 +637,43 @@ class GuiProjectTree(QTreeView):
|
|
630
637
|
SHARED.error(self.tr("Cannot add new files or folders to the Trash folder."))
|
631
638
|
return
|
632
639
|
|
633
|
-
#
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
# Set default label and determine if new item is to be added
|
638
|
-
# as child or sibling to the selected item
|
640
|
+
# Set default label and determine where to put the new item
|
641
|
+
nNote = isNote
|
642
|
+
nLevel = hLevel
|
639
643
|
if itemType == nwItemType.FILE:
|
640
644
|
if copyDoc and (cItem := SHARED.project.tree[copyDoc]):
|
645
|
+
nNote = cItem.isNoteLayout()
|
646
|
+
nLevel = nwStyles.H_LEVEL.get(cItem.mainHeading, 0)
|
641
647
|
newLabel = cItem.itemName
|
642
|
-
asChild = sIsParent and node.item.isDocumentLayout()
|
643
648
|
elif isNote:
|
644
649
|
newLabel = self.tr("New Note")
|
645
|
-
|
650
|
+
elif hLevel == 1:
|
651
|
+
newLabel = self.tr("New Part")
|
646
652
|
elif hLevel == 2:
|
647
653
|
newLabel = self.tr("New Chapter")
|
648
|
-
asChild = sIsParent and node.item.isDocumentLayout() and sLevel < 2
|
649
654
|
elif hLevel == 3:
|
650
655
|
newLabel = self.tr("New Scene")
|
651
|
-
asChild = sIsParent and node.item.isDocumentLayout() and sLevel < 3
|
652
656
|
else:
|
653
657
|
newLabel = self.tr("New Document")
|
654
|
-
asChild = sIsParent and node.item.isDocumentLayout()
|
655
658
|
else:
|
656
659
|
newLabel = self.tr("New Folder")
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
sHandle
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
SHARED.project.writeNewFile(tHandle, hLevel, not isNote)
|
675
|
-
SHARED.project.index.reIndexHandle(tHandle)
|
676
|
-
SHARED.project.tree.refreshItems([tHandle])
|
677
|
-
else:
|
678
|
-
tHandle = SHARED.project.newFolder(newLabel, sHandle, pos)
|
660
|
+
nLevel = 0
|
661
|
+
|
662
|
+
sHandle, sPos = SHARED.project.tree.pickParent(node, nLevel, nNote)
|
663
|
+
if sHandle:
|
664
|
+
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=newLabel)
|
665
|
+
if dlgOk:
|
666
|
+
# Add the file or folder
|
667
|
+
if itemType == nwItemType.FILE:
|
668
|
+
if tHandle := SHARED.project.newFile(newLabel, sHandle, sPos):
|
669
|
+
if copyDoc:
|
670
|
+
SHARED.project.copyFileContent(tHandle, copyDoc)
|
671
|
+
elif hLevel > 0:
|
672
|
+
SHARED.project.writeNewFile(tHandle, hLevel, not nNote)
|
673
|
+
SHARED.project.index.reIndexHandle(tHandle)
|
674
|
+
SHARED.project.tree.refreshItems([tHandle])
|
675
|
+
else:
|
676
|
+
tHandle = SHARED.project.newFolder(newLabel, sHandle, sPos)
|
679
677
|
|
680
678
|
# Select the new item automatically
|
681
679
|
if tHandle:
|
@@ -966,7 +964,8 @@ class GuiProjectTree(QTreeView):
|
|
966
964
|
ctxMenu.buildMultiSelectMenu()
|
967
965
|
else:
|
968
966
|
ctxMenu.buildSingleSelectMenu()
|
969
|
-
|
967
|
+
if viewport := self.viewport():
|
968
|
+
ctxMenu.exec(viewport.mapToGlobal(point))
|
970
969
|
ctxMenu.setParent(None)
|
971
970
|
return
|
972
971
|
|
@@ -974,10 +973,10 @@ class GuiProjectTree(QTreeView):
|
|
974
973
|
# Private Slots
|
975
974
|
##
|
976
975
|
|
977
|
-
@pyqtSlot(QModelIndex)
|
978
|
-
def
|
976
|
+
@pyqtSlot(QModelIndex, QModelIndex)
|
977
|
+
def _onSelectionChange(self, current: QModelIndex, previous: QModelIndex) -> None:
|
979
978
|
"""The user changed which item is selected."""
|
980
|
-
if node := self._getNode(
|
979
|
+
if node := self._getNode(current):
|
981
980
|
self.projView.selectedItemChanged.emit(node.item.itemHandle)
|
982
981
|
return
|
983
982
|
|
@@ -1026,7 +1025,7 @@ class GuiProjectTree(QTreeView):
|
|
1026
1025
|
return [i for i in self.selectedIndexes() if i.column() == 0]
|
1027
1026
|
|
1028
1027
|
def _getModel(self) -> ProjectModel | None:
|
1029
|
-
"""Return
|
1028
|
+
"""Return the model, if it exists."""
|
1030
1029
|
if isinstance(model := self.model(), ProjectModel):
|
1031
1030
|
return model
|
1032
1031
|
return None
|
@@ -1087,7 +1086,8 @@ class _UpdatableMenu(QMenu):
|
|
1087
1086
|
|
1088
1087
|
def setActionsVisible(self, value: bool) -> None:
|
1089
1088
|
"""Set the visibility of root action."""
|
1090
|
-
self.menuAction()
|
1089
|
+
if action := self.menuAction():
|
1090
|
+
action.setVisible(value)
|
1091
1091
|
return
|
1092
1092
|
|
1093
1093
|
##
|
@@ -1103,7 +1103,7 @@ class _UpdatableMenu(QMenu):
|
|
1103
1103
|
|
1104
1104
|
class _TreeContextMenu(QMenu):
|
1105
1105
|
|
1106
|
-
__slots__ = ("
|
1106
|
+
__slots__ = ("_children", "_handle", "_indices", "_item", "_model", "_node", "_tree", "_view")
|
1107
1107
|
|
1108
1108
|
def __init__(
|
1109
1109
|
self, projTree: GuiProjectTree, model: ProjectModel,
|
@@ -1131,7 +1131,7 @@ class _TreeContextMenu(QMenu):
|
|
1131
1131
|
|
1132
1132
|
def buildTrashMenu(self) -> None:
|
1133
1133
|
"""Build the special menu for the Trash folder."""
|
1134
|
-
action =
|
1134
|
+
action = qtAddAction(self, self.tr("Empty Trash"))
|
1135
1135
|
action.triggered.connect(self._tree.emptyTrash)
|
1136
1136
|
if self._children:
|
1137
1137
|
self._expandCollapse()
|
@@ -1152,7 +1152,7 @@ class _TreeContextMenu(QMenu):
|
|
1152
1152
|
self.addSeparator()
|
1153
1153
|
|
1154
1154
|
# Edit Item Settings
|
1155
|
-
action =
|
1155
|
+
action = qtAddAction(self, self.tr("Rename"))
|
1156
1156
|
action.triggered.connect(qtLambda(self._view.renameTreeItem, self._handle))
|
1157
1157
|
if isFile:
|
1158
1158
|
self._itemHeader()
|
@@ -1167,7 +1167,7 @@ class _TreeContextMenu(QMenu):
|
|
1167
1167
|
# Process Item
|
1168
1168
|
if self._children:
|
1169
1169
|
self._expandCollapse()
|
1170
|
-
action =
|
1170
|
+
action = qtAddAction(self, self.tr("Duplicate"))
|
1171
1171
|
action.triggered.connect(qtLambda(self._tree.duplicateFromHandle, self._handle))
|
1172
1172
|
self._deleteOrTrash()
|
1173
1173
|
|
@@ -1187,12 +1187,12 @@ class _TreeContextMenu(QMenu):
|
|
1187
1187
|
|
1188
1188
|
def _docActions(self) -> None:
|
1189
1189
|
"""Add document actions."""
|
1190
|
-
action =
|
1190
|
+
action = qtAddAction(self, self.tr("Open Document"))
|
1191
1191
|
action.triggered.connect(qtLambda(
|
1192
1192
|
self._view.openDocumentRequest.emit,
|
1193
1193
|
self._handle, nwDocMode.EDIT, "", True
|
1194
1194
|
))
|
1195
|
-
action =
|
1195
|
+
action = qtAddAction(self, self.tr("View Document"))
|
1196
1196
|
action.triggered.connect(qtLambda(
|
1197
1197
|
self._view.openDocumentRequest.emit,
|
1198
1198
|
self._handle, nwDocMode.VIEW, "", False
|
@@ -1201,10 +1201,11 @@ class _TreeContextMenu(QMenu):
|
|
1201
1201
|
|
1202
1202
|
def _itemCreation(self) -> None:
|
1203
1203
|
"""Add create item actions."""
|
1204
|
-
menu =
|
1205
|
-
menu.addAction(self._view.projBar.aAddEmpty)
|
1206
|
-
menu.addAction(self._view.projBar.aAddChap)
|
1204
|
+
menu = qtAddMenu(self, self.tr("Create New ..."))
|
1207
1205
|
menu.addAction(self._view.projBar.aAddScene)
|
1206
|
+
menu.addAction(self._view.projBar.aAddChap)
|
1207
|
+
menu.addAction(self._view.projBar.aAddPart)
|
1208
|
+
menu.addAction(self._view.projBar.aAddEmpty)
|
1208
1209
|
menu.addAction(self._view.projBar.aAddNote)
|
1209
1210
|
menu.addAction(self._view.projBar.aAddFolder)
|
1210
1211
|
return
|
@@ -1213,7 +1214,7 @@ class _TreeContextMenu(QMenu):
|
|
1213
1214
|
"""Check if there is a header that can be used for rename."""
|
1214
1215
|
SHARED.saveEditor()
|
1215
1216
|
if hItem := SHARED.project.index.getItemHeading(self._handle, "T0001"):
|
1216
|
-
action =
|
1217
|
+
action = qtAddAction(self, self.tr("Rename to Heading"))
|
1217
1218
|
action.triggered.connect(
|
1218
1219
|
qtLambda(self._view.renameTreeItem, self._handle, hItem.title)
|
1219
1220
|
)
|
@@ -1222,50 +1223,54 @@ class _TreeContextMenu(QMenu):
|
|
1222
1223
|
def _itemActive(self) -> None:
|
1223
1224
|
"""Add Active/Inactive actions."""
|
1224
1225
|
if len(self._indices) > 1:
|
1225
|
-
mSub =
|
1226
|
-
aOne = mSub
|
1226
|
+
mSub = qtAddMenu(self, self.tr("Set Active to ..."))
|
1227
|
+
aOne = qtAddAction(mSub, self._tree.trActive)
|
1228
|
+
aOne.setIcon(SHARED.theme.getIcon("checked", "green"))
|
1227
1229
|
aOne.triggered.connect(qtLambda(self._iterItemActive, True))
|
1228
|
-
aTwo = mSub
|
1230
|
+
aTwo = qtAddAction(mSub, self._tree.trInactive)
|
1231
|
+
aTwo.setIcon(SHARED.theme.getIcon("unchecked", "red"))
|
1229
1232
|
aTwo.triggered.connect(qtLambda(self._iterItemActive, False))
|
1230
1233
|
else:
|
1231
|
-
action =
|
1234
|
+
action = qtAddAction(self, self.tr("Toggle Active"))
|
1232
1235
|
action.triggered.connect(self._toggleItemActive)
|
1233
1236
|
return
|
1234
1237
|
|
1235
1238
|
def _itemStatusImport(self, multi: bool) -> None:
|
1236
1239
|
"""Add actions for changing status or importance."""
|
1237
1240
|
if self._item.isNovelLike():
|
1238
|
-
menu =
|
1241
|
+
menu = qtAddMenu(self, self.tr("Set Status to ..."))
|
1239
1242
|
current = self._item.itemStatus
|
1240
1243
|
for key, entry in SHARED.project.data.itemStatus.iterItems():
|
1241
1244
|
name = entry.name
|
1242
1245
|
if not multi and current == key:
|
1243
1246
|
name += f" ({nwUnicode.U_CHECK})"
|
1244
|
-
action = menu
|
1247
|
+
action = qtAddAction(menu, name)
|
1248
|
+
action.setIcon(entry.icon)
|
1245
1249
|
if multi:
|
1246
1250
|
action.triggered.connect(qtLambda(self._iterSetItemStatus, key))
|
1247
1251
|
else:
|
1248
1252
|
action.triggered.connect(qtLambda(self._changeItemStatus, key))
|
1249
1253
|
menu.addSeparator()
|
1250
|
-
action = menu
|
1254
|
+
action = qtAddAction(menu, self.tr("Manage Labels ..."))
|
1251
1255
|
action.triggered.connect(qtLambda(
|
1252
1256
|
self._view.projectSettingsRequest.emit,
|
1253
1257
|
GuiProjectSettings.PAGE_STATUS
|
1254
1258
|
))
|
1255
1259
|
else:
|
1256
|
-
menu =
|
1260
|
+
menu = qtAddMenu(self, self.tr("Set Importance to ..."))
|
1257
1261
|
current = self._item.itemImport
|
1258
1262
|
for key, entry in SHARED.project.data.itemImport.iterItems():
|
1259
1263
|
name = entry.name
|
1260
1264
|
if not multi and current == key:
|
1261
1265
|
name += f" ({nwUnicode.U_CHECK})"
|
1262
|
-
action = menu
|
1266
|
+
action = qtAddAction(menu, name)
|
1267
|
+
action.setIcon(entry.icon)
|
1263
1268
|
if multi:
|
1264
1269
|
action.triggered.connect(qtLambda(self._iterSetItemImport, key))
|
1265
1270
|
else:
|
1266
1271
|
action.triggered.connect(qtLambda(self._changeItemImport, key))
|
1267
1272
|
menu.addSeparator()
|
1268
|
-
action = menu
|
1273
|
+
action = qtAddAction(menu, self.tr("Manage Labels ..."))
|
1269
1274
|
action.triggered.connect(qtLambda(
|
1270
1275
|
self._view.projectSettingsRequest.emit,
|
1271
1276
|
GuiProjectSettings.PAGE_IMPORT
|
@@ -1274,7 +1279,7 @@ class _TreeContextMenu(QMenu):
|
|
1274
1279
|
|
1275
1280
|
def _itemTransform(self, isFile: bool, isFolder: bool) -> None:
|
1276
1281
|
"""Add actions for the Transform menu."""
|
1277
|
-
menu =
|
1282
|
+
menu = qtAddMenu(self, self.tr("Transform ..."))
|
1278
1283
|
|
1279
1284
|
trDoc = trConst(nwLabels.LAYOUT_NAME[nwItemLayout.DOCUMENT])
|
1280
1285
|
trNote = trConst(nwLabels.LAYOUT_NAME[nwItemLayout.NOTE])
|
@@ -1284,42 +1289,42 @@ class _TreeContextMenu(QMenu):
|
|
1284
1289
|
isNoteFile = isFile and self._item.isNoteLayout()
|
1285
1290
|
|
1286
1291
|
if isNoteFile and self._item.documentAllowed():
|
1287
|
-
action = menu
|
1292
|
+
action = qtAddAction(menu, self.tr("Convert to {0}").format(trDoc))
|
1288
1293
|
action.triggered.connect(qtLambda(self._changeItemLayout, loDoc))
|
1289
1294
|
|
1290
1295
|
if isDocFile:
|
1291
|
-
action = menu
|
1296
|
+
action = qtAddAction(menu, self.tr("Convert to {0}").format(trNote))
|
1292
1297
|
action.triggered.connect(qtLambda(self._changeItemLayout, loNote))
|
1293
1298
|
|
1294
1299
|
if isFolder and self._item.documentAllowed():
|
1295
|
-
action = menu
|
1300
|
+
action = qtAddAction(menu, self.tr("Convert to {0}").format(trDoc))
|
1296
1301
|
action.triggered.connect(qtLambda(self._convertFolderToFile, loDoc))
|
1297
1302
|
|
1298
1303
|
if isFolder:
|
1299
|
-
action = menu
|
1304
|
+
action = qtAddAction(menu, self.tr("Convert to {0}").format(trNote))
|
1300
1305
|
action.triggered.connect(qtLambda(self._convertFolderToFile, loNote))
|
1301
1306
|
|
1302
1307
|
if self._children and isFile:
|
1303
|
-
action = menu
|
1308
|
+
action = qtAddAction(menu, self.tr("Merge Child Items into Self"))
|
1304
1309
|
action.triggered.connect(qtLambda(self._tree.mergeDocuments, self._handle, False))
|
1305
|
-
action = menu
|
1310
|
+
action = qtAddAction(menu, self.tr("Merge Child Items into New"))
|
1306
1311
|
action.triggered.connect(qtLambda(self._tree.mergeDocuments, self._handle, True))
|
1307
1312
|
|
1308
1313
|
if self._children and isFolder:
|
1309
|
-
action = menu
|
1314
|
+
action = qtAddAction(menu, self.tr("Merge Documents in Folder"))
|
1310
1315
|
action.triggered.connect(qtLambda(self._tree.mergeDocuments, self._handle, True))
|
1311
1316
|
|
1312
1317
|
if isFile:
|
1313
|
-
action = menu
|
1318
|
+
action = qtAddAction(menu, self.tr("Split Document by Headings"))
|
1314
1319
|
action.triggered.connect(qtLambda(self._tree.splitDocument, self._handle))
|
1315
1320
|
|
1316
1321
|
return
|
1317
1322
|
|
1318
1323
|
def _expandCollapse(self) -> None:
|
1319
1324
|
"""Add actions for expand and collapse."""
|
1320
|
-
action =
|
1325
|
+
action = qtAddAction(self, self.tr("Expand All"))
|
1321
1326
|
action.triggered.connect(qtLambda(self._tree.expandFromIndex, self._indices[0]))
|
1322
|
-
action =
|
1327
|
+
action = qtAddAction(self, self.tr("Collapse All"))
|
1323
1328
|
action.triggered.connect(qtLambda(self._tree.collapseFromIndex, self._indices[0]))
|
1324
1329
|
return
|
1325
1330
|
|
@@ -1327,12 +1332,12 @@ class _TreeContextMenu(QMenu):
|
|
1327
1332
|
"""Add move to Trash action."""
|
1328
1333
|
if (
|
1329
1334
|
self._model.trashSelection(self._indices)
|
1330
|
-
or len(self._indices) == 1 and self._item.isRootType()
|
1335
|
+
or (len(self._indices) == 1 and self._item.isRootType())
|
1331
1336
|
):
|
1332
1337
|
text = self.tr("Delete Permanently")
|
1333
1338
|
else:
|
1334
1339
|
text = self.tr("Move to Trash")
|
1335
|
-
action = self
|
1340
|
+
action = qtAddAction(self, text)
|
1336
1341
|
action.triggered.connect(self._tree.processDeleteRequest)
|
1337
1342
|
return
|
1338
1343
|
|
@@ -1399,6 +1404,7 @@ class _TreeContextMenu(QMenu):
|
|
1399
1404
|
if itemLayout == nwItemLayout.DOCUMENT and self._item.documentAllowed():
|
1400
1405
|
self._item.setLayout(nwItemLayout.DOCUMENT)
|
1401
1406
|
self._item.notifyToRefresh()
|
1407
|
+
self._item.notifyNovelStructureChange()
|
1402
1408
|
elif itemLayout == nwItemLayout.NOTE:
|
1403
1409
|
self._item.setLayout(nwItemLayout.NOTE)
|
1404
1410
|
self._item.notifyToRefresh()
|
@@ -1415,6 +1421,7 @@ class _TreeContextMenu(QMenu):
|
|
1415
1421
|
self._item.setType(nwItemType.FILE)
|
1416
1422
|
self._item.setLayout(nwItemLayout.DOCUMENT)
|
1417
1423
|
self._item.notifyToRefresh()
|
1424
|
+
self._item.notifyNovelStructureChange()
|
1418
1425
|
elif msgYes and itemLayout == nwItemLayout.NOTE:
|
1419
1426
|
self._item.setType(nwItemType.FILE)
|
1420
1427
|
self._item.setLayout(nwItemLayout.NOTE)
|