novelWriter 2.2rc1__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.2rc1.dist-info → novelWriter-2.2.1.dist-info}/METADATA +1 -1
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/RECORD +113 -111
- {novelWriter-2.2rc1.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_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/typicons_dark/icons.conf +3 -2
- 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_light/icons.conf +3 -2
- 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/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/release_notes.htm +50 -7
- novelwriter/common.py +16 -29
- novelwriter/config.py +3 -3
- novelwriter/constants.py +1 -1
- novelwriter/core/buildsettings.py +1 -1
- novelwriter/core/coretools.py +2 -1
- novelwriter/core/docbuild.py +1 -1
- novelwriter/core/document.py +1 -1
- novelwriter/core/index.py +2 -2
- novelwriter/core/item.py +2 -2
- novelwriter/core/options.py +3 -3
- novelwriter/core/project.py +3 -3
- novelwriter/core/projectdata.py +2 -2
- 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 +2 -2
- novelwriter/core/tokenizer.py +1 -1
- novelwriter/core/tomd.py +2 -2
- novelwriter/core/toodt.py +1 -1
- 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 +44 -57
- 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 +4 -14
- novelwriter/dialogs/wordlist.py +34 -21
- novelwriter/enum.py +5 -4
- 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 +72 -64
- novelwriter/gui/dochighlight.py +3 -2
- novelwriter/gui/docviewer.py +22 -47
- novelwriter/gui/docviewerpanel.py +68 -23
- novelwriter/gui/editordocument.py +3 -3
- novelwriter/gui/itemdetails.py +2 -2
- novelwriter/gui/mainmenu.py +35 -30
- novelwriter/gui/noveltree.py +44 -53
- novelwriter/gui/outline.py +2 -1
- novelwriter/gui/projtree.py +5 -6
- novelwriter/gui/sidebar.py +6 -4
- novelwriter/gui/statusbar.py +47 -4
- novelwriter/gui/theme.py +5 -6
- novelwriter/guimain.py +139 -189
- novelwriter/shared.py +53 -29
- novelwriter/tools/dictionaries.py +2 -2
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +3 -4
- novelwriter/tools/manuscript.py +19 -26
- novelwriter/tools/manussettings.py +2 -4
- novelwriter/tools/projwizard.py +3 -3
- novelwriter/tools/writingstats.py +17 -4
- 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_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,10 @@ novelWriter – GUI Text Document
|
|
3
3
|
===============================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2023-09-07 [2.2b1]
|
6
|
+
Created: 2023-09-07 [2.2b1] GuiTextDocument
|
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
|
@@ -50,7 +50,7 @@ class GuiTextDocument(QTextDocument):
|
|
50
50
|
|
51
51
|
return
|
52
52
|
|
53
|
-
def __del__(self): # pragma: no cover
|
53
|
+
def __del__(self) -> None: # pragma: no cover
|
54
54
|
logger.debug("Delete: GuiTextDocument")
|
55
55
|
return
|
56
56
|
|
novelwriter/gui/itemdetails.py
CHANGED
@@ -3,10 +3,10 @@ novelWriter – GUI Item Details Panel
|
|
3
3
|
====================================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2019-04-24 [0.0.1]
|
6
|
+
Created: 2019-04-24 [0.0.1] GuiItemDetails
|
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
|
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
|
@@ -36,6 +36,7 @@ from novelwriter import CONFIG, SHARED
|
|
36
36
|
from novelwriter.enum import nwDocAction, nwDocInsert, nwWidget
|
37
37
|
from novelwriter.common import openExternalPath
|
38
38
|
from novelwriter.constants import nwConst, trConst, nwKeyWords, nwLabels, nwUnicode
|
39
|
+
from novelwriter.extensions.eventfilters import StatusTipFilter
|
39
40
|
|
40
41
|
if TYPE_CHECKING: # pragma: no cover
|
41
42
|
from novelwriter.guimain import GuiMain
|
@@ -73,6 +74,8 @@ class GuiMainMenu(QMenuBar):
|
|
73
74
|
self._buildToolsMenu()
|
74
75
|
self._buildHelpMenu()
|
75
76
|
|
77
|
+
self.installEventFilter(StatusTipFilter(mainGui))
|
78
|
+
|
76
79
|
logger.debug("Ready: GuiMainMenu")
|
77
80
|
|
78
81
|
return
|
@@ -154,12 +157,12 @@ class GuiMainMenu(QMenuBar):
|
|
154
157
|
# Project > Project Settings
|
155
158
|
self.aProjectSettings = self.projMenu.addAction(self.tr("Project Settings"))
|
156
159
|
self.aProjectSettings.setShortcut("Ctrl+Shift+,")
|
157
|
-
self.aProjectSettings.triggered.connect(
|
160
|
+
self.aProjectSettings.triggered.connect(self.mainGui.showProjectSettingsDialog)
|
158
161
|
|
159
162
|
# Project > Project Details
|
160
163
|
self.aProjectDetails = self.projMenu.addAction(self.tr("Project Details"))
|
161
164
|
self.aProjectDetails.setShortcut("Shift+F6")
|
162
|
-
self.aProjectDetails.triggered.connect(
|
165
|
+
self.aProjectDetails.triggered.connect(self.mainGui.showProjectDetailsDialog)
|
163
166
|
|
164
167
|
# Project > Separator
|
165
168
|
self.projMenu.addSeparator()
|
@@ -566,7 +569,7 @@ class GuiMainMenu(QMenuBar):
|
|
566
569
|
|
567
570
|
# Insert > Short Description Comment
|
568
571
|
self.aInsShort = self.mInsComments.addAction(self.tr("Short Description Comment"))
|
569
|
-
self.aInsShort.setShortcut("Ctrl+K,
|
572
|
+
self.aInsShort.setShortcut("Ctrl+K, H")
|
570
573
|
self.aInsShort.triggered.connect(
|
571
574
|
lambda: self.requestDocInsert.emit(nwDocInsert.SHORT)
|
572
575
|
)
|
@@ -593,8 +596,10 @@ class GuiMainMenu(QMenuBar):
|
|
593
596
|
)
|
594
597
|
|
595
598
|
# Insert > Placeholder Text
|
596
|
-
self.aLipsumText = self.
|
597
|
-
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
|
+
)
|
598
603
|
|
599
604
|
return
|
600
605
|
|
@@ -603,25 +608,25 @@ class GuiMainMenu(QMenuBar):
|
|
603
608
|
# Format
|
604
609
|
self.fmtMenu = self.addMenu(self.tr("&Format"))
|
605
610
|
|
606
|
-
# Format >
|
607
|
-
self.
|
608
|
-
self.
|
609
|
-
self.
|
610
|
-
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)
|
611
616
|
)
|
612
617
|
|
613
|
-
# Format >
|
614
|
-
self.
|
615
|
-
self.
|
616
|
-
self.
|
617
|
-
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)
|
618
623
|
)
|
619
624
|
|
620
625
|
# Format > Strikethrough
|
621
626
|
self.aFmtStrike = self.fmtMenu.addAction(self.tr("Strikethrough"))
|
622
627
|
self.aFmtStrike.setShortcut("Ctrl+D")
|
623
628
|
self.aFmtStrike.triggered.connect(
|
624
|
-
lambda: self.requestDocAction.emit(nwDocAction.
|
629
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
|
625
630
|
)
|
626
631
|
|
627
632
|
# Edit > Separator
|
@@ -647,18 +652,18 @@ class GuiMainMenu(QMenuBar):
|
|
647
652
|
# Shortcodes
|
648
653
|
self.mShortcodes = self.fmtMenu.addMenu(self.tr("More Formats ..."))
|
649
654
|
|
650
|
-
# Shortcode Italic
|
651
|
-
self.aScItalic = self.mShortcodes.addAction(self.tr("Italics (Shortcode)"))
|
652
|
-
self.aScItalic.triggered.connect(
|
653
|
-
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
654
|
-
)
|
655
|
-
|
656
655
|
# Shortcode Bold
|
657
656
|
self.aScBold = self.mShortcodes.addAction(self.tr("Bold (Shortcode)"))
|
658
657
|
self.aScBold.triggered.connect(
|
659
658
|
lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
|
660
659
|
)
|
661
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
|
+
|
662
667
|
# Shortcode Strikethrough
|
663
668
|
self.aScStrike = self.mShortcodes.addAction(self.tr("Strikethrough (Shortcode)"))
|
664
669
|
self.aScStrike.triggered.connect(
|
@@ -872,7 +877,7 @@ class GuiMainMenu(QMenuBar):
|
|
872
877
|
|
873
878
|
# Tools > Project Word List
|
874
879
|
self.aEditWordList = self.toolsMenu.addAction(self.tr("Project Word List"))
|
875
|
-
self.aEditWordList.triggered.connect(
|
880
|
+
self.aEditWordList.triggered.connect(self.mainGui.showProjectWordListDialog)
|
876
881
|
|
877
882
|
# Tools > Add Dictionaries
|
878
883
|
if CONFIG.osWindows or CONFIG.isDebug:
|
@@ -902,13 +907,13 @@ class GuiMainMenu(QMenuBar):
|
|
902
907
|
# Tools > Writing Statistics
|
903
908
|
self.aWritingStats = self.toolsMenu.addAction(self.tr("Writing Statistics"))
|
904
909
|
self.aWritingStats.setShortcut("F6")
|
905
|
-
self.aWritingStats.triggered.connect(
|
910
|
+
self.aWritingStats.triggered.connect(self.mainGui.showWritingStatsDialog)
|
906
911
|
|
907
912
|
# Tools > Preferences
|
908
913
|
self.aPreferences = self.toolsMenu.addAction(self.tr("Preferences"))
|
909
914
|
self.aPreferences.setShortcut("Ctrl+,")
|
910
915
|
self.aPreferences.setMenuRole(QAction.PreferencesRole)
|
911
|
-
self.aPreferences.triggered.connect(
|
916
|
+
self.aPreferences.triggered.connect(self.mainGui.showPreferencesDialog)
|
912
917
|
|
913
918
|
return
|
914
919
|
|
@@ -920,12 +925,12 @@ class GuiMainMenu(QMenuBar):
|
|
920
925
|
# Help > About
|
921
926
|
self.aAboutNW = self.helpMenu.addAction(self.tr("About novelWriter"))
|
922
927
|
self.aAboutNW.setMenuRole(QAction.AboutRole)
|
923
|
-
self.aAboutNW.triggered.connect(
|
928
|
+
self.aAboutNW.triggered.connect(self.mainGui.showAboutNWDialog)
|
924
929
|
|
925
930
|
# Help > About Qt5
|
926
931
|
self.aAboutQt = self.helpMenu.addAction(self.tr("About Qt5"))
|
927
932
|
self.aAboutQt.setMenuRole(QAction.AboutQtRole)
|
928
|
-
self.aAboutQt.triggered.connect(
|
933
|
+
self.aAboutQt.triggered.connect(self.mainGui.showAboutQtDialog)
|
929
934
|
|
930
935
|
# Help > Separator
|
931
936
|
self.helpMenu.addSeparator()
|
@@ -961,7 +966,7 @@ class GuiMainMenu(QMenuBar):
|
|
961
966
|
|
962
967
|
# Document > Check for Updates
|
963
968
|
self.aUpdates = self.helpMenu.addAction(self.tr("Check for New Release"))
|
964
|
-
self.aUpdates.triggered.connect(
|
969
|
+
self.aUpdates.triggered.connect(self.mainGui.showUpdatesDialog)
|
965
970
|
|
966
971
|
return
|
967
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
|
@@ -606,6 +606,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
606
606
|
logHidden, orgWidth if logHidden and logWidth == 0 else logWidth
|
607
607
|
]
|
608
608
|
|
609
|
+
logger.debug("Saving State: GuiOutline")
|
609
610
|
pOptions = SHARED.project.options
|
610
611
|
pOptions.setValue("GuiOutline", "columnState", colState)
|
611
612
|
pOptions.saveSettings()
|
novelwriter/gui/projtree.py
CHANGED
@@ -6,9 +6,10 @@ File History:
|
|
6
6
|
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
7
7
|
Created: 2022-06-06 [2.0rc1] GuiProjectView
|
8
8
|
Created: 2022-06-06 [2.0rc1] GuiProjectToolBar
|
9
|
+
Created: 2023-11-22 [2.2rc1] _TreeContextMenu
|
9
10
|
|
10
11
|
This file is a part of novelWriter
|
11
|
-
Copyright 2018–
|
12
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
12
13
|
|
13
14
|
This program is free software: you can redistribute it and/or modify
|
14
15
|
it under the terms of the GNU General Public License as published by
|
@@ -40,6 +41,7 @@ from PyQt5.QtWidgets import (
|
|
40
41
|
)
|
41
42
|
|
42
43
|
from novelwriter import CONFIG, SHARED
|
44
|
+
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout
|
43
45
|
from novelwriter.common import minmax
|
44
46
|
from novelwriter.constants import nwHeaders, nwUnicode, trConst, nwLabels
|
45
47
|
from novelwriter.core.item import NWItem
|
@@ -48,9 +50,6 @@ from novelwriter.dialogs.docmerge import GuiDocMerge
|
|
48
50
|
from novelwriter.dialogs.docsplit import GuiDocSplit
|
49
51
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
50
52
|
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
51
|
-
from novelwriter.enum import (
|
52
|
-
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
|
53
|
-
)
|
54
53
|
|
55
54
|
if TYPE_CHECKING: # pragma: no cover
|
56
55
|
from novelwriter.guimain import GuiMain
|
@@ -681,7 +680,7 @@ class GuiProjectTree(QTreeWidget):
|
|
681
680
|
|
682
681
|
# Add the new item to the project tree
|
683
682
|
self.revealNewTreeItem(tHandle, nHandle=nHandle, wordCount=True)
|
684
|
-
self.
|
683
|
+
self.projView.setTreeFocus() # See issue #1376
|
685
684
|
|
686
685
|
return True
|
687
686
|
|
@@ -1650,7 +1649,7 @@ class _TreeContextMenu(QMenu):
|
|
1650
1649
|
|
1651
1650
|
return
|
1652
1651
|
|
1653
|
-
def __del__(self): # pragma: no cover
|
1652
|
+
def __del__(self) -> None: # pragma: no cover
|
1654
1653
|
logger.debug("Delete: _TreeContextMenu")
|
1655
1654
|
return
|
1656
1655
|
|
novelwriter/gui/sidebar.py
CHANGED
@@ -3,10 +3,10 @@ novelWriter – GUI Main Window SideBar
|
|
3
3
|
=====================================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2022-05-10 [2.0rc1]
|
6
|
+
Created: 2022-05-10 [2.0rc1] GuiSideBar
|
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,12 +27,13 @@ import logging
|
|
27
27
|
|
28
28
|
from typing import TYPE_CHECKING
|
29
29
|
|
30
|
-
from PyQt5.QtCore import QEvent, QPoint, Qt, QSize, pyqtSignal
|
31
30
|
from PyQt5.QtGui import QPalette
|
31
|
+
from PyQt5.QtCore import QEvent, QPoint, Qt, QSize, pyqtSignal
|
32
32
|
from PyQt5.QtWidgets import QMenu, QToolButton, QVBoxLayout, QWidget
|
33
33
|
|
34
34
|
from novelwriter import CONFIG, SHARED
|
35
35
|
from novelwriter.enum import nwView
|
36
|
+
from novelwriter.extensions.eventfilters import StatusTipFilter
|
36
37
|
|
37
38
|
if TYPE_CHECKING: # pragma: no cover
|
38
39
|
from novelwriter.guimain import GuiMain
|
@@ -54,6 +55,7 @@ class GuiSideBar(QWidget):
|
|
54
55
|
iPx = CONFIG.pxInt(24)
|
55
56
|
iconSize = QSize(iPx, iPx)
|
56
57
|
self.setContentsMargins(0, 0, 0, 0)
|
58
|
+
self.installEventFilter(StatusTipFilter(mainGui))
|
57
59
|
|
58
60
|
# Buttons
|
59
61
|
self.tbProject = QToolButton(self)
|
@@ -162,7 +164,7 @@ class GuiSideBar(QWidget):
|
|
162
164
|
|
163
165
|
class _PopRightMenu(QMenu):
|
164
166
|
|
165
|
-
def event(self, event: QEvent):
|
167
|
+
def event(self, event: QEvent) -> bool:
|
166
168
|
"""Overload the show event and move the menu popup location."""
|
167
169
|
if event.type() == QEvent.Show:
|
168
170
|
parent = self.parent()
|
novelwriter/gui/statusbar.py
CHANGED
@@ -3,10 +3,10 @@ novelWriter – GUI Main Window Status Bar
|
|
3
3
|
========================================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2019-04-20 [0.0.1]
|
6
|
+
Created: 2019-04-20 [0.0.1] GuiMainStatus
|
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,9 +27,10 @@ import logging
|
|
27
27
|
|
28
28
|
from time import time
|
29
29
|
from typing import TYPE_CHECKING, Literal
|
30
|
+
from datetime import datetime
|
30
31
|
|
31
|
-
from PyQt5.QtCore import pyqtSlot, QLocale
|
32
32
|
from PyQt5.QtGui import QColor
|
33
|
+
from PyQt5.QtCore import pyqtSlot, QLocale
|
33
34
|
from PyQt5.QtWidgets import qApp, QStatusBar, QLabel
|
34
35
|
|
35
36
|
from novelwriter import CONFIG, SHARED
|
@@ -50,8 +51,9 @@ class GuiMainStatus(QStatusBar):
|
|
50
51
|
|
51
52
|
logger.debug("Create: GuiMainStatus")
|
52
53
|
|
53
|
-
self._refTime
|
54
|
+
self._refTime = -1.0
|
54
55
|
self._userIdle = False
|
56
|
+
self._debugInfo = False
|
55
57
|
|
56
58
|
colNone = QColor(*SHARED.theme.statNone)
|
57
59
|
colSaved = QColor(*SHARED.theme.statSaved)
|
@@ -223,4 +225,45 @@ class GuiMainStatus(QStatusBar):
|
|
223
225
|
self.setDocumentStatus(StatusLED.S_BAD if status else StatusLED.S_GOOD)
|
224
226
|
return
|
225
227
|
|
228
|
+
##
|
229
|
+
# Debug
|
230
|
+
##
|
231
|
+
|
232
|
+
def memInfo(self) -> None: # pragma: no cover
|
233
|
+
"""Display memory info on the status bar. This is used to
|
234
|
+
investigate memory usage and Qt widgets that get left in memory.
|
235
|
+
Enabled by the --meminfo command line flag.
|
236
|
+
|
237
|
+
By default, this tracks memory usage diff after launch. To track
|
238
|
+
full memory usage, set environment variable PYTHONTRACEMALLOC=1
|
239
|
+
before starting novelWriter.
|
240
|
+
"""
|
241
|
+
import tracemalloc
|
242
|
+
from collections import Counter
|
243
|
+
|
244
|
+
widgets = qApp.allWidgets()
|
245
|
+
if not self._debugInfo:
|
246
|
+
if tracemalloc.is_tracing():
|
247
|
+
self._traceMallocRef = "Total"
|
248
|
+
else:
|
249
|
+
self._traceMallocRef = "Relative"
|
250
|
+
tracemalloc.start()
|
251
|
+
self._debugInfo = True
|
252
|
+
self._wCounts = Counter([type(x).__name__ for x in widgets])
|
253
|
+
|
254
|
+
if hasattr(self, "_wCounts"):
|
255
|
+
diff = Counter([type(x).__name__ for x in widgets]) - self._wCounts
|
256
|
+
for name, count in diff.items():
|
257
|
+
logger.debug("Widget '%s': +%d", name, count)
|
258
|
+
|
259
|
+
mem = tracemalloc.get_traced_memory()
|
260
|
+
stamp = datetime.now().strftime("%H:%M:%S")
|
261
|
+
self.showMessage((
|
262
|
+
f"Debug [{stamp}]"
|
263
|
+
f" \u2013 Widgets: {len(widgets)}"
|
264
|
+
f" \u2013 {self._traceMallocRef} Memory: {mem[0]:n}"
|
265
|
+
f" \u2013 Peak: {mem[1]:n}"
|
266
|
+
), 6000)
|
267
|
+
return
|
268
|
+
|
226
269
|
# END Class GuiMainStatus
|
novelwriter/gui/theme.py
CHANGED
@@ -7,7 +7,7 @@ Created: 2019-05-18 [0.1.3] GuiTheme
|
|
7
7
|
Created: 2019-11-08 [0.4] GuiIcons
|
8
8
|
|
9
9
|
This file is a part of novelWriter
|
10
|
-
Copyright 2018–
|
10
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
11
11
|
|
12
12
|
This program is free software: you can redistribute it and/or modify
|
13
13
|
it under the terms of the GNU General Public License as published by
|
@@ -460,8 +460,8 @@ class GuiIcons:
|
|
460
460
|
"search_regex", "search_word",
|
461
461
|
|
462
462
|
# Format Icons
|
463
|
-
"fmt_bold", "
|
464
|
-
"fmt_superscript", "fmt_underline",
|
463
|
+
"fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "fmt_strike", "fmt_strike-md",
|
464
|
+
"fmt_subscript", "fmt_superscript", "fmt_underline",
|
465
465
|
|
466
466
|
# General Button Icons
|
467
467
|
"add", "backward", "bookmark", "browse", "checked", "close", "cross", "down", "edit",
|
@@ -479,9 +479,8 @@ class GuiIcons:
|
|
479
479
|
}
|
480
480
|
|
481
481
|
TOGGLE_ICON_KEYS = {
|
482
|
-
"sticky":
|
483
|
-
"bullet":
|
484
|
-
"fmt_mode": ("fmt_mode-sc", "fmt_mode-md"),
|
482
|
+
"sticky": ("sticky-on", "sticky-off"),
|
483
|
+
"bullet": ("bullet-on", "bullet-off"),
|
485
484
|
}
|
486
485
|
|
487
486
|
IMAGE_MAP = {
|