novelWriter 2.2b1__py3-none-any.whl → 2.2.1__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-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/METADATA +3 -3
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/RECORD +128 -114
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +10 -5
- 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_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +1 -0
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/i18n/project_en_US.json +1 -0
- novelwriter/assets/i18n/project_es_419.json +11 -0
- novelwriter/assets/i18n/project_fr_FR.json +11 -0
- novelwriter/assets/i18n/project_it_IT.json +11 -0
- novelwriter/assets/i18n/project_ja_JP.json +2 -1
- novelwriter/assets/i18n/project_nb_NO.json +1 -0
- novelwriter/assets/i18n/project_zh_CN.json +11 -0
- novelwriter/assets/icons/novelwriter.ico +0 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +11 -3
- novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_panel.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_dark/typ_eye.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +11 -3
- novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_panel.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_light/typ_eye.svg +4 -0
- novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/release_notes.htm +50 -7
- novelwriter/common.py +35 -27
- novelwriter/config.py +13 -28
- novelwriter/constants.py +21 -4
- novelwriter/core/buildsettings.py +2 -2
- novelwriter/core/coretools.py +8 -2
- novelwriter/core/docbuild.py +1 -1
- novelwriter/core/document.py +1 -1
- novelwriter/core/index.py +102 -36
- novelwriter/core/item.py +2 -2
- novelwriter/core/options.py +6 -3
- novelwriter/core/project.py +5 -5
- novelwriter/core/projectdata.py +3 -3
- novelwriter/core/projectxml.py +1 -1
- novelwriter/core/sessions.py +2 -2
- novelwriter/core/spellcheck.py +4 -3
- novelwriter/core/status.py +3 -3
- novelwriter/core/storage.py +1 -1
- novelwriter/core/tohtml.py +11 -5
- novelwriter/core/tokenizer.py +28 -21
- novelwriter/core/tomd.py +6 -2
- novelwriter/core/toodt.py +12 -5
- novelwriter/core/tree.py +2 -2
- novelwriter/dialogs/about.py +30 -31
- novelwriter/dialogs/docmerge.py +24 -15
- novelwriter/dialogs/docsplit.py +27 -16
- novelwriter/dialogs/editlabel.py +19 -7
- novelwriter/dialogs/preferences.py +116 -131
- novelwriter/dialogs/projdetails.py +29 -36
- novelwriter/dialogs/projload.py +32 -36
- novelwriter/dialogs/projsettings.py +20 -15
- novelwriter/dialogs/quotes.py +32 -25
- novelwriter/dialogs/updates.py +17 -16
- novelwriter/dialogs/wordlist.py +34 -21
- novelwriter/enum.py +19 -8
- novelwriter/error.py +1 -1
- novelwriter/extensions/circularprogress.py +1 -1
- novelwriter/extensions/configlayout.py +3 -15
- novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
- novelwriter/extensions/novelselector.py +1 -1
- novelwriter/extensions/pageddialog.py +1 -1
- novelwriter/extensions/pagedsidebar.py +2 -5
- novelwriter/extensions/simpleprogress.py +8 -9
- novelwriter/extensions/statusled.py +1 -1
- novelwriter/extensions/switch.py +4 -4
- novelwriter/extensions/switchbox.py +1 -6
- novelwriter/gui/doceditor.py +349 -236
- novelwriter/gui/dochighlight.py +10 -11
- novelwriter/gui/docviewer.py +158 -360
- novelwriter/gui/docviewerpanel.py +502 -0
- novelwriter/gui/editordocument.py +4 -4
- novelwriter/gui/itemdetails.py +2 -2
- novelwriter/gui/mainmenu.py +50 -36
- novelwriter/gui/noveltree.py +44 -53
- novelwriter/gui/outline.py +12 -7
- novelwriter/gui/projtree.py +465 -381
- novelwriter/gui/sidebar.py +9 -7
- novelwriter/gui/statusbar.py +48 -5
- novelwriter/gui/theme.py +26 -8
- novelwriter/guimain.py +212 -208
- novelwriter/shared.py +76 -30
- novelwriter/tools/dictionaries.py +268 -0
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +20 -10
- novelwriter/tools/manuscript.py +20 -27
- novelwriter/tools/manussettings.py +2 -4
- novelwriter/tools/projwizard.py +3 -3
- novelwriter/tools/writingstats.py +18 -5
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_dark/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/typ_at.svg +0 -4
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/top_level.txt +0 -0
novelwriter/gui/mainmenu.py
CHANGED
@@ -3,10 +3,10 @@ novelWriter – GUI Main Menu
|
|
3
3
|
===========================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2019-04-27 [0.0.1]
|
6
|
+
Created: 2019-04-27 [0.0.1] GuiMainMenu
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
@@ -27,16 +27,16 @@ import logging
|
|
27
27
|
|
28
28
|
from typing import TYPE_CHECKING
|
29
29
|
from pathlib import Path
|
30
|
-
from urllib.parse import urljoin
|
31
|
-
from urllib.request import pathname2url
|
32
30
|
|
33
|
-
from PyQt5.QtCore import QUrl, pyqtSignal, pyqtSlot
|
34
31
|
from PyQt5.QtGui import QDesktopServices
|
32
|
+
from PyQt5.QtCore import QUrl, pyqtSignal, pyqtSlot
|
35
33
|
from PyQt5.QtWidgets import QMenuBar, QAction
|
36
34
|
|
37
35
|
from novelwriter import CONFIG, SHARED
|
38
36
|
from novelwriter.enum import nwDocAction, nwDocInsert, nwWidget
|
37
|
+
from novelwriter.common import openExternalPath
|
39
38
|
from novelwriter.constants import nwConst, trConst, nwKeyWords, nwLabels, nwUnicode
|
39
|
+
from novelwriter.extensions.eventfilters import StatusTipFilter
|
40
40
|
|
41
41
|
if TYPE_CHECKING: # pragma: no cover
|
42
42
|
from novelwriter.guimain import GuiMain
|
@@ -74,6 +74,8 @@ class GuiMainMenu(QMenuBar):
|
|
74
74
|
self._buildToolsMenu()
|
75
75
|
self._buildHelpMenu()
|
76
76
|
|
77
|
+
self.installEventFilter(StatusTipFilter(mainGui))
|
78
|
+
|
77
79
|
logger.debug("Ready: GuiMainMenu")
|
78
80
|
|
79
81
|
return
|
@@ -111,9 +113,7 @@ class GuiMainMenu(QMenuBar):
|
|
111
113
|
def _openUserManualFile(self) -> None:
|
112
114
|
"""Open the documentation in PDF format."""
|
113
115
|
if isinstance(CONFIG.pdfDocs, Path):
|
114
|
-
|
115
|
-
QUrl(urljoin("file:", pathname2url(str(CONFIG.pdfDocs))))
|
116
|
-
)
|
116
|
+
openExternalPath(CONFIG.pdfDocs)
|
117
117
|
return
|
118
118
|
|
119
119
|
@pyqtSlot(str)
|
@@ -157,12 +157,12 @@ class GuiMainMenu(QMenuBar):
|
|
157
157
|
# Project > Project Settings
|
158
158
|
self.aProjectSettings = self.projMenu.addAction(self.tr("Project Settings"))
|
159
159
|
self.aProjectSettings.setShortcut("Ctrl+Shift+,")
|
160
|
-
self.aProjectSettings.triggered.connect(
|
160
|
+
self.aProjectSettings.triggered.connect(self.mainGui.showProjectSettingsDialog)
|
161
161
|
|
162
162
|
# Project > Project Details
|
163
163
|
self.aProjectDetails = self.projMenu.addAction(self.tr("Project Details"))
|
164
164
|
self.aProjectDetails.setShortcut("Shift+F6")
|
165
|
-
self.aProjectDetails.triggered.connect(
|
165
|
+
self.aProjectDetails.triggered.connect(self.mainGui.showProjectDetailsDialog)
|
166
166
|
|
167
167
|
# Project > Separator
|
168
168
|
self.projMenu.addSeparator()
|
@@ -174,7 +174,7 @@ class GuiMainMenu(QMenuBar):
|
|
174
174
|
|
175
175
|
# Project > Delete
|
176
176
|
self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item"))
|
177
|
-
self.aDeleteItem.
|
177
|
+
self.aDeleteItem.setShortcut("Ctrl+Shift+Del") # Cannot be Ctrl+Del, see #629
|
178
178
|
self.aDeleteItem.triggered.connect(lambda: self.mainGui.projView.requestDeleteItem(None))
|
179
179
|
|
180
180
|
# Project > Empty Trash
|
@@ -567,6 +567,13 @@ class GuiMainMenu(QMenuBar):
|
|
567
567
|
lambda: self.requestDocInsert.emit(nwDocInsert.SYNOPSIS)
|
568
568
|
)
|
569
569
|
|
570
|
+
# Insert > Short Description Comment
|
571
|
+
self.aInsShort = self.mInsComments.addAction(self.tr("Short Description Comment"))
|
572
|
+
self.aInsShort.setShortcut("Ctrl+K, H")
|
573
|
+
self.aInsShort.triggered.connect(
|
574
|
+
lambda: self.requestDocInsert.emit(nwDocInsert.SHORT)
|
575
|
+
)
|
576
|
+
|
570
577
|
# Insert > Symbols
|
571
578
|
self.mInsBreaks = self.insMenu.addMenu(self.tr("Page Break and Space"))
|
572
579
|
|
@@ -589,8 +596,10 @@ class GuiMainMenu(QMenuBar):
|
|
589
596
|
)
|
590
597
|
|
591
598
|
# Insert > Placeholder Text
|
592
|
-
self.aLipsumText = self.
|
593
|
-
self.aLipsumText.triggered.connect(
|
599
|
+
self.aLipsumText = self.insMenu.addAction(self.tr("Placeholder Text"))
|
600
|
+
self.aLipsumText.triggered.connect(
|
601
|
+
lambda: self.requestDocInsert.emit(nwDocInsert.LIPSUM)
|
602
|
+
)
|
594
603
|
|
595
604
|
return
|
596
605
|
|
@@ -599,25 +608,25 @@ class GuiMainMenu(QMenuBar):
|
|
599
608
|
# Format
|
600
609
|
self.fmtMenu = self.addMenu(self.tr("&Format"))
|
601
610
|
|
602
|
-
# Format >
|
603
|
-
self.
|
604
|
-
self.
|
605
|
-
self.
|
606
|
-
lambda: self.requestDocAction.emit(nwDocAction.
|
611
|
+
# Format > Bold
|
612
|
+
self.aFmtBold = self.fmtMenu.addAction(self.tr("Bold"))
|
613
|
+
self.aFmtBold.setShortcut("Ctrl+B")
|
614
|
+
self.aFmtBold.triggered.connect(
|
615
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD)
|
607
616
|
)
|
608
617
|
|
609
|
-
# Format >
|
610
|
-
self.
|
611
|
-
self.
|
612
|
-
self.
|
613
|
-
lambda: self.requestDocAction.emit(nwDocAction.
|
618
|
+
# Format > Italic
|
619
|
+
self.aFmtItalic = self.fmtMenu.addAction(self.tr("Italic"))
|
620
|
+
self.aFmtItalic.setShortcut("Ctrl+I")
|
621
|
+
self.aFmtItalic.triggered.connect(
|
622
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC)
|
614
623
|
)
|
615
624
|
|
616
625
|
# Format > Strikethrough
|
617
626
|
self.aFmtStrike = self.fmtMenu.addAction(self.tr("Strikethrough"))
|
618
627
|
self.aFmtStrike.setShortcut("Ctrl+D")
|
619
628
|
self.aFmtStrike.triggered.connect(
|
620
|
-
lambda: self.requestDocAction.emit(nwDocAction.
|
629
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
|
621
630
|
)
|
622
631
|
|
623
632
|
# Edit > Separator
|
@@ -643,18 +652,18 @@ class GuiMainMenu(QMenuBar):
|
|
643
652
|
# Shortcodes
|
644
653
|
self.mShortcodes = self.fmtMenu.addMenu(self.tr("More Formats ..."))
|
645
654
|
|
646
|
-
# Shortcode Italic
|
647
|
-
self.aScItalic = self.mShortcodes.addAction(self.tr("Italics (Shortcode)"))
|
648
|
-
self.aScItalic.triggered.connect(
|
649
|
-
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
650
|
-
)
|
651
|
-
|
652
655
|
# Shortcode Bold
|
653
656
|
self.aScBold = self.mShortcodes.addAction(self.tr("Bold (Shortcode)"))
|
654
657
|
self.aScBold.triggered.connect(
|
655
658
|
lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
|
656
659
|
)
|
657
660
|
|
661
|
+
# Shortcode Italic
|
662
|
+
self.aScItalic = self.mShortcodes.addAction(self.tr("Italics (Shortcode)"))
|
663
|
+
self.aScItalic.triggered.connect(
|
664
|
+
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
665
|
+
)
|
666
|
+
|
658
667
|
# Shortcode Strikethrough
|
659
668
|
self.aScStrike = self.mShortcodes.addAction(self.tr("Strikethrough (Shortcode)"))
|
660
669
|
self.aScStrike.triggered.connect(
|
@@ -868,7 +877,12 @@ class GuiMainMenu(QMenuBar):
|
|
868
877
|
|
869
878
|
# Tools > Project Word List
|
870
879
|
self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List"))
|
871
|
-
self.aEditWordList.triggered.connect(
|
880
|
+
self.aEditWordList.triggered.connect(self.mainGui.showProjectWordListDialog)
|
881
|
+
|
882
|
+
# Tools > Add Dictionaries
|
883
|
+
if CONFIG.osWindows or CONFIG.isDebug:
|
884
|
+
self.aAddDicts = self.toolsMenu.addAction(self.tr("Add Dictionaries"))
|
885
|
+
self.aAddDicts.triggered.connect(self.mainGui.showDictionariesDialog)
|
872
886
|
|
873
887
|
# Tools > Separator
|
874
888
|
self.toolsMenu.addSeparator()
|
@@ -893,13 +907,13 @@ class GuiMainMenu(QMenuBar):
|
|
893
907
|
# Tools > Writing Statistics
|
894
908
|
self.aWritingStats = self.toolsMenu.addAction(self.tr("Writing Statistics"))
|
895
909
|
self.aWritingStats.setShortcut("F6")
|
896
|
-
self.aWritingStats.triggered.connect(
|
910
|
+
self.aWritingStats.triggered.connect(self.mainGui.showWritingStatsDialog)
|
897
911
|
|
898
912
|
# Tools > Preferences
|
899
913
|
self.aPreferences = self.toolsMenu.addAction(self.tr("Preferences"))
|
900
914
|
self.aPreferences.setShortcut("Ctrl+,")
|
901
915
|
self.aPreferences.setMenuRole(QAction.PreferencesRole)
|
902
|
-
self.aPreferences.triggered.connect(
|
916
|
+
self.aPreferences.triggered.connect(self.mainGui.showPreferencesDialog)
|
903
917
|
|
904
918
|
return
|
905
919
|
|
@@ -911,12 +925,12 @@ class GuiMainMenu(QMenuBar):
|
|
911
925
|
# Help > About
|
912
926
|
self.aAboutNW = self.helpMenu.addAction(self.tr("About novelWriter"))
|
913
927
|
self.aAboutNW.setMenuRole(QAction.AboutRole)
|
914
|
-
self.aAboutNW.triggered.connect(
|
928
|
+
self.aAboutNW.triggered.connect(self.mainGui.showAboutNWDialog)
|
915
929
|
|
916
930
|
# Help > About Qt5
|
917
931
|
self.aAboutQt = self.helpMenu.addAction(self.tr("About Qt5"))
|
918
932
|
self.aAboutQt.setMenuRole(QAction.AboutQtRole)
|
919
|
-
self.aAboutQt.triggered.connect(
|
933
|
+
self.aAboutQt.triggered.connect(self.mainGui.showAboutQtDialog)
|
920
934
|
|
921
935
|
# Help > Separator
|
922
936
|
self.helpMenu.addSeparator()
|
@@ -952,7 +966,7 @@ class GuiMainMenu(QMenuBar):
|
|
952
966
|
|
953
967
|
# Document > Check for Updates
|
954
968
|
self.aUpdates = self.helpMenu.addAction(self.tr("Check for New Release"))
|
955
|
-
self.aUpdates.triggered.connect(
|
969
|
+
self.aUpdates.triggered.connect(self.mainGui.showUpdatesDialog)
|
956
970
|
|
957
971
|
return
|
958
972
|
|
novelwriter/gui/noveltree.py
CHANGED
@@ -8,7 +8,7 @@ Created: 2022-06-12 [2.0rc1] GuiNovelView
|
|
8
8
|
Created: 2022-06-12 [2.0rc1] GuiNovelToolBar
|
9
9
|
|
10
10
|
This file is a part of novelWriter
|
11
|
-
Copyright 2018–
|
11
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
12
12
|
|
13
13
|
This program is free software: you can redistribute it and/or modify
|
14
14
|
it under the terms of the GNU General Public License as published by
|
@@ -145,6 +145,7 @@ class GuiNovelView(QWidget):
|
|
145
145
|
"""Run closing project tasks."""
|
146
146
|
lastColType = self.novelTree.lastColType
|
147
147
|
lastColSize = self.novelTree.lastColSize
|
148
|
+
logger.debug("Saving State: GuiNovelView")
|
148
149
|
pOptions = SHARED.project.options
|
149
150
|
pOptions.setValue("GuiNovelView", "lastCol", lastColType)
|
150
151
|
pOptions.setValue("GuiNovelView", "lastColSize", lastColSize)
|
@@ -205,18 +206,18 @@ class GuiNovelToolBar(QWidget):
|
|
205
206
|
|
206
207
|
# Novel Selector
|
207
208
|
selFont = self.font()
|
208
|
-
selFont.setWeight(QFont.Bold)
|
209
|
+
selFont.setWeight(QFont.Weight.Bold)
|
209
210
|
self.novelPrefix = self.tr("Outline of {0}")
|
210
211
|
self.novelValue = NovelSelector(self)
|
211
212
|
self.novelValue.setFont(selFont)
|
212
213
|
self.novelValue.setMinimumWidth(CONFIG.pxInt(150))
|
213
|
-
self.novelValue.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
214
|
+
self.novelValue.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
214
215
|
self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
|
215
216
|
|
216
217
|
self.tbNovel = QToolButton(self)
|
217
218
|
self.tbNovel.setToolTip(self.tr("Novel Root"))
|
218
219
|
self.tbNovel.setIconSize(QSize(iPx, iPx))
|
219
|
-
self.tbNovel.clicked.connect(self.
|
220
|
+
self.tbNovel.clicked.connect(self.novelValue.showPopup)
|
220
221
|
|
221
222
|
# Refresh Button
|
222
223
|
self.tbRefresh = QToolButton(self)
|
@@ -243,7 +244,7 @@ class GuiNovelToolBar(QWidget):
|
|
243
244
|
self.tbMore.setToolTip(self.tr("More Options"))
|
244
245
|
self.tbMore.setIconSize(QSize(iPx, iPx))
|
245
246
|
self.tbMore.setMenu(self.mMore)
|
246
|
-
self.tbMore.setPopupMode(QToolButton.InstantPopup)
|
247
|
+
self.tbMore.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
247
248
|
|
248
249
|
# Assemble
|
249
250
|
self.outerBox = QHBoxLayout()
|
@@ -274,7 +275,7 @@ class GuiNovelToolBar(QWidget):
|
|
274
275
|
self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
|
275
276
|
|
276
277
|
qPalette = self.palette()
|
277
|
-
qPalette.setBrush(QPalette.Window, qPalette.base())
|
278
|
+
qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
|
278
279
|
self.setPalette(qPalette)
|
279
280
|
|
280
281
|
# StyleSheets
|
@@ -326,12 +327,6 @@ class GuiNovelToolBar(QWidget):
|
|
326
327
|
# Private Slots
|
327
328
|
##
|
328
329
|
|
329
|
-
@pyqtSlot()
|
330
|
-
def _openNovelSelector(self) -> None:
|
331
|
-
"""Trigger the dropdown list of the novel selector."""
|
332
|
-
self.novelValue.showPopup()
|
333
|
-
return
|
334
|
-
|
335
330
|
@pyqtSlot()
|
336
331
|
def _refreshNovelTree(self) -> None:
|
337
332
|
"""Rebuild the current tree."""
|
@@ -407,14 +402,14 @@ class GuiNovelTree(QTreeWidget):
|
|
407
402
|
cMg = CONFIG.pxInt(6)
|
408
403
|
|
409
404
|
self.setIconSize(QSize(iPx, iPx))
|
410
|
-
self.setFrameStyle(QFrame.NoFrame)
|
405
|
+
self.setFrameStyle(QFrame.Shape.NoFrame)
|
411
406
|
self.setUniformRowHeights(True)
|
412
407
|
self.setAllColumnsShowFocus(True)
|
413
408
|
self.setHeaderHidden(True)
|
414
409
|
self.setIndentation(0)
|
415
410
|
self.setColumnCount(4)
|
416
|
-
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
417
|
-
self.setSelectionMode(QAbstractItemView.SingleSelection)
|
411
|
+
self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
412
|
+
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
418
413
|
self.setExpandsOnDoubleClick(False)
|
419
414
|
self.setDragEnabled(False)
|
420
415
|
|
@@ -422,10 +417,10 @@ class GuiNovelTree(QTreeWidget):
|
|
422
417
|
treeHeader = self.header()
|
423
418
|
treeHeader.setStretchLastSection(False)
|
424
419
|
treeHeader.setMinimumSectionSize(iPx + cMg)
|
425
|
-
treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.Stretch)
|
426
|
-
treeHeader.setSectionResizeMode(self.C_WORDS, QHeaderView.ResizeToContents)
|
427
|
-
treeHeader.setSectionResizeMode(self.C_EXTRA, QHeaderView.ResizeToContents)
|
428
|
-
treeHeader.setSectionResizeMode(self.C_MORE, QHeaderView.ResizeToContents)
|
420
|
+
treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.ResizeMode.Stretch)
|
421
|
+
treeHeader.setSectionResizeMode(self.C_WORDS, QHeaderView.ResizeMode.ResizeToContents)
|
422
|
+
treeHeader.setSectionResizeMode(self.C_EXTRA, QHeaderView.ResizeMode.ResizeToContents)
|
423
|
+
treeHeader.setSectionResizeMode(self.C_MORE, QHeaderView.ResizeMode.ResizeToContents)
|
429
424
|
|
430
425
|
# Pre-Generate Tree Formatting
|
431
426
|
fH1 = self.font()
|
@@ -454,14 +449,14 @@ class GuiNovelTree(QTreeWidget):
|
|
454
449
|
"""Set or update tree widget settings."""
|
455
450
|
# Scroll bars
|
456
451
|
if CONFIG.hideVScroll:
|
457
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
452
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
458
453
|
else:
|
459
|
-
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
454
|
+
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
460
455
|
|
461
456
|
if CONFIG.hideHScroll:
|
462
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
457
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
463
458
|
else:
|
464
|
-
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
|
459
|
+
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
465
460
|
|
466
461
|
return
|
467
462
|
|
@@ -521,21 +516,16 @@ class GuiNovelTree(QTreeWidget):
|
|
521
516
|
|
522
517
|
def refreshHandle(self, tHandle: str) -> None:
|
523
518
|
"""Refresh the data for a given handle."""
|
524
|
-
idxData
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
self.refreshTree()
|
535
|
-
return
|
536
|
-
|
537
|
-
self._updateTreeItemValues(trItem, tHeading, tHandle, sTitle)
|
538
|
-
|
519
|
+
if idxData := SHARED.project.index.getItemData(tHandle):
|
520
|
+
logger.debug("Refreshing meta data for item '%s'", tHandle)
|
521
|
+
for sTitle, tHeading in idxData.items():
|
522
|
+
sKey = f"{tHandle}:{sTitle}"
|
523
|
+
if trItem := self._treeMap.get(sKey, None):
|
524
|
+
self._updateTreeItemValues(trItem, tHeading, tHandle, sTitle)
|
525
|
+
else:
|
526
|
+
logger.debug("Heading '%s' not in novel tree", sKey)
|
527
|
+
self.refreshTree()
|
528
|
+
return
|
539
529
|
return
|
540
530
|
|
541
531
|
def getSelectedHandle(self) -> tuple[str | None, str | None]:
|
@@ -566,27 +556,25 @@ class GuiNovelTree(QTreeWidget):
|
|
566
556
|
self._lastColSize = minmax(colSize, 15, 75)/100.0
|
567
557
|
return
|
568
558
|
|
569
|
-
def setActiveHandle(self, tHandle: str | None) -> None:
|
559
|
+
def setActiveHandle(self, tHandle: str | None, doScroll: bool = False) -> None:
|
570
560
|
"""Highlight the rows associated with a given handle."""
|
571
|
-
|
572
|
-
|
561
|
+
didScroll = False
|
573
562
|
self._actHandle = tHandle
|
574
563
|
for i in range(self.topLevelItemCount()):
|
575
|
-
tItem
|
576
|
-
if tItem is not None:
|
564
|
+
if tItem := self.topLevelItem(i):
|
577
565
|
if tItem.data(self.C_DATA, self.D_HANDLE) == tHandle:
|
578
566
|
tItem.setBackground(self.C_TITLE, self.palette().alternateBase())
|
579
567
|
tItem.setBackground(self.C_WORDS, self.palette().alternateBase())
|
580
568
|
tItem.setBackground(self.C_EXTRA, self.palette().alternateBase())
|
581
569
|
tItem.setBackground(self.C_MORE, self.palette().alternateBase())
|
570
|
+
if doScroll and not didScroll:
|
571
|
+
self.scrollToItem(tItem, QAbstractItemView.ScrollHint.PositionAtCenter)
|
572
|
+
didScroll = True
|
582
573
|
else:
|
583
574
|
tItem.setBackground(self.C_TITLE, self.palette().base())
|
584
575
|
tItem.setBackground(self.C_WORDS, self.palette().base())
|
585
576
|
tItem.setBackground(self.C_EXTRA, self.palette().base())
|
586
577
|
tItem.setBackground(self.C_MORE, self.palette().base())
|
587
|
-
|
588
|
-
logger.debug("Highlighted Novel Tree in %.3f ms", (time() - tStart)*1000)
|
589
|
-
|
590
578
|
return
|
591
579
|
|
592
580
|
##
|
@@ -600,12 +588,12 @@ class GuiNovelTree(QTreeWidget):
|
|
600
588
|
"""
|
601
589
|
super().mousePressEvent(event)
|
602
590
|
|
603
|
-
if event.button() == Qt.LeftButton:
|
591
|
+
if event.button() == Qt.MouseButton.LeftButton:
|
604
592
|
selItem = self.indexAt(event.pos())
|
605
593
|
if not selItem.isValid():
|
606
594
|
self.clearSelection()
|
607
595
|
|
608
|
-
elif event.button() == Qt.MiddleButton:
|
596
|
+
elif event.button() == Qt.MouseButton.MiddleButton:
|
609
597
|
selItem = self.itemAt(event.pos())
|
610
598
|
if not isinstance(selItem, QTreeWidgetItem):
|
611
599
|
return
|
@@ -636,7 +624,10 @@ class GuiNovelTree(QTreeWidget):
|
|
636
624
|
trItem = self.topLevelItem(i)
|
637
625
|
if isinstance(trItem, QTreeWidgetItem):
|
638
626
|
lastText = trItem.data(self.C_DATA, self.D_EXTRA)
|
639
|
-
trItem.setText(
|
627
|
+
trItem.setText(
|
628
|
+
self.C_EXTRA,
|
629
|
+
fMetric.elidedText(lastText, Qt.TextElideMode.ElideRight, eliW)
|
630
|
+
)
|
640
631
|
return
|
641
632
|
|
642
633
|
##
|
@@ -692,7 +683,7 @@ class GuiNovelTree(QTreeWidget):
|
|
692
683
|
newItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
|
693
684
|
newItem.setData(self.C_DATA, self.D_TITLE, sTitle)
|
694
685
|
newItem.setData(self.C_DATA, self.D_KEY, tKey)
|
695
|
-
newItem.setTextAlignment(self.C_WORDS, Qt.AlignRight)
|
686
|
+
newItem.setTextAlignment(self.C_WORDS, Qt.AlignmentFlag.AlignRight)
|
696
687
|
|
697
688
|
self._updateTreeItemValues(newItem, novIdx, tHandle, sTitle)
|
698
689
|
self._treeMap[tKey] = newItem
|
@@ -711,16 +702,16 @@ class GuiNovelTree(QTreeWidget):
|
|
711
702
|
iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
|
712
703
|
hDec = SHARED.theme.getHeaderDecoration(iLevel)
|
713
704
|
|
714
|
-
trItem.setData(self.C_TITLE, Qt.DecorationRole, hDec)
|
705
|
+
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
715
706
|
trItem.setText(self.C_TITLE, idxItem.title)
|
716
707
|
trItem.setFont(self.C_TITLE, self._hFonts[iLevel])
|
717
708
|
trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}")
|
718
|
-
trItem.setData(self.C_MORE, Qt.DecorationRole, self._pMore)
|
709
|
+
trItem.setData(self.C_MORE, Qt.ItemDataRole.DecorationRole, self._pMore)
|
719
710
|
|
720
711
|
# Custom column
|
721
712
|
mW = int(self._lastColSize * self.viewport().width())
|
722
713
|
lastText, toolTip = self._getLastColumnText(tHandle, sTitle)
|
723
|
-
elideText = self.fontMetrics().elidedText(lastText, Qt.ElideRight, mW)
|
714
|
+
elideText = self.fontMetrics().elidedText(lastText, Qt.TextElideMode.ElideRight, mW)
|
724
715
|
trItem.setText(self.C_EXTRA, elideText)
|
725
716
|
trItem.setData(self.C_DATA, self.D_EXTRA, lastText)
|
726
717
|
trItem.setToolTip(self.C_EXTRA, toolTip)
|
novelwriter/gui/outline.py
CHANGED
@@ -10,7 +10,7 @@ Created: 2019-11-16 [0.4.1] GuiOutlineHeaderMenu
|
|
10
10
|
Created: 2020-06-02 [0.7] GuiOutlineDetails
|
11
11
|
|
12
12
|
This file is a part of novelWriter
|
13
|
-
Copyright 2018–
|
13
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
14
14
|
|
15
15
|
This program is free software: you can redistribute it and/or modify
|
16
16
|
it under the terms of the GNU General Public License as published by
|
@@ -377,13 +377,17 @@ class GuiOutlineTree(QTreeWidget):
|
|
377
377
|
fH2 = self.font()
|
378
378
|
fH2.setBold(True)
|
379
379
|
|
380
|
+
iType = nwItemType.FILE
|
381
|
+
iClass = nwItemClass.NO_CLASS
|
382
|
+
iLayout = nwItemLayout.DOCUMENT
|
383
|
+
|
380
384
|
self._hFonts = [self.font(), fH1, fH2, self.font(), self.font()]
|
381
385
|
self._dIcon = {
|
382
|
-
"H0": SHARED.theme.getItemIcon(
|
383
|
-
"H1": SHARED.theme.getItemIcon(
|
384
|
-
"H2": SHARED.theme.getItemIcon(
|
385
|
-
"H3": SHARED.theme.getItemIcon(
|
386
|
-
"H4": SHARED.theme.getItemIcon(
|
386
|
+
"H0": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H0"),
|
387
|
+
"H1": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H1"),
|
388
|
+
"H2": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H2"),
|
389
|
+
"H3": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H3"),
|
390
|
+
"H4": SHARED.theme.getItemIcon(iType, iClass, iLayout, "H4"),
|
387
391
|
}
|
388
392
|
|
389
393
|
# Internals
|
@@ -549,7 +553,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
549
553
|
"""Load the state of the main tree header, that is, column order
|
550
554
|
and column width.
|
551
555
|
"""
|
552
|
-
# Load whatever we saved last time, regardless of
|
556
|
+
# Load whatever we saved last time, regardless of whether it
|
553
557
|
# contains the correct names or number of columns.
|
554
558
|
colState = SHARED.project.options.getValue("GuiOutline", "columnState", {})
|
555
559
|
|
@@ -602,6 +606,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
602
606
|
logHidden, orgWidth if logHidden and logWidth == 0 else logWidth
|
603
607
|
]
|
604
608
|
|
609
|
+
logger.debug("Saving State: GuiOutline")
|
605
610
|
pOptions = SHARED.project.options
|
606
611
|
pOptions.setValue("GuiOutline", "columnState", colState)
|
607
612
|
pOptions.saveSettings()
|