novelWriter 2.4.3__py3-none-any.whl → 2.5__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 (123) hide show
  1. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/METADATA +4 -5
  2. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/RECORD +122 -112
  3. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/WHEEL +1 -1
  4. novelwriter/__init__.py +33 -39
  5. novelwriter/assets/i18n/nw_de_DE.qm +0 -0
  6. novelwriter/assets/i18n/nw_en_US.qm +0 -0
  7. novelwriter/assets/i18n/nw_es_419.qm +0 -0
  8. novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
  9. novelwriter/assets/i18n/nw_it_IT.qm +0 -0
  10. novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
  11. novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
  12. novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
  13. novelwriter/assets/i18n/nw_pl_PL.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_en_GB.json +1 -0
  17. novelwriter/assets/i18n/project_pl_PL.json +116 -0
  18. novelwriter/assets/i18n/project_pt_BR.json +74 -74
  19. novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
  20. novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
  21. novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
  22. novelwriter/assets/icons/typicons_light/icons.conf +2 -0
  23. novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
  24. novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
  25. novelwriter/assets/manual.pdf +0 -0
  26. novelwriter/assets/sample.zip +0 -0
  27. novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
  28. novelwriter/assets/syntax/default_dark.conf +32 -18
  29. novelwriter/assets/syntax/default_light.conf +24 -10
  30. novelwriter/assets/syntax/dracula.conf +44 -0
  31. novelwriter/assets/syntax/grey_dark.conf +5 -4
  32. novelwriter/assets/syntax/grey_light.conf +5 -4
  33. novelwriter/assets/syntax/light_owl.conf +7 -6
  34. novelwriter/assets/syntax/night_owl.conf +7 -6
  35. novelwriter/assets/syntax/snazzy.conf +42 -0
  36. novelwriter/assets/syntax/solarized_dark.conf +4 -3
  37. novelwriter/assets/syntax/solarized_light.conf +4 -3
  38. novelwriter/assets/syntax/tango.conf +27 -11
  39. novelwriter/assets/syntax/tomorrow.conf +6 -5
  40. novelwriter/assets/syntax/tomorrow_night.conf +7 -6
  41. novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
  42. novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
  43. novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
  44. novelwriter/assets/text/credits_en.htm +52 -41
  45. novelwriter/assets/themes/cyberpunk_night.conf +3 -0
  46. novelwriter/assets/themes/default_dark.conf +2 -0
  47. novelwriter/assets/themes/default_light.conf +2 -0
  48. novelwriter/assets/themes/dracula.conf +48 -0
  49. novelwriter/assets/themes/solarized_dark.conf +2 -0
  50. novelwriter/assets/themes/solarized_light.conf +2 -0
  51. novelwriter/common.py +33 -12
  52. novelwriter/config.py +184 -98
  53. novelwriter/constants.py +47 -35
  54. novelwriter/core/buildsettings.py +68 -69
  55. novelwriter/core/coretools.py +5 -23
  56. novelwriter/core/docbuild.py +52 -40
  57. novelwriter/core/document.py +3 -5
  58. novelwriter/core/index.py +115 -45
  59. novelwriter/core/item.py +8 -19
  60. novelwriter/core/options.py +2 -4
  61. novelwriter/core/project.py +37 -61
  62. novelwriter/core/projectdata.py +1 -3
  63. novelwriter/core/projectxml.py +12 -15
  64. novelwriter/core/sessions.py +3 -5
  65. novelwriter/core/spellcheck.py +4 -9
  66. novelwriter/core/status.py +211 -164
  67. novelwriter/core/storage.py +0 -8
  68. novelwriter/core/tohtml.py +139 -105
  69. novelwriter/core/tokenizer.py +278 -122
  70. novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
  71. novelwriter/core/toodt.py +257 -166
  72. novelwriter/core/toqdoc.py +419 -0
  73. novelwriter/core/tree.py +5 -7
  74. novelwriter/dialogs/about.py +11 -18
  75. novelwriter/dialogs/docmerge.py +17 -19
  76. novelwriter/dialogs/docsplit.py +17 -19
  77. novelwriter/dialogs/editlabel.py +6 -10
  78. novelwriter/dialogs/preferences.py +200 -164
  79. novelwriter/dialogs/projectsettings.py +225 -189
  80. novelwriter/dialogs/quotes.py +12 -9
  81. novelwriter/dialogs/wordlist.py +9 -15
  82. novelwriter/enum.py +35 -30
  83. novelwriter/error.py +8 -15
  84. novelwriter/extensions/configlayout.py +55 -21
  85. novelwriter/extensions/eventfilters.py +1 -5
  86. novelwriter/extensions/modified.py +70 -14
  87. novelwriter/extensions/novelselector.py +1 -3
  88. novelwriter/extensions/pagedsidebar.py +9 -12
  89. novelwriter/extensions/{circularprogress.py → progressbars.py} +30 -8
  90. novelwriter/extensions/statusled.py +40 -26
  91. novelwriter/extensions/switch.py +4 -6
  92. novelwriter/extensions/switchbox.py +7 -6
  93. novelwriter/extensions/versioninfo.py +3 -9
  94. novelwriter/gui/doceditor.py +120 -139
  95. novelwriter/gui/dochighlight.py +231 -186
  96. novelwriter/gui/docviewer.py +69 -108
  97. novelwriter/gui/docviewerpanel.py +3 -10
  98. novelwriter/gui/editordocument.py +1 -3
  99. novelwriter/gui/itemdetails.py +7 -11
  100. novelwriter/gui/mainmenu.py +22 -18
  101. novelwriter/gui/noveltree.py +11 -24
  102. novelwriter/gui/outline.py +15 -26
  103. novelwriter/gui/projtree.py +39 -65
  104. novelwriter/gui/search.py +10 -3
  105. novelwriter/gui/sidebar.py +2 -6
  106. novelwriter/gui/statusbar.py +29 -37
  107. novelwriter/gui/theme.py +26 -48
  108. novelwriter/guimain.py +162 -160
  109. novelwriter/shared.py +36 -19
  110. novelwriter/text/patterns.py +113 -0
  111. novelwriter/tools/dictionaries.py +10 -20
  112. novelwriter/tools/lipsum.py +10 -16
  113. novelwriter/tools/manusbuild.py +9 -11
  114. novelwriter/tools/manuscript.py +75 -149
  115. novelwriter/tools/manussettings.py +74 -76
  116. novelwriter/tools/noveldetails.py +16 -21
  117. novelwriter/tools/welcome.py +21 -26
  118. novelwriter/tools/writingstats.py +9 -12
  119. novelwriter/types.py +49 -4
  120. novelwriter/extensions/simpleprogress.py +0 -55
  121. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/LICENSE.md +0 -0
  122. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/entry_points.txt +0 -0
  123. {novelWriter-2.4.3.dist-info → novelWriter-2.5.dist-info}/top_level.txt +0 -0
@@ -36,11 +36,10 @@ import logging
36
36
 
37
37
  from enum import Enum
38
38
  from time import time
39
- from typing import TYPE_CHECKING
40
39
 
41
40
  from PyQt5.QtCore import (
42
- QObject, QPoint, QRegExp, QRegularExpression, QRunnable, Qt, QTimer,
43
- pyqtSignal, pyqtSlot
41
+ QObject, QPoint, QRegularExpression, QRunnable, Qt, QTimer, pyqtSignal,
42
+ pyqtSlot
44
43
  )
45
44
  from PyQt5.QtGui import (
46
45
  QColor, QCursor, QKeyEvent, QKeySequence, QMouseEvent, QPalette, QPixmap,
@@ -55,7 +54,8 @@ from novelwriter import CONFIG, SHARED
55
54
  from novelwriter.common import minmax, transferCase
56
55
  from novelwriter.constants import nwConst, nwKeyWords, nwShortcode, nwUnicode
57
56
  from novelwriter.core.document import NWDocument
58
- from novelwriter.enum import nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwTrinary
57
+ from novelwriter.enum import nwComment, nwDocAction, nwDocInsert, nwDocMode, nwItemClass, nwTrinary
58
+ from novelwriter.extensions.configlayout import NColourLabel
59
59
  from novelwriter.extensions.eventfilters import WheelEventFilter
60
60
  from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton
61
61
  from novelwriter.gui.dochighlight import BLOCK_META, BLOCK_TITLE
@@ -65,13 +65,10 @@ from novelwriter.text.counting import standardCounter
65
65
  from novelwriter.tools.lipsum import GuiLipsum
66
66
  from novelwriter.types import (
67
67
  QtAlignCenterTop, QtAlignJustify, QtAlignLeft, QtAlignLeftTop,
68
- QtAlignRight, QtKeepAnchor, QtModCtrl, QtModeNone, QtModShift, QtMouseLeft,
68
+ QtAlignRight, QtKeepAnchor, QtModCtrl, QtModNone, QtModShift, QtMouseLeft,
69
69
  QtMoveAnchor, QtMoveLeft, QtMoveRight
70
70
  )
71
71
 
72
- if TYPE_CHECKING: # pragma: no cover
73
- from novelwriter.guimain import GuiMain
74
-
75
72
  logger = logging.getLogger(__name__)
76
73
 
77
74
 
@@ -82,8 +79,6 @@ class _SelectAction(Enum):
82
79
  KEEP_POSITION = 2
83
80
  MOVE_AFTER = 3
84
81
 
85
- # END Class _SelectAction
86
-
87
82
 
88
83
  class GuiDocEditor(QPlainTextEdit):
89
84
  """Gui Widget: Main Document Editor"""
@@ -107,15 +102,14 @@ class GuiDocEditor(QPlainTextEdit):
107
102
  requestProjectItemSelected = pyqtSignal(str, bool)
108
103
  requestProjectItemRenamed = pyqtSignal(str, str)
109
104
  requestNewNoteCreation = pyqtSignal(str, nwItemClass)
105
+ requestNextDocument = pyqtSignal(str, bool)
110
106
 
111
- def __init__(self, mainGui: GuiMain) -> None:
112
- super().__init__(parent=mainGui)
107
+ def __init__(self, parent: QWidget) -> None:
108
+ super().__init__(parent=parent)
113
109
 
114
110
  logger.debug("Create: GuiDocEditor")
115
111
 
116
112
  # Class Variables
117
- self.mainGui = mainGui
118
-
119
113
  self._nwDocument = None
120
114
  self._nwItem = None
121
115
 
@@ -217,6 +211,7 @@ class GuiDocEditor(QPlainTextEdit):
217
211
  # Function Mapping
218
212
  self.closeSearch = self.docSearch.closeSearch
219
213
  self.searchVisible = self.docSearch.isVisible
214
+ self.changeFocusState = self.docHeader.changeFocusState
220
215
 
221
216
  # Finalise
222
217
  self.updateSyntaxColours()
@@ -328,8 +323,11 @@ class GuiDocEditor(QPlainTextEdit):
328
323
  # Reload spell check and dictionaries
329
324
  SHARED.updateSpellCheckLanguage()
330
325
 
331
- # Set font
332
- self.initFont()
326
+ # Set the font. See issues #1862 and #1875.
327
+ self.setFont(CONFIG.textFont)
328
+ self.docHeader.updateFont()
329
+ self.docFooter.updateFont()
330
+ self.docSearch.updateFont()
333
331
 
334
332
  # Update highlighter settings
335
333
  self._qDocument.syntaxHighlighter.initHighlighter()
@@ -379,23 +377,6 @@ class GuiDocEditor(QPlainTextEdit):
379
377
 
380
378
  return
381
379
 
382
- def initFont(self) -> None:
383
- """Set the font of the main widget and sub-widgets. This needs
384
- special attention since there appears to be a bug in Qt 5.15.3.
385
- See issues #1862 and #1875.
386
- """
387
- font = self.font()
388
- font.setFamily(CONFIG.textFont)
389
- font.setPointSize(CONFIG.textSize)
390
- self.setFont(font)
391
-
392
- # Reset sub-widget font to GUI font
393
- self.docHeader.updateFont()
394
- self.docFooter.updateFont()
395
- self.docSearch.updateFont()
396
-
397
- return
398
-
399
380
  def loadText(self, tHandle: str, tLine: int | None = None) -> bool:
400
381
  """Load text from a document into the editor. If we have an I/O
401
382
  error, we must handle this and clear the editor so that we don't
@@ -457,11 +438,6 @@ class GuiDocEditor(QPlainTextEdit):
457
438
 
458
439
  return True
459
440
 
460
- def updateTagHighLighting(self) -> None:
461
- """Rerun the syntax highlighter on all meta data lines."""
462
- self._qDocument.syntaxHighlighter.rehighlightByType(BLOCK_META)
463
- return
464
-
465
441
  def replaceText(self, text: str) -> None:
466
442
  """Replace the text of the current document with the provided
467
443
  text. This also clears undo history.
@@ -492,7 +468,6 @@ class GuiDocEditor(QPlainTextEdit):
492
468
  cC, wC, pC = standardCounter(docText)
493
469
  self._updateDocCounts(cC, wC, pC)
494
470
 
495
- self.saveCursorPosition()
496
471
  if not self._nwDocument.writeDocument(docText):
497
472
  saveOk = False
498
473
  if self._nwDocument.hashError:
@@ -855,14 +830,15 @@ class GuiDocEditor(QPlainTextEdit):
855
830
  )
856
831
  return
857
832
 
858
- def insertText(self, insert: str | nwDocInsert) -> bool:
833
+ def insertText(self, insert: str | nwDocInsert) -> None:
859
834
  """Insert a specific type of text at the cursor position."""
860
835
  if self._docHandle is None:
861
836
  logger.error("No document open")
862
- return False
837
+ return
863
838
 
864
- newBlock = False
865
- goAfter = False
839
+ text = ""
840
+ block = False
841
+ after = False
866
842
 
867
843
  if isinstance(insert, str):
868
844
  text = insert
@@ -877,43 +853,41 @@ class GuiDocEditor(QPlainTextEdit):
877
853
  text = self._typDQuoteC
878
854
  elif insert == nwDocInsert.SYNOPSIS:
879
855
  text = "%Synopsis: "
880
- newBlock = True
881
- goAfter = True
856
+ block = True
857
+ after = True
882
858
  elif insert == nwDocInsert.SHORT:
883
859
  text = "%Short: "
884
- newBlock = True
885
- goAfter = True
860
+ block = True
861
+ after = True
886
862
  elif insert == nwDocInsert.NEW_PAGE:
887
863
  text = "[newpage]"
888
- newBlock = True
889
- goAfter = False
864
+ block = True
865
+ after = False
890
866
  elif insert == nwDocInsert.VSPACE_S:
891
867
  text = "[vspace]"
892
- newBlock = True
893
- goAfter = False
868
+ block = True
869
+ after = False
894
870
  elif insert == nwDocInsert.VSPACE_M:
895
871
  text = "[vspace:2]"
896
- newBlock = True
897
- goAfter = False
872
+ block = True
873
+ after = False
898
874
  elif insert == nwDocInsert.LIPSUM:
899
875
  text = GuiLipsum.getLipsum(self)
900
- newBlock = True
901
- goAfter = False
902
- else:
903
- return False
904
- else:
905
- return False
876
+ block = True
877
+ after = False
878
+ elif insert == nwDocInsert.FOOTNOTE:
879
+ self._insertCommentStructure(nwComment.FOOTNOTE)
906
880
 
907
881
  if text:
908
- if newBlock:
909
- self.insertNewBlock(text, defaultAfter=goAfter)
882
+ if block:
883
+ self.insertNewBlock(text, defaultAfter=after)
910
884
  else:
911
885
  cursor = self.textCursor()
912
886
  cursor.beginEditBlock()
913
887
  cursor.insertText(text)
914
888
  cursor.endEditBlock()
915
889
 
916
- return True
890
+ return
917
891
 
918
892
  def insertNewBlock(self, text: str, defaultAfter: bool = True) -> bool:
919
893
  """Insert a piece of text on a blank line."""
@@ -979,7 +953,7 @@ class GuiDocEditor(QPlainTextEdit):
979
953
  super().keyPressEvent(event)
980
954
  nPos = self.cursorRect().topLeft().y()
981
955
  kMod = event.modifiers()
982
- okMod = kMod in (QtModeNone, QtModShift)
956
+ okMod = kMod in (QtModNone, QtModShift)
983
957
  okKey = event.key() not in self.MOVE_KEYS
984
958
  if nPos != cPos and okMod and okKey:
985
959
  mPos = CONFIG.autoScrollPos*0.01 * self.viewport().height()
@@ -1057,6 +1031,13 @@ class GuiDocEditor(QPlainTextEdit):
1057
1031
  self.beginSearch()
1058
1032
  return
1059
1033
 
1034
+ @pyqtSlot(list, list)
1035
+ def updateChangedTags(self, updated: list[str], deleted: list[str]) -> None:
1036
+ """Tags have changed, so just in case we rehighlight them."""
1037
+ if updated or deleted:
1038
+ self._qDocument.syntaxHighlighter.rehighlightByType(BLOCK_META)
1039
+ return
1040
+
1060
1041
  ##
1061
1042
  # Private Slots
1062
1043
  ##
@@ -1179,7 +1160,8 @@ class GuiDocEditor(QPlainTextEdit):
1179
1160
  lambda _, option=option: self._correctWord(sCursor, option)
1180
1161
  )
1181
1162
  else:
1182
- ctxMenu.addAction("%s %s" % (nwUnicode.U_ENDASH, self.tr("No Suggestions")))
1163
+ trNone = self.tr("No Suggestions")
1164
+ ctxMenu.addAction(f"{nwUnicode.U_ENDASH} {trNone}")
1183
1165
 
1184
1166
  ctxMenu.addSeparator()
1185
1167
  action = ctxMenu.addAction(self.tr("Add Word to Dictionary"))
@@ -1335,9 +1317,8 @@ class GuiDocEditor(QPlainTextEdit):
1335
1317
  self.docSearch.setResultCount(0, 0)
1336
1318
  self._lastFind = None
1337
1319
  if CONFIG.searchNextFile and not goBack:
1338
- self.mainGui.openNextDocument(
1339
- self._docHandle, wrapAround=CONFIG.searchLoop
1340
- )
1320
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
1321
+ QApplication.processEvents()
1341
1322
  self.beginSearch()
1342
1323
  self.setFocus()
1343
1324
  return
@@ -1356,9 +1337,8 @@ class GuiDocEditor(QPlainTextEdit):
1356
1337
 
1357
1338
  if resIdx > maxIdx and self._docHandle:
1358
1339
  if CONFIG.searchNextFile and not goBack:
1359
- self.mainGui.openNextDocument(
1360
- self._docHandle, wrapAround=CONFIG.searchLoop
1361
- )
1340
+ self.requestNextDocument.emit(self._docHandle, CONFIG.searchLoop)
1341
+ QApplication.processEvents()
1362
1342
  self.beginSearch()
1363
1343
  self.setFocus()
1364
1344
  return
@@ -1865,6 +1845,32 @@ class GuiDocEditor(QPlainTextEdit):
1865
1845
 
1866
1846
  return
1867
1847
 
1848
+ def _insertCommentStructure(self, style: nwComment) -> None:
1849
+ """Insert a shortcut/comment combo."""
1850
+ if self._docHandle and style == nwComment.FOOTNOTE:
1851
+ self.saveText() # Index must be up to date
1852
+ key = SHARED.project.index.newCommentKey(self._docHandle, style)
1853
+ code = nwShortcode.COMMENT_STYLES[nwComment.FOOTNOTE]
1854
+
1855
+ cursor = self.textCursor()
1856
+ block = cursor.block()
1857
+ text = block.text().rstrip()
1858
+ if not text or text.startswith("@"):
1859
+ logger.error("Invalid footnote location")
1860
+ return
1861
+
1862
+ cursor.beginEditBlock()
1863
+ cursor.insertText(code.format(key))
1864
+ cursor.setPosition(block.position() + block.length() - 1)
1865
+ cursor.insertBlock()
1866
+ cursor.insertBlock()
1867
+ cursor.insertText(f"%Footnote.{key}: ")
1868
+ cursor.endEditBlock()
1869
+
1870
+ self.setTextCursor(cursor)
1871
+
1872
+ return
1873
+
1868
1874
  ##
1869
1875
  # Internal Functions
1870
1876
  ##
@@ -1920,8 +1926,6 @@ class GuiDocEditor(QPlainTextEdit):
1920
1926
  ).format(tag)):
1921
1927
  itemClass = nwKeyWords.KEY_CLASS.get(tBits[0], nwItemClass.NO_CLASS)
1922
1928
  self.requestNewNoteCreation.emit(tag, itemClass)
1923
- QApplication.processEvents()
1924
- self._qDocument.syntaxHighlighter.rehighlightBlock(block)
1925
1929
 
1926
1930
  return nwTrinary.POSITIVE if exist else nwTrinary.NEGATIVE
1927
1931
 
@@ -2028,6 +2032,9 @@ class GuiDocEditor(QPlainTextEdit):
2028
2032
  cursor.movePosition(QtMoveLeft, QtKeepAnchor, nDelete)
2029
2033
  cursor.insertText(tInsert)
2030
2034
 
2035
+ # Re-highlight, since the auto-replace sometimes interferes with it
2036
+ self._qDocument.syntaxHighlighter.rehighlightBlock(cursor.block())
2037
+
2031
2038
  return
2032
2039
 
2033
2040
  @staticmethod
@@ -2128,8 +2135,6 @@ class GuiDocEditor(QPlainTextEdit):
2128
2135
  self._doReplace = False
2129
2136
  return
2130
2137
 
2131
- # END Class GuiDocEditor
2132
-
2133
2138
 
2134
2139
  class MetaCompleter(QMenu):
2135
2140
  """GuiWidget: Meta Completer Menu
@@ -2207,15 +2212,13 @@ class MetaCompleter(QMenu):
2207
2212
  self.complete.emit(pos, length, value)
2208
2213
  return
2209
2214
 
2210
- # END Class MetaCompleter
2211
-
2212
-
2213
- # =============================================================================================== #
2214
- # The Off-GUI Thread Word Counter
2215
- # A runnable for the word counter to be run in the thread pool off the main GUI thread.
2216
- # =============================================================================================== #
2217
2215
 
2218
2216
  class BackgroundWordCounter(QRunnable):
2217
+ """The Off-GUI Thread Word Counter
2218
+
2219
+ A runnable for the word counter to be run in the thread pool off the
2220
+ main GUI thread.
2221
+ """
2219
2222
 
2220
2223
  def __init__(self, docEditor: GuiDocEditor, forSelection: bool = False) -> None:
2221
2224
  super().__init__()
@@ -2248,8 +2251,6 @@ class BackgroundWordCounter(QRunnable):
2248
2251
 
2249
2252
  return
2250
2253
 
2251
- # END Class BackgroundWordCounter
2252
-
2253
2254
 
2254
2255
  class BackgroundWordCounterSignals(QObject):
2255
2256
  """The QRunnable cannot emit a signal, so we need a simple QObject
@@ -2257,15 +2258,13 @@ class BackgroundWordCounterSignals(QObject):
2257
2258
  """
2258
2259
  countsReady = pyqtSignal(int, int, int)
2259
2260
 
2260
- # END Class BackgroundWordCounterSignals
2261
-
2262
-
2263
- # =============================================================================================== #
2264
- # The Formatting and Options Fold Out Menu
2265
- # Only used by DocEditor, and is opened by the first button in the header
2266
- # =============================================================================================== #
2267
2261
 
2268
2262
  class GuiDocToolBar(QWidget):
2263
+ """The Formatting and Options Fold Out Menu
2264
+
2265
+ Only used by DocEditor, and is opened by the first button in the
2266
+ header.
2267
+ """
2269
2268
 
2270
2269
  requestDocAction = pyqtSignal(nwDocAction)
2271
2270
 
@@ -2390,15 +2389,13 @@ class GuiDocToolBar(QWidget):
2390
2389
 
2391
2390
  return
2392
2391
 
2393
- # END Class GuiDocToolBar
2394
-
2395
-
2396
- # =============================================================================================== #
2397
- # The Embedded Document Search/Replace Feature
2398
- # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
2399
- # =============================================================================================== #
2400
2392
 
2401
2393
  class GuiDocEditSearch(QFrame):
2394
+ """The Embedded Document Search/Replace Feature
2395
+
2396
+ Only used by DocEditor, and is at a fixed position in the
2397
+ QTextEdit's viewport.
2398
+ """
2402
2399
 
2403
2400
  def __init__(self, docEditor: GuiDocEditor) -> None:
2404
2401
  super().__init__(parent=docEditor)
@@ -2546,32 +2543,18 @@ class GuiDocEditSearch(QFrame):
2546
2543
  # Getters
2547
2544
  ##
2548
2545
 
2549
- def getSearchObject(self) -> str | QRegularExpression | QRegExp:
2546
+ def getSearchObject(self) -> str | QRegularExpression:
2550
2547
  """Return the current search text either as text or as a regular
2551
2548
  expression object.
2552
2549
  """
2553
2550
  text = self.searchBox.text()
2554
2551
  if CONFIG.searchRegEx:
2555
- # Using the Unicode-capable QRegularExpression class was
2556
- # only added in Qt 5.13. Otherwise, 5.3 and up supports
2557
- # only the QRegExp class.
2558
- if CONFIG.verQtValue >= 0x050d00:
2559
- rxOpt = QRegularExpression.PatternOption.UseUnicodePropertiesOption
2560
- if not CONFIG.searchCase:
2561
- rxOpt |= QRegularExpression.PatternOption.CaseInsensitiveOption
2562
- regEx = QRegularExpression(text, rxOpt)
2563
- self._alertSearchValid(regEx.isValid())
2564
- return regEx
2565
- else: # pragma: no cover
2566
- # >= 50300 to < 51300
2567
- if CONFIG.searchCase:
2568
- rxOpt = Qt.CaseSensitivity.CaseSensitive
2569
- else:
2570
- rxOpt = Qt.CaseSensitivity.CaseInsensitive
2571
- regEx = QRegExp(text, rxOpt)
2572
- self._alertSearchValid(regEx.isValid())
2573
- return regEx
2574
-
2552
+ rxOpt = QRegularExpression.PatternOption.UseUnicodePropertiesOption
2553
+ if not CONFIG.searchCase:
2554
+ rxOpt |= QRegularExpression.PatternOption.CaseInsensitiveOption
2555
+ regEx = QRegularExpression(text, rxOpt)
2556
+ self._alertSearchValid(regEx.isValid())
2557
+ return regEx
2575
2558
  return text
2576
2559
 
2577
2560
  ##
@@ -2775,15 +2758,13 @@ class GuiDocEditSearch(QFrame):
2775
2758
  self.searchBox.setPalette(qPalette)
2776
2759
  return
2777
2760
 
2778
- # END Class GuiDocEditSearch
2779
-
2780
-
2781
- # =============================================================================================== #
2782
- # The Embedded Document Header
2783
- # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
2784
- # =============================================================================================== #
2785
2761
 
2786
2762
  class GuiDocEditHeader(QWidget):
2763
+ """The Embedded Document Header
2764
+
2765
+ Only used by DocEditor, and is at a fixed position in the
2766
+ QTextEdit's viewport.
2767
+ """
2787
2768
 
2788
2769
  closeDocumentRequest = pyqtSignal()
2789
2770
  toggleToolBarRequest = pyqtSignal()
@@ -2806,8 +2787,7 @@ class GuiDocEditHeader(QWidget):
2806
2787
  self.setAutoFillBackground(True)
2807
2788
 
2808
2789
  # Title Label
2809
- self.itemTitle = QLabel("", self)
2810
- self.itemTitle.setIndent(0)
2790
+ self.itemTitle = NColourLabel("", self, faded=SHARED.theme.fadedText)
2811
2791
  self.itemTitle.setMargin(0)
2812
2792
  self.itemTitle.setContentsMargins(0, 0, 0, 0)
2813
2793
  self.itemTitle.setAutoFillBackground(True)
@@ -2939,10 +2919,15 @@ class GuiDocEditHeader(QWidget):
2939
2919
  palette.setColor(QPalette.ColorRole.Window, SHARED.theme.colBack)
2940
2920
  palette.setColor(QPalette.ColorRole.WindowText, SHARED.theme.colText)
2941
2921
  palette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
2942
-
2943
2922
  self.setPalette(palette)
2944
- self.itemTitle.setPalette(palette)
2923
+ self.itemTitle.setTextColors(
2924
+ color=palette.windowText().color(), faded=SHARED.theme.fadedText
2925
+ )
2926
+ return
2945
2927
 
2928
+ def changeFocusState(self, state: bool) -> None:
2929
+ """Toggle focus state."""
2930
+ self.itemTitle.setColorState(state)
2946
2931
  return
2947
2932
 
2948
2933
  def setHandle(self, tHandle: str) -> None:
@@ -3001,15 +2986,13 @@ class GuiDocEditHeader(QWidget):
3001
2986
  self.docEditor.requestProjectItemSelected.emit(self._docHandle or "", True)
3002
2987
  return
3003
2988
 
3004
- # END Class GuiDocEditHeader
3005
-
3006
-
3007
- # =============================================================================================== #
3008
- # The Embedded Document Footer
3009
- # Only used by DocEditor, and is at a fixed position in the QTextEdit's viewport
3010
- # =============================================================================================== #
3011
2989
 
3012
2990
  class GuiDocEditFooter(QWidget):
2991
+ """The Embedded Document Footer
2992
+
2993
+ Only used by DocEditor, and is at a fixed position in the
2994
+ QTextEdit's viewport.
2995
+ """
3013
2996
 
3014
2997
  def __init__(self, parent: QWidget) -> None:
3015
2998
  super().__init__(parent=parent)
@@ -3164,7 +3147,7 @@ class GuiDocEditFooter(QWidget):
3164
3147
  sText = ""
3165
3148
  else:
3166
3149
  iPx = round(0.9*SHARED.theme.baseIconHeight)
3167
- status, icon = self._tItem.getImportStatus(incIcon=True)
3150
+ status, icon = self._tItem.getImportStatus()
3168
3151
  sIcon = icon.pixmap(iPx, iPx)
3169
3152
  sText = f"{status} / {self._tItem.describeMe()}"
3170
3153
 
@@ -3195,5 +3178,3 @@ class GuiDocEditFooter(QWidget):
3195
3178
  wText = self._trWordCount.format("0", "+0")
3196
3179
  self.wordsText.setText(wText)
3197
3180
  return
3198
-
3199
- # END Class GuiDocEditFooter