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