novelWriter 2.3rc1__py3-none-any.whl → 2.4__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 (125) hide show
  1. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/METADATA +5 -6
  2. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/RECORD +119 -109
  3. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/WHEEL +1 -1
  4. novelWriter-2.4.dist-info/entry_points.txt +2 -0
  5. novelwriter/__init__.py +17 -10
  6. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  7. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  8. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  9. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  10. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  11. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  12. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  13. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  14. novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
  15. novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
  16. novelwriter/assets/i18n/project_nl_NL.json +11 -0
  17. novelwriter/assets/i18n/project_pt_BR.json +11 -0
  18. novelwriter/assets/icons/none.svg +4 -0
  19. novelwriter/assets/icons/typicons_dark/icons.conf +4 -0
  20. novelwriter/assets/icons/typicons_dark/nw_tb-mark.svg +7 -0
  21. novelwriter/assets/icons/typicons_dark/typ_refresh-flipped.svg +1 -1
  22. novelwriter/assets/icons/typicons_dark/typ_refresh.svg +1 -1
  23. novelwriter/assets/icons/typicons_dark/typ_search-grey.svg +4 -0
  24. novelwriter/assets/icons/typicons_dark/typ_times.svg +1 -1
  25. novelwriter/assets/icons/typicons_dark/typ_unfold-hidden.svg +4 -0
  26. novelwriter/assets/icons/typicons_dark/typ_unfold-visible.svg +4 -0
  27. novelwriter/assets/icons/typicons_light/icons.conf +4 -0
  28. novelwriter/assets/icons/typicons_light/nw_tb-mark.svg +7 -0
  29. novelwriter/assets/icons/typicons_light/typ_refresh-flipped.svg +1 -1
  30. novelwriter/assets/icons/typicons_light/typ_refresh.svg +1 -1
  31. novelwriter/assets/icons/typicons_light/typ_search-grey.svg +4 -0
  32. novelwriter/assets/icons/typicons_light/typ_times.svg +1 -1
  33. novelwriter/assets/icons/typicons_light/typ_unfold-hidden.svg +4 -0
  34. novelwriter/assets/icons/typicons_light/typ_unfold-visible.svg +4 -0
  35. novelwriter/assets/manual.pdf +0 -0
  36. novelwriter/assets/sample.zip +0 -0
  37. novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
  38. novelwriter/assets/syntax/default_dark.conf +1 -0
  39. novelwriter/assets/syntax/default_light.conf +1 -0
  40. novelwriter/assets/syntax/grey_dark.conf +1 -0
  41. novelwriter/assets/syntax/grey_light.conf +1 -0
  42. novelwriter/assets/syntax/light_owl.conf +1 -0
  43. novelwriter/assets/syntax/night_owl.conf +1 -0
  44. novelwriter/assets/syntax/solarized_dark.conf +1 -0
  45. novelwriter/assets/syntax/solarized_light.conf +1 -0
  46. novelwriter/assets/syntax/tango.conf +23 -0
  47. novelwriter/assets/syntax/tomorrow.conf +1 -0
  48. novelwriter/assets/syntax/tomorrow_night.conf +1 -0
  49. novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
  50. novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
  51. novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
  52. novelwriter/assets/text/credits_en.htm +25 -23
  53. novelwriter/assets/themes/cyberpunk_night.conf +29 -0
  54. novelwriter/common.py +12 -4
  55. novelwriter/config.py +47 -16
  56. novelwriter/constants.py +5 -6
  57. novelwriter/core/buildsettings.py +64 -44
  58. novelwriter/core/coretools.py +97 -13
  59. novelwriter/core/docbuild.py +74 -7
  60. novelwriter/core/document.py +24 -3
  61. novelwriter/core/index.py +31 -112
  62. novelwriter/core/project.py +11 -15
  63. novelwriter/core/projectxml.py +3 -2
  64. novelwriter/core/sessions.py +2 -2
  65. novelwriter/core/spellcheck.py +3 -3
  66. novelwriter/core/status.py +6 -5
  67. novelwriter/core/storage.py +16 -6
  68. novelwriter/core/tohtml.py +22 -25
  69. novelwriter/core/tokenizer.py +417 -237
  70. novelwriter/core/tomd.py +17 -8
  71. novelwriter/core/toodt.py +386 -351
  72. novelwriter/core/tree.py +8 -8
  73. novelwriter/dialogs/about.py +10 -12
  74. novelwriter/dialogs/docmerge.py +17 -14
  75. novelwriter/dialogs/docsplit.py +20 -19
  76. novelwriter/dialogs/editlabel.py +5 -4
  77. novelwriter/dialogs/preferences.py +32 -40
  78. novelwriter/dialogs/projectsettings.py +31 -28
  79. novelwriter/dialogs/quotes.py +10 -9
  80. novelwriter/dialogs/wordlist.py +18 -15
  81. novelwriter/enum.py +17 -14
  82. novelwriter/error.py +14 -12
  83. novelwriter/extensions/circularprogress.py +12 -8
  84. novelwriter/extensions/configlayout.py +23 -3
  85. novelwriter/extensions/modified.py +51 -2
  86. novelwriter/extensions/pagedsidebar.py +16 -14
  87. novelwriter/extensions/simpleprogress.py +3 -1
  88. novelwriter/extensions/statusled.py +3 -1
  89. novelwriter/extensions/switch.py +10 -9
  90. novelwriter/extensions/switchbox.py +14 -13
  91. novelwriter/extensions/versioninfo.py +1 -1
  92. novelwriter/gui/doceditor.py +433 -496
  93. novelwriter/gui/dochighlight.py +54 -33
  94. novelwriter/gui/docviewer.py +162 -175
  95. novelwriter/gui/docviewerpanel.py +20 -37
  96. novelwriter/gui/editordocument.py +15 -4
  97. novelwriter/gui/itemdetails.py +51 -54
  98. novelwriter/gui/mainmenu.py +37 -17
  99. novelwriter/gui/noveltree.py +31 -37
  100. novelwriter/gui/outline.py +120 -98
  101. novelwriter/gui/projtree.py +114 -112
  102. novelwriter/gui/search.py +362 -0
  103. novelwriter/gui/sidebar.py +36 -45
  104. novelwriter/gui/statusbar.py +14 -14
  105. novelwriter/gui/theme.py +116 -34
  106. novelwriter/guimain.py +216 -207
  107. novelwriter/shared.py +31 -6
  108. novelwriter/text/counting.py +138 -0
  109. novelwriter/tools/dictionaries.py +15 -14
  110. novelwriter/tools/lipsum.py +20 -17
  111. novelwriter/tools/manusbuild.py +43 -35
  112. novelwriter/tools/manuscript.py +381 -104
  113. novelwriter/tools/manussettings.py +263 -125
  114. novelwriter/tools/noveldetails.py +21 -19
  115. novelwriter/tools/welcome.py +59 -57
  116. novelwriter/tools/writingstats.py +61 -55
  117. novelwriter/types.py +90 -0
  118. novelWriter-2.3rc1.dist-info/entry_points.txt +0 -5
  119. novelwriter/core/__init__.py +0 -3
  120. novelwriter/dialogs/__init__.py +0 -3
  121. novelwriter/extensions/__init__.py +0 -3
  122. novelwriter/gui/__init__.py +0 -3
  123. novelwriter/tools/__init__.py +0 -3
  124. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/LICENSE.md +0 -0
  125. {novelWriter-2.3rc1.dist-info → novelWriter-2.4.dist-info}/top_level.txt +0 -0
@@ -31,20 +31,23 @@ 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
- QInputDialog, QMenu, QSizePolicy, QToolButton, QToolTip, QTreeWidget,
39
- QTreeWidgetItem, QVBoxLayout, QWidget
38
+ QInputDialog, QMenu, QSizePolicy, QToolTip, QTreeWidget, QTreeWidgetItem,
39
+ QVBoxLayout, QWidget
40
40
  )
41
41
 
42
42
  from novelwriter import CONFIG, SHARED
43
- from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
44
43
  from novelwriter.common import minmax
45
44
  from novelwriter.constants import nwHeaders, nwKeyWords, nwLabels, trConst
46
45
  from novelwriter.core.index import IndexHeading
46
+ from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
47
+ from novelwriter.extensions.modified import NIconToolButton
47
48
  from novelwriter.extensions.novelselector import NovelSelector
49
+ from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
50
+ from novelwriter.types import QtAlignRight, QtDecoration, QtMouseLeft, QtMouseMiddle, QtUserRole
48
51
 
49
52
  if TYPE_CHECKING: # pragma: no cover
50
53
  from novelwriter.guimain import GuiMain
@@ -198,7 +201,7 @@ class GuiNovelToolBar(QWidget):
198
201
  self.novelView = novelView
199
202
  self.mainGui = novelView.mainGui
200
203
 
201
- iPx = SHARED.theme.baseIconSize
204
+ iSz = SHARED.theme.baseIconSize
202
205
  mPx = CONFIG.pxInt(2)
203
206
 
204
207
  self.setContentsMargins(0, 0, 0, 0)
@@ -215,15 +218,13 @@ class GuiNovelToolBar(QWidget):
215
218
  self.novelValue.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
216
219
  self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
217
220
 
218
- self.tbNovel = QToolButton(self)
221
+ self.tbNovel = NIconToolButton(self, iSz)
219
222
  self.tbNovel.setToolTip(self.tr("Novel Root"))
220
- self.tbNovel.setIconSize(QSize(iPx, iPx))
221
223
  self.tbNovel.clicked.connect(self.novelValue.showPopup)
222
224
 
223
225
  # Refresh Button
224
- self.tbRefresh = QToolButton(self)
226
+ self.tbRefresh = NIconToolButton(self, iSz)
225
227
  self.tbRefresh.setToolTip(self.tr("Refresh"))
226
- self.tbRefresh.setIconSize(QSize(iPx, iPx))
227
228
  self.tbRefresh.clicked.connect(self._refreshNovelTree)
228
229
 
229
230
  # More Options Menu
@@ -241,11 +242,9 @@ 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 = QToolButton(self)
245
+ self.tbMore = NIconToolButton(self, iSz)
245
246
  self.tbMore.setToolTip(self.tr("More Options"))
246
- self.tbMore.setIconSize(QSize(iPx, iPx))
247
247
  self.tbMore.setMenu(self.mMore)
248
- self.tbMore.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
249
248
 
250
249
  # Assemble
251
250
  self.outerBox = QHBoxLayout()
@@ -271,25 +270,19 @@ class GuiNovelToolBar(QWidget):
271
270
  def updateTheme(self) -> None:
272
271
  """Update theme elements."""
273
272
  # Icons
274
- self.tbNovel.setIcon(SHARED.theme.getIcon("cls_novel"))
275
- self.tbRefresh.setIcon(SHARED.theme.getIcon("refresh"))
276
- self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
273
+ self.tbNovel.setThemeIcon("cls_novel")
274
+ self.tbRefresh.setThemeIcon("refresh")
275
+ self.tbMore.setThemeIcon("menu")
277
276
 
278
277
  qPalette = self.palette()
279
278
  qPalette.setBrush(QPalette.ColorRole.Window, qPalette.base())
280
279
  self.setPalette(qPalette)
281
280
 
282
281
  # StyleSheets
283
- fadeCol = qPalette.text().color()
284
- buttonStyle = (
285
- "QToolButton {{padding: {0}px; border: none; background: transparent;}} "
286
- "QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
287
- ).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue())
288
- buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}"
289
-
282
+ buttonStyle = SHARED.theme.getStyleSheet(STYLES_MIN_TOOLBUTTON)
290
283
  self.tbNovel.setStyleSheet(buttonStyle)
291
284
  self.tbRefresh.setStyleSheet(buttonStyle)
292
- self.tbMore.setStyleSheet(buttonStyleMenu)
285
+ self.tbMore.setStyleSheet(buttonStyle)
293
286
 
294
287
  self.novelValue.setStyleSheet(
295
288
  "QComboBox {border-style: none; padding-left: 0;} "
@@ -351,7 +344,7 @@ class GuiNovelToolBar(QWidget):
351
344
  # Internal Functions
352
345
  ##
353
346
 
354
- def _addLastColAction(self, colType, actionLabel) -> None:
347
+ def _addLastColAction(self, colType: NovelTreeColumn, actionLabel: str) -> None:
355
348
  """Add a column selection entry to the last column menu."""
356
349
  aLast = self.mLastCol.addAction(actionLabel)
357
350
  aLast.setCheckable(True)
@@ -371,10 +364,10 @@ class GuiNovelTree(QTreeWidget):
371
364
  C_EXTRA = 2
372
365
  C_MORE = 3
373
366
 
374
- D_HANDLE = Qt.ItemDataRole.UserRole
375
- D_TITLE = Qt.ItemDataRole.UserRole + 1
376
- D_KEY = Qt.ItemDataRole.UserRole + 2
377
- 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
378
371
 
379
372
  def __init__(self, novelView: GuiNovelView) -> None:
380
373
  super().__init__(parent=novelView)
@@ -399,10 +392,11 @@ class GuiNovelTree(QTreeWidget):
399
392
  # Build GUI
400
393
  # =========
401
394
 
402
- iPx = SHARED.theme.baseIconSize
395
+ iPx = SHARED.theme.baseIconHeight
396
+ iSz = SHARED.theme.baseIconSize
403
397
  cMg = CONFIG.pxInt(6)
404
398
 
405
- self.setIconSize(QSize(iPx, iPx))
399
+ self.setIconSize(iSz)
406
400
  self.setFrameStyle(QFrame.Shape.NoFrame)
407
401
  self.setUniformRowHeights(True)
408
402
  self.setAllColumnsShowFocus(True)
@@ -463,7 +457,7 @@ class GuiNovelTree(QTreeWidget):
463
457
 
464
458
  def updateTheme(self) -> None:
465
459
  """Update theme elements."""
466
- iPx = SHARED.theme.baseIconSize
460
+ iPx = SHARED.theme.baseIconHeight
467
461
  self._pMore = SHARED.theme.loadDecoration("deco_doc_more", h=iPx)
468
462
  return
469
463
 
@@ -589,12 +583,12 @@ class GuiNovelTree(QTreeWidget):
589
583
  """
590
584
  super().mousePressEvent(event)
591
585
 
592
- if event.button() == Qt.MouseButton.LeftButton:
586
+ if event.button() == QtMouseLeft:
593
587
  selItem = self.indexAt(event.pos())
594
588
  if not selItem.isValid():
595
589
  self.clearSelection()
596
590
 
597
- elif event.button() == Qt.MouseButton.MiddleButton:
591
+ elif event.button() == QtMouseMiddle:
598
592
  selItem = self.itemAt(event.pos())
599
593
  if not isinstance(selItem, QTreeWidgetItem):
600
594
  return
@@ -684,7 +678,7 @@ class GuiNovelTree(QTreeWidget):
684
678
  newItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
685
679
  newItem.setData(self.C_DATA, self.D_TITLE, sTitle)
686
680
  newItem.setData(self.C_DATA, self.D_KEY, tKey)
687
- newItem.setTextAlignment(self.C_WORDS, Qt.AlignmentFlag.AlignRight)
681
+ newItem.setTextAlignment(self.C_WORDS, QtAlignRight)
688
682
 
689
683
  self._updateTreeItemValues(newItem, novIdx, tHandle, sTitle)
690
684
  self._treeMap[tKey] = newItem
@@ -703,11 +697,11 @@ class GuiNovelTree(QTreeWidget):
703
697
  iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
704
698
  hDec = SHARED.theme.getHeaderDecoration(iLevel)
705
699
 
706
- trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
700
+ trItem.setData(self.C_TITLE, QtDecoration, hDec)
707
701
  trItem.setText(self.C_TITLE, idxItem.title)
708
702
  trItem.setFont(self.C_TITLE, self._hFonts[iLevel])
709
703
  trItem.setText(self.C_WORDS, f"{idxItem.wordCount:n}")
710
- trItem.setData(self.C_MORE, Qt.ItemDataRole.DecorationRole, self._pMore)
704
+ trItem.setData(self.C_MORE, QtDecoration, self._pMore)
711
705
 
712
706
  # Custom column
713
707
  mW = int(self._lastColSize * self.viewport().width())
@@ -750,7 +744,7 @@ class GuiNovelTree(QTreeWidget):
750
744
  logger.debug("Generating meta data tooltip for '%s:%s'", tHandle, sTitle)
751
745
 
752
746
  pIndex = SHARED.project.index
753
- novIdx = pIndex.getItemHeader(tHandle, sTitle)
747
+ novIdx = pIndex.getItemHeading(tHandle, sTitle)
754
748
  refTags = pIndex.getReferences(tHandle, sTitle)
755
749
  if not novIdx:
756
750
  return
@@ -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]))
@@ -798,13 +800,19 @@ class GuiOutlineDetails(QScrollArea):
798
800
  hSpace = int(CONFIG.pxInt(10))
799
801
  vSpace = int(CONFIG.pxInt(4))
800
802
 
803
+ bFont = SHARED.theme.guiFontB
804
+
801
805
  # Details Area
802
- self.titleLabel = QLabel("<b>%s</b>" % self.tr("Title"))
803
- self.fileLabel = QLabel("<b>%s</b>" % self.tr("Document"))
804
- self.itemLabel = QLabel("<b>%s</b>" % self.tr("Status"))
805
- self.titleValue = QLabel("")
806
- self.fileValue = QLabel("")
807
- 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)
812
+
813
+ self.titleLabel.setFont(bFont)
814
+ self.fileLabel.setFont(bFont)
815
+ self.itemLabel.setFont(bFont)
808
816
 
809
817
  self.titleValue.setMinimumWidth(minTitle)
810
818
  self.titleValue.setMaximumWidth(maxTitle)
@@ -814,38 +822,55 @@ class GuiOutlineDetails(QScrollArea):
814
822
  self.itemValue.setMaximumWidth(maxTitle)
815
823
 
816
824
  # Stats Area
817
- self.cCLabel = QLabel("<b>%s</b>" % self.tr("Characters"))
818
- self.wCLabel = QLabel("<b>%s</b>" % self.tr("Words"))
819
- self.pCLabel = QLabel("<b>%s</b>" % self.tr("Paragraphs"))
820
- self.cCValue = QLabel("")
821
- self.wCValue = QLabel("")
822
- 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)
831
+
832
+ self.cCLabel.setFont(bFont)
833
+ self.wCLabel.setFont(bFont)
834
+ self.pCLabel.setFont(bFont)
823
835
 
824
836
  self.cCValue.setMinimumWidth(wCount)
825
837
  self.wCValue.setMinimumWidth(wCount)
826
838
  self.pCValue.setMinimumWidth(wCount)
827
- self.cCValue.setAlignment(Qt.AlignRight)
828
- self.wCValue.setAlignment(Qt.AlignRight)
829
- self.pCValue.setAlignment(Qt.AlignRight)
839
+ self.cCValue.setAlignment(QtAlignRight)
840
+ self.wCValue.setAlignment(QtAlignRight)
841
+ self.pCValue.setAlignment(QtAlignRight)
830
842
 
831
843
  # Synopsis
832
- self.synopLabel = QLabel("<b>%s</b>" % self.tr("Synopsis"))
833
- self.synopValue = QLabel("")
834
- self.synopLWrap = QHBoxLayout()
844
+ self.synopLabel = QLabel(self.tr("Synopsis"), self)
845
+ self.synopLabel.setFont(bFont)
846
+
847
+ self.synopValue = QLabel("", self)
835
848
  self.synopValue.setWordWrap(True)
836
- self.synopValue.setAlignment(Qt.AlignTop | Qt.AlignLeft)
849
+ self.synopValue.setAlignment(QtAlignLeftTop)
850
+
851
+ self.synopLWrap = QHBoxLayout()
837
852
  self.synopLWrap.addWidget(self.synopValue, 1)
838
853
 
839
854
  # Tags
840
- self.povKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.POV_KEY]))
841
- self.focKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.FOCUS_KEY]))
842
- self.chrKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY]))
843
- self.pltKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY]))
844
- self.timKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.TIME_KEY]))
845
- self.wldKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY]))
846
- self.objKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY]))
847
- self.entKeyLabel = QLabel("<b>%s</b>" % trConst(nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY]))
848
- self.cstKeyLabel = QLabel("<b>%s</b>" % 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)
864
+
865
+ self.povKeyLabel.setFont(bFont)
866
+ self.focKeyLabel.setFont(bFont)
867
+ self.chrKeyLabel.setFont(bFont)
868
+ self.pltKeyLabel.setFont(bFont)
869
+ self.timKeyLabel.setFont(bFont)
870
+ self.wldKeyLabel.setFont(bFont)
871
+ self.objKeyLabel.setFont(bFont)
872
+ self.entKeyLabel.setFont(bFont)
873
+ self.cstKeyLabel.setFont(bFont)
849
874
 
850
875
  self.povKeyLWrap = QHBoxLayout()
851
876
  self.focKeyLWrap = QHBoxLayout()
@@ -857,15 +882,15 @@ class GuiOutlineDetails(QScrollArea):
857
882
  self.entKeyLWrap = QHBoxLayout()
858
883
  self.cstKeyLWrap = QHBoxLayout()
859
884
 
860
- self.povKeyValue = QLabel("")
861
- self.focKeyValue = QLabel("")
862
- self.chrKeyValue = QLabel("")
863
- self.pltKeyValue = QLabel("")
864
- self.timKeyValue = QLabel("")
865
- self.wldKeyValue = QLabel("")
866
- self.objKeyValue = QLabel("")
867
- self.entKeyValue = QLabel("")
868
- 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)
869
894
 
870
895
  self.povKeyValue.setWordWrap(True)
871
896
  self.focKeyValue.setWordWrap(True)
@@ -902,23 +927,20 @@ class GuiOutlineDetails(QScrollArea):
902
927
  self.mainForm = QGridLayout()
903
928
  self.mainGroup.setLayout(self.mainForm)
904
929
 
905
- topLeft = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignLeft
906
- topRight = Qt.AlignmentFlag.AlignTop | Qt.AlignmentFlag.AlignRight
907
-
908
- self.mainForm.addWidget(self.titleLabel, 0, 0, 1, 1, topLeft)
909
- self.mainForm.addWidget(self.titleValue, 0, 1, 1, 1, topLeft)
910
- self.mainForm.addWidget(self.cCLabel, 0, 2, 1, 1, topLeft)
911
- self.mainForm.addWidget(self.cCValue, 0, 3, 1, 1, topRight)
912
- self.mainForm.addWidget(self.fileLabel, 1, 0, 1, 1, topLeft)
913
- self.mainForm.addWidget(self.fileValue, 1, 1, 1, 1, topLeft)
914
- self.mainForm.addWidget(self.wCLabel, 1, 2, 1, 1, topLeft)
915
- self.mainForm.addWidget(self.wCValue, 1, 3, 1, 1, topRight)
916
- self.mainForm.addWidget(self.itemLabel, 2, 0, 1, 1, topLeft)
917
- self.mainForm.addWidget(self.itemValue, 2, 1, 1, 1, topLeft)
918
- self.mainForm.addWidget(self.pCLabel, 2, 2, 1, 1, topLeft)
919
- self.mainForm.addWidget(self.pCValue, 2, 3, 1, 1, topRight)
920
- self.mainForm.addWidget(self.synopLabel, 3, 0, 1, 4, topLeft)
921
- 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)
922
944
 
923
945
  self.mainForm.setColumnStretch(1, 1)
924
946
  self.mainForm.setRowStretch(4, 1)
@@ -930,24 +952,24 @@ class GuiOutlineDetails(QScrollArea):
930
952
  self.tagsForm = QGridLayout()
931
953
  self.tagsGroup.setLayout(self.tagsForm)
932
954
 
933
- self.tagsForm.addWidget(self.povKeyLabel, 0, 0, 1, 1, topLeft)
934
- self.tagsForm.addLayout(self.povKeyLWrap, 0, 1, 1, 1, topLeft)
935
- self.tagsForm.addWidget(self.focKeyLabel, 1, 0, 1, 1, topLeft)
936
- self.tagsForm.addLayout(self.focKeyLWrap, 1, 1, 1, 1, topLeft)
937
- self.tagsForm.addWidget(self.chrKeyLabel, 2, 0, 1, 1, topLeft)
938
- self.tagsForm.addLayout(self.chrKeyLWrap, 2, 1, 1, 1, topLeft)
939
- self.tagsForm.addWidget(self.pltKeyLabel, 3, 0, 1, 1, topLeft)
940
- self.tagsForm.addLayout(self.pltKeyLWrap, 3, 1, 1, 1, topLeft)
941
- self.tagsForm.addWidget(self.timKeyLabel, 4, 0, 1, 1, topLeft)
942
- self.tagsForm.addLayout(self.timKeyLWrap, 4, 1, 1, 1, topLeft)
943
- self.tagsForm.addWidget(self.wldKeyLabel, 5, 0, 1, 1, topLeft)
944
- self.tagsForm.addLayout(self.wldKeyLWrap, 5, 1, 1, 1, topLeft)
945
- self.tagsForm.addWidget(self.objKeyLabel, 6, 0, 1, 1, topLeft)
946
- self.tagsForm.addLayout(self.objKeyLWrap, 6, 1, 1, 1, topLeft)
947
- self.tagsForm.addWidget(self.entKeyLabel, 7, 0, 1, 1, topLeft)
948
- self.tagsForm.addLayout(self.entKeyLWrap, 7, 1, 1, 1, topLeft)
949
- self.tagsForm.addWidget(self.cstKeyLabel, 8, 0, 1, 1, topLeft)
950
- 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)
951
973
 
952
974
  self.tagsForm.setColumnStretch(1, 1)
953
975
  self.tagsForm.setRowStretch(8, 1)
@@ -955,7 +977,7 @@ class GuiOutlineDetails(QScrollArea):
955
977
  self.tagsForm.setVerticalSpacing(vSpace)
956
978
 
957
979
  # Assemble
958
- self.outerWidget = QWidget()
980
+ self.outerWidget = QWidget(self)
959
981
  self.outerBox = QHBoxLayout()
960
982
  self.outerBox.addWidget(self.mainGroup, 0)
961
983
  self.outerBox.addWidget(self.tagsGroup, 1)
@@ -989,7 +1011,7 @@ class GuiOutlineDetails(QScrollArea):
989
1011
 
990
1012
  def clearDetails(self) -> None:
991
1013
  """Clear all the data labels."""
992
- self.titleLabel.setText("<b>%s</b>" % self.tr("Title"))
1014
+ self.titleLabel.setText(self.tr("Title"))
993
1015
  self.titleValue.setText("")
994
1016
  self.fileValue.setText("")
995
1017
  self.itemValue.setText("")
@@ -1020,10 +1042,10 @@ class GuiOutlineDetails(QScrollArea):
1020
1042
  """
1021
1043
  pIndex = SHARED.project.index
1022
1044
  nwItem = SHARED.project.tree[tHandle]
1023
- novIdx = pIndex.getItemHeader(tHandle, sTitle)
1045
+ novIdx = pIndex.getItemHeading(tHandle, sTitle)
1024
1046
  novRefs = pIndex.getReferences(tHandle, sTitle)
1025
1047
  if nwItem and novIdx:
1026
- self.titleLabel.setText("<b>%s</b>" % self.tr(self.LVL_MAP.get(novIdx.level, "H1")))
1048
+ self.titleLabel.setText(self.tr(self.LVL_MAP.get(novIdx.level, "H1")))
1027
1049
  self.titleValue.setText(novIdx.title)
1028
1050
 
1029
1051
  itemStatus, _ = nwItem.getImportStatus(incIcon=False)