novelWriter 2.4b1__py3-none-any.whl → 2.4.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.
Files changed (89) hide show
  1. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/METADATA +5 -6
  2. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/RECORD +79 -83
  3. novelwriter/__init__.py +15 -8
  4. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  5. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  6. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  7. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  8. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  9. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  10. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  11. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  12. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  13. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  14. novelwriter/assets/icons/none.svg +4 -0
  15. novelwriter/assets/icons/typicons_dark/icons.conf +2 -2
  16. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
  17. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
  18. novelwriter/assets/icons/typicons_light/icons.conf +2 -2
  19. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
  20. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
  21. novelwriter/assets/manual.pdf +0 -0
  22. novelwriter/assets/sample.zip +0 -0
  23. novelwriter/common.py +11 -3
  24. novelwriter/config.py +12 -4
  25. novelwriter/core/buildsettings.py +7 -7
  26. novelwriter/core/coretools.py +21 -22
  27. novelwriter/core/docbuild.py +2 -2
  28. novelwriter/core/projectxml.py +1 -1
  29. novelwriter/core/spellcheck.py +3 -3
  30. novelwriter/core/status.py +3 -2
  31. novelwriter/core/tokenizer.py +3 -3
  32. novelwriter/core/toodt.py +333 -356
  33. novelwriter/dialogs/about.py +9 -11
  34. novelwriter/dialogs/docmerge.py +17 -14
  35. novelwriter/dialogs/docsplit.py +14 -12
  36. novelwriter/dialogs/editlabel.py +5 -4
  37. novelwriter/dialogs/preferences.py +29 -34
  38. novelwriter/dialogs/projectsettings.py +31 -28
  39. novelwriter/dialogs/quotes.py +10 -9
  40. novelwriter/dialogs/wordlist.py +17 -14
  41. novelwriter/error.py +14 -12
  42. novelwriter/extensions/circularprogress.py +12 -8
  43. novelwriter/extensions/configlayout.py +1 -3
  44. novelwriter/extensions/modified.py +33 -2
  45. novelwriter/extensions/pagedsidebar.py +16 -14
  46. novelwriter/extensions/simpleprogress.py +3 -1
  47. novelwriter/extensions/statusled.py +3 -1
  48. novelwriter/extensions/switch.py +10 -9
  49. novelwriter/extensions/switchbox.py +14 -13
  50. novelwriter/gui/doceditor.py +205 -246
  51. novelwriter/gui/dochighlight.py +26 -9
  52. novelwriter/gui/docviewer.py +55 -59
  53. novelwriter/gui/docviewerpanel.py +16 -13
  54. novelwriter/gui/editordocument.py +4 -4
  55. novelwriter/gui/itemdetails.py +45 -48
  56. novelwriter/gui/mainmenu.py +2 -2
  57. novelwriter/gui/noveltree.py +23 -21
  58. novelwriter/gui/outline.py +93 -94
  59. novelwriter/gui/projtree.py +32 -30
  60. novelwriter/gui/search.py +75 -29
  61. novelwriter/gui/sidebar.py +24 -28
  62. novelwriter/gui/statusbar.py +14 -14
  63. novelwriter/gui/theme.py +61 -39
  64. novelwriter/guimain.py +37 -33
  65. novelwriter/shared.py +21 -9
  66. novelwriter/text/counting.py +1 -0
  67. novelwriter/tools/dictionaries.py +15 -14
  68. novelwriter/tools/lipsum.py +20 -17
  69. novelwriter/tools/manusbuild.py +44 -35
  70. novelwriter/tools/manuscript.py +112 -112
  71. novelwriter/tools/manussettings.py +91 -98
  72. novelwriter/tools/noveldetails.py +20 -18
  73. novelwriter/tools/welcome.py +51 -48
  74. novelwriter/tools/writingstats.py +61 -55
  75. novelwriter/types.py +90 -0
  76. novelwriter/assets/icons/typicons_dark/typ_arrow-down.svg +0 -4
  77. novelwriter/assets/icons/typicons_dark/typ_arrow-right.svg +0 -4
  78. novelwriter/assets/icons/typicons_light/typ_arrow-down.svg +0 -4
  79. novelwriter/assets/icons/typicons_light/typ_arrow-right.svg +0 -4
  80. novelwriter/core/__init__.py +0 -3
  81. novelwriter/dialogs/__init__.py +0 -3
  82. novelwriter/extensions/__init__.py +0 -3
  83. novelwriter/gui/__init__.py +0 -3
  84. novelwriter/text/__init__.py +0 -3
  85. novelwriter/tools/__init__.py +0 -3
  86. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/LICENSE.md +0 -0
  87. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/WHEEL +0 -0
  88. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/entry_points.txt +0 -0
  89. {novelWriter-2.4b1.dist-info → novelWriter-2.4.1.dist-info}/top_level.txt +0 -0
@@ -25,25 +25,22 @@ from __future__ import annotations
25
25
 
26
26
  import logging
27
27
 
28
- from typing import TYPE_CHECKING
29
-
30
- from PyQt5.QtGui import QFont
31
- from PyQt5.QtCore import Qt, pyqtSlot
28
+ from PyQt5.QtCore import pyqtSlot
32
29
  from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel
33
30
 
34
31
  from novelwriter import CONFIG, SHARED
35
32
  from novelwriter.constants import trConst, nwLabels
36
-
37
- if TYPE_CHECKING: # pragma: no cover
38
- from novelwriter.guimain import GuiMain
33
+ from novelwriter.types import (
34
+ QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase, QtAlignRightMiddle
35
+ )
39
36
 
40
37
  logger = logging.getLogger(__name__)
41
38
 
42
39
 
43
40
  class GuiItemDetails(QWidget):
44
41
 
45
- def __init__(self, mainGui: GuiMain) -> None:
46
- super().__init__(parent=mainGui)
42
+ def __init__(self, parent: QWidget) -> None:
43
+ super().__init__(parent=parent)
47
44
 
48
45
  logger.debug("Create: GuiItemDetails")
49
46
 
@@ -56,89 +53,89 @@ class GuiItemDetails(QWidget):
56
53
  mPx = CONFIG.pxInt(6)
57
54
  fPt = SHARED.theme.fontPointSize
58
55
 
59
- fntLabel = QFont()
56
+ fntLabel = self.font()
60
57
  fntLabel.setBold(True)
61
58
  fntLabel.setPointSizeF(0.9*fPt)
62
59
 
63
- fntValue = QFont()
60
+ fntValue = self.font()
64
61
  fntValue.setPointSizeF(0.9*fPt)
65
62
 
66
63
  # Label
67
- self.labelName = QLabel(self.tr("Label"))
64
+ self.labelName = QLabel(self.tr("Label"), self)
68
65
  self.labelName.setFont(fntLabel)
69
- self.labelName.setAlignment(Qt.AlignLeft | Qt.AlignBaseline)
66
+ self.labelName.setAlignment(QtAlignLeftBase)
70
67
 
71
- self.labelIcon = QLabel("")
72
- self.labelIcon.setAlignment(Qt.AlignRight | Qt.AlignBaseline)
68
+ self.labelIcon = QLabel("", self)
69
+ self.labelIcon.setAlignment(QtAlignRightBase)
73
70
 
74
- self.labelData = QLabel("")
71
+ self.labelData = QLabel("", self)
75
72
  self.labelData.setFont(fntValue)
76
- self.labelData.setAlignment(Qt.AlignLeft | Qt.AlignBaseline)
73
+ self.labelData.setAlignment(QtAlignLeftBase)
77
74
  self.labelData.setWordWrap(True)
78
75
 
79
76
  # Status
80
- self.statusName = QLabel(self.tr("Status"))
77
+ self.statusName = QLabel(self.tr("Status"), self)
81
78
  self.statusName.setFont(fntLabel)
82
- self.statusName.setAlignment(Qt.AlignLeft)
79
+ self.statusName.setAlignment(QtAlignLeft)
83
80
 
84
- self.statusIcon = QLabel("")
85
- self.statusIcon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
81
+ self.statusIcon = QLabel("", self)
82
+ self.statusIcon.setAlignment(QtAlignRightMiddle)
86
83
 
87
- self.statusData = QLabel("")
84
+ self.statusData = QLabel("", self)
88
85
  self.statusData.setFont(fntValue)
89
- self.statusData.setAlignment(Qt.AlignLeft)
86
+ self.statusData.setAlignment(QtAlignLeft)
90
87
 
91
88
  # Class
92
- self.className = QLabel(self.tr("Class"))
89
+ self.className = QLabel(self.tr("Class"), self)
93
90
  self.className.setFont(fntLabel)
94
- self.className.setAlignment(Qt.AlignLeft)
91
+ self.className.setAlignment(QtAlignLeft)
95
92
 
96
- self.classIcon = QLabel("")
97
- self.classIcon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
93
+ self.classIcon = QLabel("", self)
94
+ self.classIcon.setAlignment(QtAlignRightMiddle)
98
95
 
99
- self.classData = QLabel("")
96
+ self.classData = QLabel("", self)
100
97
  self.classData.setFont(fntValue)
101
- self.classData.setAlignment(Qt.AlignLeft)
98
+ self.classData.setAlignment(QtAlignLeft)
102
99
 
103
100
  # Layout
104
- self.usageName = QLabel(self.tr("Usage"))
101
+ self.usageName = QLabel(self.tr("Usage"), self)
105
102
  self.usageName.setFont(fntLabel)
106
- self.usageName.setAlignment(Qt.AlignLeft)
103
+ self.usageName.setAlignment(QtAlignLeft)
107
104
 
108
- self.usageIcon = QLabel("")
109
- self.usageIcon.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
105
+ self.usageIcon = QLabel("", self)
106
+ self.usageIcon.setAlignment(QtAlignRightMiddle)
110
107
 
111
- self.usageData = QLabel("")
108
+ self.usageData = QLabel("", self)
112
109
  self.usageData.setFont(fntValue)
113
- self.usageData.setAlignment(Qt.AlignLeft)
110
+ self.usageData.setAlignment(QtAlignLeft)
114
111
  self.usageData.setWordWrap(True)
115
112
 
116
113
  # Character Count
117
- self.cCountName = QLabel(" "+self.tr("Characters"))
114
+ self.cCountName = QLabel(" "+self.tr("Characters"), self)
118
115
  self.cCountName.setFont(fntLabel)
119
- self.cCountName.setAlignment(Qt.AlignRight)
116
+ self.cCountName.setAlignment(QtAlignRight)
120
117
 
121
- self.cCountData = QLabel("")
118
+ self.cCountData = QLabel("", self)
122
119
  self.cCountData.setFont(fntValue)
123
- self.cCountData.setAlignment(Qt.AlignRight)
120
+ self.cCountData.setAlignment(QtAlignRight)
124
121
 
125
122
  # Word Count
126
- self.wCountName = QLabel(" "+self.tr("Words"))
123
+ self.wCountName = QLabel(" "+self.tr("Words"), self)
127
124
  self.wCountName.setFont(fntLabel)
128
- self.wCountName.setAlignment(Qt.AlignRight)
125
+ self.wCountName.setAlignment(QtAlignRight)
129
126
 
130
- self.wCountData = QLabel("")
127
+ self.wCountData = QLabel("", self)
131
128
  self.wCountData.setFont(fntValue)
132
- self.wCountData.setAlignment(Qt.AlignRight)
129
+ self.wCountData.setAlignment(QtAlignRight)
133
130
 
134
131
  # Paragraph Count
135
- self.pCountName = QLabel(" "+self.tr("Paragraphs"))
132
+ self.pCountName = QLabel(" "+self.tr("Paragraphs"), self)
136
133
  self.pCountName.setFont(fntLabel)
137
- self.pCountName.setAlignment(Qt.AlignRight)
134
+ self.pCountName.setAlignment(QtAlignRight)
138
135
 
139
- self.pCountData = QLabel("")
136
+ self.pCountData = QLabel("", self)
140
137
  self.pCountData.setFont(fntValue)
141
- self.pCountData.setAlignment(Qt.AlignRight)
138
+ self.pCountData.setAlignment(QtAlignRight)
142
139
 
143
140
  # Assemble
144
141
  self.mainBox = QGridLayout(self)
@@ -234,7 +231,7 @@ class GuiItemDetails(QWidget):
234
231
  return
235
232
 
236
233
  self._handle = tHandle
237
- iPx = int(round(0.8*SHARED.theme.baseIconSize))
234
+ iPx = int(round(0.9*SHARED.theme.baseIconHeight))
238
235
 
239
236
  # Label
240
237
  # =====
@@ -736,8 +736,8 @@ class GuiMainMenu(QMenuBar):
736
736
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_UNN)
737
737
  )
738
738
 
739
- # Format > Hard Scene
740
- self.aFmtHardSc = self.fmtMenu.addAction(self.tr("Hard Scene"))
739
+ # Format > Alternative Scene
740
+ self.aFmtHardSc = self.fmtMenu.addAction(self.tr("Alternative Scene"))
741
741
  self.aFmtHardSc.triggered.connect(
742
742
  lambda: self.requestDocAction.emit(nwDocAction.BLOCK_HSC)
743
743
  )
@@ -31,8 +31,8 @@ from enum import Enum
31
31
  from time import time
32
32
  from typing import TYPE_CHECKING
33
33
 
34
+ from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSlot, pyqtSignal
34
35
  from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
35
- from PyQt5.QtCore import QModelIndex, QPoint, Qt, QSize, pyqtSlot, pyqtSignal
36
36
  from PyQt5.QtWidgets import (
37
37
  QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
38
38
  QInputDialog, QMenu, QSizePolicy, QToolTip, QTreeWidget, QTreeWidgetItem,
@@ -47,6 +47,7 @@ from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
47
47
  from novelwriter.extensions.modified import NIconToolButton
48
48
  from novelwriter.extensions.novelselector import NovelSelector
49
49
  from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
50
+ from novelwriter.types import QtAlignRight, QtDecoration, QtMouseLeft, QtMouseMiddle, QtUserRole
50
51
 
51
52
  if TYPE_CHECKING: # pragma: no cover
52
53
  from novelwriter.guimain import GuiMain
@@ -200,7 +201,7 @@ class GuiNovelToolBar(QWidget):
200
201
  self.novelView = novelView
201
202
  self.mainGui = novelView.mainGui
202
203
 
203
- iPx = SHARED.theme.baseIconSize
204
+ iSz = SHARED.theme.baseIconSize
204
205
  mPx = CONFIG.pxInt(2)
205
206
 
206
207
  self.setContentsMargins(0, 0, 0, 0)
@@ -217,12 +218,12 @@ class GuiNovelToolBar(QWidget):
217
218
  self.novelValue.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
218
219
  self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
219
220
 
220
- self.tbNovel = NIconToolButton(self, iPx)
221
+ self.tbNovel = NIconToolButton(self, iSz)
221
222
  self.tbNovel.setToolTip(self.tr("Novel Root"))
222
223
  self.tbNovel.clicked.connect(self.novelValue.showPopup)
223
224
 
224
225
  # Refresh Button
225
- self.tbRefresh = NIconToolButton(self, iPx)
226
+ self.tbRefresh = NIconToolButton(self, iSz)
226
227
  self.tbRefresh.setToolTip(self.tr("Refresh"))
227
228
  self.tbRefresh.clicked.connect(self._refreshNovelTree)
228
229
 
@@ -241,7 +242,7 @@ class GuiNovelToolBar(QWidget):
241
242
  self.aLastColSize = self.mLastCol.addAction(self.tr("Column Size"))
242
243
  self.aLastColSize.triggered.connect(self._selectLastColumnSize)
243
244
 
244
- self.tbMore = NIconToolButton(self, iPx)
245
+ self.tbMore = NIconToolButton(self, iSz)
245
246
  self.tbMore.setToolTip(self.tr("More Options"))
246
247
  self.tbMore.setMenu(self.mMore)
247
248
 
@@ -269,9 +270,9 @@ class GuiNovelToolBar(QWidget):
269
270
  def updateTheme(self) -> None:
270
271
  """Update theme elements."""
271
272
  # Icons
272
- self.tbNovel.setIcon(SHARED.theme.getIcon("cls_novel"))
273
- self.tbRefresh.setIcon(SHARED.theme.getIcon("refresh"))
274
- self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
273
+ self.tbNovel.setThemeIcon("cls_novel")
274
+ self.tbRefresh.setThemeIcon("refresh")
275
+ self.tbMore.setThemeIcon("menu")
275
276
 
276
277
  qPalette = self.palette()
277
278
  qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
@@ -343,7 +344,7 @@ class GuiNovelToolBar(QWidget):
343
344
  # Internal Functions
344
345
  ##
345
346
 
346
- def _addLastColAction(self, colType, actionLabel) -> None:
347
+ def _addLastColAction(self, colType: NovelTreeColumn, actionLabel: str) -> None:
347
348
  """Add a column selection entry to the last column menu."""
348
349
  aLast = self.mLastCol.addAction(actionLabel)
349
350
  aLast.setCheckable(True)
@@ -363,10 +364,10 @@ class GuiNovelTree(QTreeWidget):
363
364
  C_EXTRA = 2
364
365
  C_MORE = 3
365
366
 
366
- D_HANDLE = Qt.ItemDataRole.UserRole
367
- D_TITLE = Qt.ItemDataRole.UserRole + 1
368
- D_KEY = Qt.ItemDataRole.UserRole + 2
369
- D_EXTRA = Qt.ItemDataRole.UserRole + 3
367
+ D_HANDLE = QtUserRole
368
+ D_TITLE = QtUserRole + 1
369
+ D_KEY = QtUserRole + 2
370
+ D_EXTRA = QtUserRole + 3
370
371
 
371
372
  def __init__(self, novelView: GuiNovelView) -> None:
372
373
  super().__init__(parent=novelView)
@@ -391,10 +392,11 @@ class GuiNovelTree(QTreeWidget):
391
392
  # Build GUI
392
393
  # =========
393
394
 
394
- iPx = SHARED.theme.baseIconSize
395
+ iPx = SHARED.theme.baseIconHeight
396
+ iSz = SHARED.theme.baseIconSize
395
397
  cMg = CONFIG.pxInt(6)
396
398
 
397
- self.setIconSize(QSize(iPx, iPx))
399
+ self.setIconSize(iSz)
398
400
  self.setFrameStyle(QFrame.Shape.NoFrame)
399
401
  self.setUniformRowHeights(True)
400
402
  self.setAllColumnsShowFocus(True)
@@ -455,7 +457,7 @@ class GuiNovelTree(QTreeWidget):
455
457
 
456
458
  def updateTheme(self) -> None:
457
459
  """Update theme elements."""
458
- iPx = SHARED.theme.baseIconSize
460
+ iPx = SHARED.theme.baseIconHeight
459
461
  self._pMore = SHARED.theme.loadDecoration("deco_doc_more", h=iPx)
460
462
  return
461
463
 
@@ -581,12 +583,12 @@ class GuiNovelTree(QTreeWidget):
581
583
  """
582
584
  super().mousePressEvent(event)
583
585
 
584
- if event.button() == Qt.MouseButton.LeftButton:
586
+ if event.button() == QtMouseLeft:
585
587
  selItem = self.indexAt(event.pos())
586
588
  if not selItem.isValid():
587
589
  self.clearSelection()
588
590
 
589
- elif event.button() == Qt.MouseButton.MiddleButton:
591
+ elif event.button() == QtMouseMiddle:
590
592
  selItem = self.itemAt(event.pos())
591
593
  if not isinstance(selItem, QTreeWidgetItem):
592
594
  return
@@ -676,7 +678,7 @@ class GuiNovelTree(QTreeWidget):
676
678
  newItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
677
679
  newItem.setData(self.C_DATA, self.D_TITLE, sTitle)
678
680
  newItem.setData(self.C_DATA, self.D_KEY, tKey)
679
- newItem.setTextAlignment(self.C_WORDS, Qt.AlignmentFlag.AlignRight)
681
+ newItem.setTextAlignment(self.C_WORDS, QtAlignRight)
680
682
 
681
683
  self._updateTreeItemValues(newItem, novIdx, tHandle, sTitle)
682
684
  self._treeMap[tKey] = newItem
@@ -695,11 +697,11 @@ class GuiNovelTree(QTreeWidget):
695
697
  iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
696
698
  hDec = SHARED.theme.getHeaderDecoration(iLevel)
697
699
 
698
- trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
700
+ trItem.setData(self.C_TITLE, QtDecoration, hDec)
699
701
  trItem.setText(self.C_TITLE, idxItem.title)
700
702
  trItem.setFont(self.C_TITLE, self._hFonts[iLevel])
701
703
  trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}")
702
- trItem.setData(self.C_MORE, Qt.ItemDataRole.DecorationRole, self._pMore)
704
+ trItem.setData(self.C_MORE, QtDecoration, self._pMore)
703
705
 
704
706
  # Custom column
705
707
  mW = int(self._lastColSize * self.viewport().width())
@@ -33,7 +33,7 @@ import logging
33
33
  from time import time
34
34
  from enum import Enum
35
35
 
36
- from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP
36
+ from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot, QT_TRANSLATE_NOOP
37
37
  from PyQt5.QtWidgets import (
38
38
  QAbstractItemView, QAction, QFileDialog, QFrame, QGridLayout, QGroupBox,
39
39
  QHBoxLayout, QLabel, QMenu, QScrollArea, QSizePolicy, QSplitter, QToolBar,
@@ -47,7 +47,11 @@ from novelwriter.enum import (
47
47
  from novelwriter.error import logException
48
48
  from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
49
49
  from novelwriter.constants import nwHeaders, trConst, nwKeyWords, nwLabels
50
+ from novelwriter.extensions.configlayout import NColourLabel
50
51
  from novelwriter.extensions.novelselector import NovelSelector
52
+ from novelwriter.types import (
53
+ QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration, QtUserRole
54
+ )
51
55
 
52
56
 
53
57
  logger = logging.getLogger(__name__)
@@ -67,7 +71,7 @@ class GuiOutlineView(QWidget):
67
71
  self.outlineBar = GuiOutlineToolBar(self)
68
72
  self.outlineBar.setEnabled(False)
69
73
 
70
- self.splitOutline = QSplitter(Qt.Vertical)
74
+ self.splitOutline = QSplitter(Qt.Orientation.Vertical, self)
71
75
  self.splitOutline.addWidget(self.outlineTree)
72
76
  self.splitOutline.addWidget(self.outlineData)
73
77
  self.splitOutline.setOpaqueResize(False)
@@ -187,7 +191,7 @@ class GuiOutlineView(QWidget):
187
191
  return
188
192
 
189
193
  @pyqtSlot(str)
190
- def _rootItemChanged(self, tHandle) -> None:
194
+ def _rootItemChanged(self, tHandle: str) -> None:
191
195
  """Handle root novel changed or needs to be refreshed."""
192
196
  self.outlineTree.refreshTree(rootHandle=(tHandle or None), overRide=True)
193
197
  return
@@ -206,19 +210,18 @@ class GuiOutlineToolBar(QToolBar):
206
210
 
207
211
  logger.debug("Create: GuiOutlineToolBar")
208
212
 
209
- iPx = CONFIG.pxInt(22)
210
- mPx = CONFIG.pxInt(12)
211
-
212
213
  self.setMovable(False)
213
- self.setIconSize(QSize(iPx, iPx))
214
+ self.setIconSize(1.4*SHARED.theme.baseIconSize)
214
215
  self.setContentsMargins(0, 0, 0, 0)
215
216
 
216
217
  stretch = QWidget(self)
217
218
  stretch.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
218
219
 
219
220
  # Novel Selector
220
- self.novelLabel = QLabel(self.tr("Outline of"))
221
- self.novelLabel.setContentsMargins(0, 0, mPx, 0)
221
+ self.novelLabel = NColourLabel(
222
+ self.tr("Outline of"), parent=self, scale=NColourLabel.HEADER_SCALE, bold=True
223
+ )
224
+ self.novelLabel.setContentsMargins(0, 0, CONFIG.pxInt(12), 0)
222
225
 
223
226
  self.novelValue = NovelSelector(self)
224
227
  self.novelValue.setIncludeAll(True)
@@ -353,8 +356,8 @@ class GuiOutlineTree(QTreeWidget):
353
356
  nwOutline.SYNOP: False,
354
357
  }
355
358
 
356
- D_HANDLE = Qt.ItemDataRole.UserRole
357
- D_TITLE = Qt.ItemDataRole.UserRole + 1
359
+ D_HANDLE = QtUserRole
360
+ D_TITLE = QtUserRole + 1
358
361
 
359
362
  hiddenStateChanged = pyqtSignal()
360
363
  activeItemChanged = pyqtSignal(str, str)
@@ -375,8 +378,7 @@ class GuiOutlineTree(QTreeWidget):
375
378
  self.itemDoubleClicked.connect(self._treeDoubleClick)
376
379
  self.itemSelectionChanged.connect(self._itemSelected)
377
380
 
378
- iPx = SHARED.theme.baseIconSize
379
- self.setIconSize(QSize(iPx, iPx))
381
+ self.setIconSize(SHARED.theme.baseIconSize)
380
382
  self.setIndentation(0)
381
383
 
382
384
  self.treeHead = self.header()
@@ -426,7 +428,7 @@ class GuiOutlineTree(QTreeWidget):
426
428
  ##
427
429
 
428
430
  @property
429
- def hiddenColumns(self):
431
+ def hiddenColumns(self) -> dict[nwOutline, bool]:
430
432
  return self._colHidden
431
433
 
432
434
  ##
@@ -584,7 +586,7 @@ class GuiOutlineTree(QTreeWidget):
584
586
  # Internal Functions
585
587
  ##
586
588
 
587
- def _loadHeaderState(self):
589
+ def _loadHeaderState(self) -> None:
588
590
  """Load the state of the main tree header, that is, column order
589
591
  and column width.
590
592
  """
@@ -675,11 +677,11 @@ class GuiOutlineTree(QTreeWidget):
675
677
  headItem = self.headerItem()
676
678
  if isinstance(headItem, QTreeWidgetItem):
677
679
  headItem.setTextAlignment(
678
- self._colIdx[nwOutline.CCOUNT], Qt.AlignmentFlag.AlignRight)
680
+ self._colIdx[nwOutline.CCOUNT], QtAlignRight)
679
681
  headItem.setTextAlignment(
680
- self._colIdx[nwOutline.WCOUNT], Qt.AlignmentFlag.AlignRight)
682
+ self._colIdx[nwOutline.WCOUNT], QtAlignRight)
681
683
  headItem.setTextAlignment(
682
- self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
684
+ self._colIdx[nwOutline.PCOUNT], QtAlignRight)
683
685
 
684
686
  novStruct = SHARED.project.index.novelStructure(rootHandle=rootHandle, activeOnly=True)
685
687
  for _, tHandle, sTitle, novIdx in novStruct:
@@ -692,7 +694,7 @@ class GuiOutlineTree(QTreeWidget):
692
694
  trItem = QTreeWidgetItem()
693
695
  hDec = SHARED.theme.getHeaderDecoration(iLevel)
694
696
 
695
- trItem.setData(self._colIdx[nwOutline.TITLE], Qt.ItemDataRole.DecorationRole, hDec)
697
+ trItem.setData(self._colIdx[nwOutline.TITLE], QtDecoration, hDec)
696
698
  trItem.setText(self._colIdx[nwOutline.TITLE], novIdx.title)
697
699
  trItem.setData(self._colIdx[nwOutline.TITLE], self.D_HANDLE, tHandle)
698
700
  trItem.setData(self._colIdx[nwOutline.TITLE], self.D_TITLE, sTitle)
@@ -705,9 +707,9 @@ class GuiOutlineTree(QTreeWidget):
705
707
  trItem.setText(self._colIdx[nwOutline.CCOUNT], f"{novIdx.charCount:n}")
706
708
  trItem.setText(self._colIdx[nwOutline.WCOUNT], f"{novIdx.wordCount:n}")
707
709
  trItem.setText(self._colIdx[nwOutline.PCOUNT], f"{novIdx.paraCount:n}")
708
- trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], Qt.AlignmentFlag.AlignRight)
709
- trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], Qt.AlignmentFlag.AlignRight)
710
- trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], Qt.AlignmentFlag.AlignRight)
710
+ trItem.setTextAlignment(self._colIdx[nwOutline.CCOUNT], QtAlignRight)
711
+ trItem.setTextAlignment(self._colIdx[nwOutline.WCOUNT], QtAlignRight)
712
+ trItem.setTextAlignment(self._colIdx[nwOutline.PCOUNT], QtAlignRight)
711
713
 
712
714
  refs = SHARED.project.index.getReferences(tHandle, sTitle)
713
715
  trItem.setText(self._colIdx[nwOutline.POV], ", ".join(refs[nwKeyWords.POV_KEY]))
@@ -801,12 +803,12 @@ class GuiOutlineDetails(QScrollArea):
801
803
  bFont = SHARED.theme.guiFontB
802
804
 
803
805
  # Details Area
804
- self.titleLabel = QLabel(self.tr("Title"))
805
- self.fileLabel = QLabel(self.tr("Document"))
806
- self.itemLabel = QLabel(self.tr("Status"))
807
- self.titleValue = QLabel("")
808
- self.fileValue = QLabel("")
809
- self.itemValue = QLabel("")
806
+ self.titleLabel = QLabel(self.tr("Title"), self)
807
+ self.fileLabel = QLabel(self.tr("Document"), self)
808
+ self.itemLabel = QLabel(self.tr("Status"), self)
809
+ self.titleValue = QLabel("", self)
810
+ self.fileValue = QLabel("", self)
811
+ self.itemValue = QLabel("", self)
810
812
 
811
813
  self.titleLabel.setFont(bFont)
812
814
  self.fileLabel.setFont(bFont)
@@ -820,12 +822,12 @@ class GuiOutlineDetails(QScrollArea):
820
822
  self.itemValue.setMaximumWidth(maxTitle)
821
823
 
822
824
  # Stats Area
823
- self.cCLabel = QLabel(self.tr("Characters"))
824
- self.wCLabel = QLabel(self.tr("Words"))
825
- self.pCLabel = QLabel(self.tr("Paragraphs"))
826
- self.cCValue = QLabel("")
827
- self.wCValue = QLabel("")
828
- self.pCValue = QLabel("")
825
+ self.cCLabel = QLabel(self.tr("Characters"), self)
826
+ self.wCLabel = QLabel(self.tr("Words"), self)
827
+ self.pCLabel = QLabel(self.tr("Paragraphs"), self)
828
+ self.cCValue = QLabel("", self)
829
+ self.wCValue = QLabel("", self)
830
+ self.pCValue = QLabel("", self)
829
831
 
830
832
  self.cCLabel.setFont(bFont)
831
833
  self.wCLabel.setFont(bFont)
@@ -834,31 +836,31 @@ class GuiOutlineDetails(QScrollArea):
834
836
  self.cCValue.setMinimumWidth(wCount)
835
837
  self.wCValue.setMinimumWidth(wCount)
836
838
  self.pCValue.setMinimumWidth(wCount)
837
- self.cCValue.setAlignment(Qt.AlignRight)
838
- self.wCValue.setAlignment(Qt.AlignRight)
839
- self.pCValue.setAlignment(Qt.AlignRight)
839
+ self.cCValue.setAlignment(QtAlignRight)
840
+ self.wCValue.setAlignment(QtAlignRight)
841
+ self.pCValue.setAlignment(QtAlignRight)
840
842
 
841
843
  # Synopsis
842
- self.synopLabel = QLabel(self.tr("Synopsis"))
844
+ self.synopLabel = QLabel(self.tr("Synopsis"), self)
843
845
  self.synopLabel.setFont(bFont)
844
846
 
845
- self.synopValue = QLabel("")
847
+ self.synopValue = QLabel("", self)
846
848
  self.synopValue.setWordWrap(True)
847
- self.synopValue.setAlignment(Qt.AlignTop | Qt.AlignLeft)
849
+ self.synopValue.setAlignment(QtAlignLeftTop)
848
850
 
849
851
  self.synopLWrap = QHBoxLayout()
850
852
  self.synopLWrap.addWidget(self.synopValue, 1)
851
853
 
852
854
  # Tags
853
- self.povKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
854
- self.focKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
855
- self.chrKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
856
- self.pltKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
857
- self.timKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
858
- self.wldKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
859
- self.objKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
860
- self.entKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
861
- self.cstKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]))
855
+ self.povKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]), self)
856
+ self.focKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]), self)
857
+ self.chrKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]), self)
858
+ self.pltKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]), self)
859
+ self.timKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]), self)
860
+ self.wldKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]), self)
861
+ self.objKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]), self)
862
+ self.entKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]), self)
863
+ self.cstKeyLabel = QLabel(trConst(nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY]), self)
862
864
 
863
865
  self.povKeyLabel.setFont(bFont)
864
866
  self.focKeyLabel.setFont(bFont)
@@ -880,15 +882,15 @@ class GuiOutlineDetails(QScrollArea):
880
882
  self.entKeyLWrap = QHBoxLayout()
881
883
  self.cstKeyLWrap = QHBoxLayout()
882
884
 
883
- self.povKeyValue = QLabel("")
884
- self.focKeyValue = QLabel("")
885
- self.chrKeyValue = QLabel("")
886
- self.pltKeyValue = QLabel("")
887
- self.timKeyValue = QLabel("")
888
- self.wldKeyValue = QLabel("")
889
- self.objKeyValue = QLabel("")
890
- self.entKeyValue = QLabel("")
891
- self.cstKeyValue = QLabel("")
885
+ self.povKeyValue = QLabel("", self)
886
+ self.focKeyValue = QLabel("", self)
887
+ self.chrKeyValue = QLabel("", self)
888
+ self.pltKeyValue = QLabel("", self)
889
+ self.timKeyValue = QLabel("", self)
890
+ self.wldKeyValue = QLabel("", self)
891
+ self.objKeyValue = QLabel("", self)
892
+ self.entKeyValue = QLabel("", self)
893
+ self.cstKeyValue = QLabel("", self)
892
894
 
893
895
  self.povKeyValue.setWordWrap(True)
894
896
  self.focKeyValue.setWordWrap(True)
@@ -925,23 +927,20 @@ class GuiOutlineDetails(QScrollArea):
925
927
  self.mainForm = QGridLayout()
926
928
  self.mainGroup.setLayout(self.mainForm)
927
929
 
928
- topLeft = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft
929
- topRight = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight
930
-
931
- self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, topLeft)
932
- self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, topLeft)
933
- self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, topLeft)
934
- self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, topRight)
935
- self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, topLeft)
936
- self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, topLeft)
937
- self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, topLeft)
938
- self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, topRight)
939
- self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, topLeft)
940
- self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, topLeft)
941
- self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, topLeft)
942
- self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, topRight)
943
- self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, topLeft)
944
- self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, topLeft)
930
+ self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, QtAlignLeftTop)
931
+ self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, QtAlignLeftTop)
932
+ self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, QtAlignLeftTop)
933
+ self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, QtAlignRightTop)
934
+ self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, QtAlignLeftTop)
935
+ self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, QtAlignLeftTop)
936
+ self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, QtAlignLeftTop)
937
+ self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, QtAlignRightTop)
938
+ self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, QtAlignLeftTop)
939
+ self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, QtAlignLeftTop)
940
+ self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, QtAlignLeftTop)
941
+ self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, QtAlignRightTop)
942
+ self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, QtAlignLeftTop)
943
+ self.mainForm.addLayout(self.synopLWrap, 4, 0, 1, 4, QtAlignLeftTop)
945
944
 
946
945
  self.mainForm.setColumnStretch(1, 1)
947
946
  self.mainForm.setRowStretch(4, 1)
@@ -953,24 +952,24 @@ class GuiOutlineDetails(QScrollArea):
953
952
  self.tagsForm = QGridLayout()
954
953
  self.tagsGroup.setLayout(self.tagsForm)
955
954
 
956
- self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, topLeft)
957
- self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, topLeft)
958
- self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, topLeft)
959
- self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, topLeft)
960
- self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, topLeft)
961
- self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, topLeft)
962
- self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, topLeft)
963
- self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, topLeft)
964
- self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, topLeft)
965
- self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, topLeft)
966
- self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, topLeft)
967
- self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, topLeft)
968
- self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, topLeft)
969
- self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, topLeft)
970
- self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, topLeft)
971
- self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, topLeft)
972
- self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, topLeft)
973
- self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, topLeft)
955
+ self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, QtAlignLeftTop)
956
+ self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, QtAlignLeftTop)
957
+ self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, QtAlignLeftTop)
958
+ self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, QtAlignLeftTop)
959
+ self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, QtAlignLeftTop)
960
+ self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, QtAlignLeftTop)
961
+ self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, QtAlignLeftTop)
962
+ self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, QtAlignLeftTop)
963
+ self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, QtAlignLeftTop)
964
+ self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, QtAlignLeftTop)
965
+ self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, QtAlignLeftTop)
966
+ self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, QtAlignLeftTop)
967
+ self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, QtAlignLeftTop)
968
+ self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, QtAlignLeftTop)
969
+ self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, QtAlignLeftTop)
970
+ self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, QtAlignLeftTop)
971
+ self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, QtAlignLeftTop)
972
+ self.tagsForm.addLayout(self.cstKeyLWrap, 8, 1, 1, 1, QtAlignLeftTop)
974
973
 
975
974
  self.tagsForm.setColumnStretch(1, 1)
976
975
  self.tagsForm.setRowStretch(8, 1)
@@ -978,7 +977,7 @@ class GuiOutlineDetails(QScrollArea):
978
977
  self.tagsForm.setVerticalSpacing(vSpace)
979
978
 
980
979
  # Assemble
981
- self.outerWidget = QWidget()
980
+ self.outerWidget = QWidget(self)
982
981
  self.outerBox = QHBoxLayout()
983
982
  self.outerBox.addWidget(self.mainGroup, 0)
984
983
  self.outerBox.addWidget(self.tagsGroup, 1)